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
;;
}