all repos — litestore @ efb742ad373069beee01773e0cd72baa66e99a86

A minimalist nosql document store.

Improved routing.
h3rald h3rald@h3rald.com
Sat, 11 Apr 2015 12:11:58 +0200
commit

efb742ad373069beee01773e0cd72baa66e99a86

parent

284ede3eb68ba64f4350a3c2c2f9812c1b8d0860

2 files changed, 47 insertions(+), 30 deletions(-)

jump to
M lib/server.nimlib/server.nim

@@ -14,37 +14,50 @@ echo ""

info("Exiting...") quit() -proc parseApiUrl(req: Request): ResourceInfo = - var matches = @["", "", ""] - if req.url.path.find(PEG_URL, matches) != -1: - result.version = matches[0] - result.resource = matches[1] - result.id = matches[2] +proc processApiUrl(req: Request, LS: LiteStore, info: ResourceInfo): Response = + if info.version == "v1" and info.resource.match(peg"^docs / info$"): + return api_v1.route(req, LS, info.resource, info.id) else: - raise newException(EInvalidRequest, req.getReqInfo()) + if info.version != "v1": + return resError(Http400, "Bad request - Invalid API version: $1" % info.version) + else: + if info.resource.decodeURL.strip == "": + return resError(Http400, "Bad request - No resource specified" % info.resource) + else: + return resError(Http400, "Bad request - Invalid resource: $1" % info.resource) -proc route(req: Request, LS: LiteStore): Response = - if req.url.path == "/favicon.ico": - result.code = Http200 - result.content = LS.favicon - result.headers = {"Content-Type": "image/x-icon"}.newStringTable - return result - try: - var info = req.parseApiUrl - if info.version == "docs" or info.version == "info": + +proc process(req: Request, LS: LiteStore): Response = + var matches = @["", "", ""] + template route(req, peg: expr, op: stmt): stmt {.immediate.}= + if req.url.path.find(peg, matches) != -1: + op + try: + var info: ResourceInfo = (version: "", resource: "", id: "") + req.route peg"^\/?$": + info.version = "v1" + info.resource = "info" + return req.processApiUrl(LS, info) + req.route peg"^\/favicon.ico$": + result.code = Http200 + result.content = LS.favicon + result.headers = {"Content-Type": "image/x-icon"}.newStringTable + return result + req.route PEG_DEFAULT_URL: info.version = "v1" - info.id = info.resource - info.resource = "docs" - if info.version == "v1" and info.resource.match(peg"^docs / info$"): - return api_v1.route(req, LS, info.resource, info.id) - else: - if info.version != "v1": - return resError(Http400, "Bad request - Invalid API version: $1" % info.version) - else: - if info.resource.decodeURL.strip == "": - return resError(Http400, "Bad request - No resource specified" % info.resource) - else: - return resError(Http400, "Bad request - Invalid resource: $1" % info.resource) + info.resource = matches[0] + info.id = matches[1] + return req.processApiUrl(LS, info) + req.route PEG_URL: + info.version = matches[0] + info.resource = matches[1] + info.id = matches[2] + return req.processApiUrl(LS, info) + raise newException(EInvalidRequest, req.getReqInfo()) + except EInvalidRequest: + let e = (ref EInvalidRequest)(getCurrentException()) + let trace = e.getStackTrace() + return resError(Http400, "Bad Request: $1" % getCurrentExceptionMsg(), trace) except: let e = getCurrentException() let trace = e.getStackTrace()

@@ -56,7 +69,7 @@ proc serve*(LS: LiteStore) =

var server = newAsyncHttpServer() proc handleHttpRequest(req: Request): Future[void] {.async.} = info(getReqInfo(req).replace("$", "$$")) - let res = req.route(LS) + let res = req.process(LS) await req.respond(res.code, res.content, res.headers) info(LS.appname & " v" & LS.appversion & " started on " & LS.address & ":" & $LS.port & ".") if LS.mount:
M lib/types.nimlib/types.nim

@@ -59,8 +59,12 @@ let PEG_USER_TAG* = peg"""

^[a-zA-Z0-9_\-?~:.@#^!+]+$ """ +let PEG_DEFAULT_URL* = peg""" + ^\/{(docs / info)} (\/ {(.+)} / \/?)$ +""" + let PEG_URL* = peg""" - ^\/({(v\d+)} \/)? {([^\/]+)} (\/ {(.+)} / \/?)$ + ^\/({(v\d+)} \/) {([^\/]+)} (\/ {(.+)} / \/?)$ """ const