Skip to content

Instantly share code, notes, and snippets.

@mashingan
Created December 23, 2017 15:03
Show Gist options
  • Save mashingan/957137458dbe360a688495b357f343fd to your computer and use it in GitHub Desktop.
Save mashingan/957137458dbe360a688495b357f343fd to your computer and use it in GitHub Desktop.
Basic REST with nest
##
## Example of Nest that tracks how long routing takes
##
import nest
import logging
import asynchttpserver, strtabs, times, asyncdispatch, math
import httpcore
type
RequestHandler* = proc (
req: Request,
headers : var HttpHeaders,
args : RoutingArgs
) : string {.gcsafe.}
#
# Initialization
#
var logger = newConsoleLogger()
let server = newAsyncHttpServer()
logger.log(lvlInfo, "****** Created server on ", getTime(), " ******")
#
# Set up mappings
#
var mapper = newRouter[RequestHandler]()
proc rootHandler(req: Request, headers: var HttpHeaders, args: RoutingArgs):
string {.gcsafe, procvar.} =
"You visited " & req.url.path
proc paramHandler(req: Request, headers: var HttpHeaders, args: RoutingArgs):
string {.gcsafe, procvar.} =
let id = args.pathArgs["id"]
echo "the id is ", id
"You visited " & req.url.path & " with id " & id
proc queryHandler(req: Request, headers: var HttpHeaders, args: RoutingArgs):
string {.gcsafe, procvar.} =
echo "The query given is ", args.queryArgs
"You visited " & req.url.path & " with query " & $args.queryArgs
proc patternHandler(req: Request, headers: var HttpHeaders, args: RoutingArgs):
string {.gcsafe, procvar.} =
"You visited " & req.url.path
mapper.map(rootHandler, $GET, "/")
mapper.map(paramHandler, $GET, "/param/{id}/ok")
mapper.map(queryHandler, $GET, "/query")
mapper.map(patternHandler, $GET, "/pattern/*/nice")
mapper.compress()
#
# Set up the dispatcher
#
# NOTE: these only use unsafe pointers to work with asynchttpserver, which requires full gcsafety in thread mode
let routerPtr = addr mapper
let loggerPtr = addr logger
proc dispatch(req: Request) {.async, gcsafe.} =
##
## Figures out what handler to call, and calls it
##
let startT = epochTime()
let matchingResult = routerPtr[].route(req.reqMethod, req.url, req.headers)
let endT = epochTime()
loggerPtr[].log(lvlDebug, "Routing took ", ((endT - startT) * 1000000), " microseconds")
if matchingResult.status == routingFailure:
await req.respond(Http404, "Resource not found")
else:
var
statusCode : HttpCode
headers = newHttpHeaders()
content : string
try:
content = matchingResult.handler(req, headers, matchingResult.arguments)
statusCode = Http200
except:
loggerPtr[].log(lvlError, "Internal error occured:\n\t", getCurrentExceptionMsg())
content = "Internal server error"
statusCode = Http500
await req.respond(statusCode, content, headers)
# start up the server
logger.log(lvlInfo, "****** Started server on ", getTime(), " ******")
waitFor server.serve(Port(3000), dispatch)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment