Hi! I've been trying to figure it out scavenging the depths of internet, but am unable to it seems. Basically what I'm doing is taking the asynchttpserver example and modifying it to be able to have a basic routing system, with all of the code looking like this:
import std/asynchttpserver
import std/asyncdispatch
type
GET = object
path: string
callback: proc (req: Request) {.async.}
type
POST = object
path: string
callback: proc (req: Request) {.async.}
var routes: seq[GET|POST] = @[
GET(path: "/", callback: proc (req: Request) {.async.} =
let headers = {"Content-Type": "text/plain; charset=utf-8"}
await req.respond(Http200, "Hello, world!", headers.newHttpHeaders())
),
]
proc router(req: Request, routes: seq[GET|POST]) {.async.} =
var foundRoute: proc(req: Request) {.async.}
for route in routes:
if req.url.path == route.path:
foundRoute = route.callback
break
await foundRoute(req)
proc main {.async.} =
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
await router(req, routes)
server.listen(Port(8080))
while true:
if server.shouldAcceptRequest():
await server.acceptRequest(cb)
else:
await sleepAsync(1000)
waitFor main()
But for some reason in the server.acceptRequest(cb) line I get a error saying there's a type mismatch:
Expression: acceptRequest(server, cb)
[1] server: AsyncHttpServer
[2] cb: proc (req: Request): Future[system.void]
Expected one of (first mismatch at [position]):
[2] proc acceptRequest(server: AsyncHttpServer; callback: proc (request: Request): Future[
void] {.closure, gcsafe.}): owned(Future[void])
But they are both, from what I can see, Future[void], so I'm not really sure why this is happening. Any help is appreciated!
{.closure, gcsafe.}
That is the part that doesn't match. It's not required, but you can add gcsafe to your callback pragma: {.async, gcsafe.}, and then the real error message should appear when you try to compile:
../nim/lib/pure/asyncmacro.nim(250, 31) Error: 'cb (Async)' is not GC-safe as it accesses 'routes' which is a global using GC'ed memory
Oh that's it! Thank you very much!
So what I had to do to solve my issue was to make the routes be a const instead of a var and then I needed to add gcsafe pragma to all the async ones, and it started compiling and working well.
Since your object types are identical this one will do:
type
RouteKind = enum Post, Get
Route = object
kind: RouteKind
path: string
callback: proc (req: Request) {.async.}