I am trying to write a small DSL to define HTTP routes, much like Spray for Scala.
The building blocks to be combined are
type Handler = proc(req: Request): Future[bool]
which are functions that take a request and
These can be combined either one inside the other (think first filtering by method and then by path) or one along the other (think rejecting a path, then trying next one).
The designed will need to be expanded, but this is not the point. The problem I have is that I am not able to make those runnable from an AsyncHttpServer. The error I get is
web.nim(50, 15) Error: type mismatch: got (AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.closure.})
but expected one of:
asynchttpserver.serve(server: AsyncHttpServer, port: Port, callback: proc (request: Request): Future[system.void]{.closure, gcsafe.}, address: string)
Apparently the only difference between what I pass and what I get is (address has a default) that the callback has a {.gcsafe.} pragma. What can I do to guarantee this? For completeness, here is the full code:
import asynchttpserver, asyncdispatch, strtabs
proc ok(req: Request, s: string) {.async.} =
await req.respond(Http200, s, {"Content-Type": "text/plain;charset=utf-8"}.newStringTable)
proc notFound(req: Request, s: string) {.async.} =
await req.respond(Http404, s, {"Content-Type": "text/plain;charset=utf-8"}.newStringTable)
type Handler = proc(req: Request): Future[bool]
proc handle(h: Handler): proc(req: Request): Future[void] =
proc server(req: Request): Future[void] {.async.} =
let done = await h(req)
if not done:
await req.notFound("Not found")
return server
proc `~`(h1, h2: Handler): Handler =
proc h3(req: Request): Future[bool] {.async.} =
return (await h1(req)) or (await h2(req))
return h3
proc `->`(h1, h2: Handler): Handler =
proc h3(req: Request): Future[bool] {.async.} =
return (await h1(req)) and (await h2(req))
return h3
proc ok(s: string): Handler =
proc h(req: Request): Future[bool] {.async.} =
await req.ok(s)
return true
return h
proc path(s: string): Handler =
proc h(req: Request): Future[bool] {.async.} =
return req.url.path == s
return h
let handler =
(path("/hello") -> ok("Hello, world")) ~
(path("/goodnight") -> ok("Goodnight, moon"))
let server = newAsyncHttpServer()
waitFor server.serve(Port(8080), handle(handler))
Having handle automatically derive its return type seems to fix this:
proc handle(h: Handler): auto =