ref: f37c8970f11e21b0b6f29c4aac10f92101d0c906
dir: /lib/http/server.myr/
use bio use std use thread use "types" use "session" use "parse" pkg http = const announce : (ds : byte[:] -> std.result(server#, err)) const shutdown : (srv : server# -> void) const serve : (srv : server# -> void) ;; const announce = {ds var afd match std.announce(ds) | `std.Ok f: afd = f | `std.Err e: -> `std.Err `Econn ;; match std.listen(afd) | `std.Err e: -> `std.Err `Econn | `std.Ok lfd: std.close(afd) -> `std.Ok std.mk([.lfd=lfd]) ;; } const serve = {srv while true match waitconn(srv) | `std.Ok fd: thread.spawn({;communicate(srv, fd)}) | `std.Err e: /* eh? */ ;; ;; } const communicate = {srv, fd var s s = mksrvsession(fd) while !srv.quit match parsereq(s) | `std.Ok req: dispatch(srv, s, req) | `std.Err e: break ;; ;; std.close(fd) } const dispatch = {srv, sess, req var resp : resp# resp = std.mk([ .status=200, .hdrs = [][:], .len = 0, .err = `std.None, .reason = "", .body = "pong\n", .enc = `Length ]) respond(srv, sess, resp) } const respond = {srv, s, resp var sb sb = std.mksb() bio.put(s.f, "HTTP/1.1 {} {}\r\n", resp.status, statusstr(resp.status)) bio.put(s.f, "Content-Length: {}\r\n", resp.body.len) bio.put(s.f, "Encoding: {}\r\n", resp.enc) for (k, v) in resp.hdrs bio.put(s.f, "{}: {}\r\n", k, v) ;; bio.put(s.f, "\r\n") bio.write(s.f, resp.body) bio.flush(s.f) } const statusstr = {st match st | 200: -> "OK" | 404: -> "Not Found" | 503: -> "Internal Error" | _: -> "Bad State" ;; } const shutdown = {srv std.close(srv.lfd) } const waitconn = {srv match std.accept(srv.lfd) | `std.Ok fd: -> `std.Ok fd | `std.Err e: -> `std.Err `Econn ;; }