1
0
Fork 0
forked from fun/fun
fun/examples/broken/await_http_client.fun

122 lines
2.7 KiB
Standard ML
Executable file

#!/usr/bin/env fun
/*
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-03-29
*/
/*
* Async-style HTTP GET using lib/async/scheduler.fun helpers
*
* This demonstrates building an "await-like" workflow without VM-level
* async/await. We use a cooperative task that advances a small state
* machine each tick, calling await_write/await_read to probe readiness.
*/
#include <async/scheduler.fun>
host = "example.org"
port = 80
// Task state and step function
fun http_get_step(t)
// phases: 0=connect, 1=set nonblock, 2=send, 3=recv, 4=done
if (t.phase == nil)
t.phase = 0
if (t.phase == 0)
t.fd = tcp_connect(host, port)
if (t.fd == 0)
print("connect failed")
t.done = 1
return
t.phase = 1
return
if (t.phase == 1)
ok = fd_set_nonblock(t.fd, 1)
if (ok == 0)
print("failed to set nonblocking")
sock_close(t.fd)
t.done = 1
return
t.req = "GET / HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n"
t.sent = 0
t.phase = 2
return
if (t.phase == 2)
// send request in chunks when writable
if (t.sent < len(t.req))
// short timeout to keep loop responsive
wr = await_write(t.fd, 50)
if (wr < 0)
print("poll write error")
sock_close(t.fd)
t.done = 1
return
if (wr == 0)
// not yet writable; yield to others
return
chunk = substr(t.req, t.sent, len(t.req) - t.sent)
n = sock_send(t.fd, chunk)
if (n < 0)
print("send error")
sock_close(t.fd)
t.done = 1
return
t.sent = t.sent + n
return
// all sent; switch to receive
t.buf = ""
t.phase = 3
return
if (t.phase == 3)
rd = await_read(t.fd, 100)
if (rd < 0)
print("poll read error")
sock_close(t.fd)
t.phase = 4
t.done = 1
return
if (rd == 0)
// try a small read to detect close, else wait more
data = sock_recv(t.fd, 4096)
if (len(data) == 0)
sock_close(t.fd)
t.phase = 4
t.done = 1
return
t.buf = t.buf + data
return
// readable
data = sock_recv(t.fd, 4096)
if (len(data) == 0)
sock_close(t.fd)
t.phase = 4
t.done = 1
return
t.buf = t.buf + data
return
if (t.phase == 4)
// print first 200 chars and finish
print(substr(t.buf, 0, 200))
t.done = 1
return
// Spawn task and run
task = task_spawn(http_get_step, {})
run_until_done()
/*
Expected: prints the beginning of an HTTP response from example.org
*/