ref: 0237d07f7d26800a94ddeb25f82a6c7e66ea14c9
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) : 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
;;
}