ref: 63a2d3e2f8602665941b3b84560489a1566ca4d6
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#, fn : (srv : server#, s : session#, req : req# -> void) -> void) const respond : (srv : server#, sess : session#, resp : resp# -> 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, fn while true match waitconn(srv) | `std.Ok fd: thread.spawn({;communicate(srv, fd, fn)}) | `std.Err e: /* eh? */ ;; ;; } const communicate = {srv, fd, fn var s s = mksrvsession(fd) while !srv.quit match parsereq(s) | `std.Ok req: fn(srv, s, req) | `std.Err e: break ;; ;; std.close(fd) } 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 ;; }