all repos — litestore @ 9210fa51fc9e620d5e71408e3708f92b59dfeb28

A minimalist nosql document store.

server.nim

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
import asynchttpserver, asyncdispatch, times, strutils, pegs, strtabs
import types, api

proc getReqInfo(req: Request): string =
  return $getLocalTime(getTime()) & " - " & req.hostname & " " & req.reqMethod & " " & req.url.path

proc handleCtrlC() {.noconv.} =
  echo "\nExiting..."
  quit()

proc rDocs(path: string, matches: var seq[string]): bool =
  return path.find(peg"""^\/? {(.*)}""", matches) != -1

proc optionsRoutes(req: Request, LS: LiteStore): Response =
  var matches = @[""]
  if req.url.path.rDocs(matches):
    if matches[0] != "":
      result.code = Http200
      result.content = ""
      result.headers = {"Allow": "HEAD,GET,PUT,PATCH,DELETE"}.newStringTable
    else:
      result.code = Http200
      result.content = ""
      result.headers = {"Allow": "HEAD,GET,POST,DELETE"}.newStringTable
  else:
    return resError(Http400, "Bad request: $1" % req.url.path) 

proc headRoutes(req: Request, LS: LiteStore): Response =
  var matches = @[""]
  var options = newQueryOptions()
  options.select = "id, content_type, binary, searchable, created, modified"
  if req.url.path.rDocs(matches):
    if matches[0] != "":
      # Retrieve a single document
      return LS.getRawDocument(matches[0], options)
    else:
      # Retrieve a multiple documents
      return LS.getRawDocuments(options)
  else:
    return resError(Http400, "Bad request: $1" % req.url.path) 

proc getRoutes(req: Request, LS: LiteStore): Response =
  var matches = @[""]
  if req.url.path.rDocs(matches):
    if matches[0] != "":
      # Retrieve a single document
      if req.url.query.contains("raw=true") or req.headers["Content-Type"] == "application/json":
        return LS.getRawDocument(matches[0])
      else:
        return LS.getDocument(matches[0])
    else:
      # Retrieve a multiple documents
      return LS.getRawDocuments()
  else:
    return resError(Http400, "Bad request: $1" % req.url.path) 

proc route(req: Request, LS: LiteStore): Response =
  case req.reqMethod:
    of "HEAD":
      return req.headRoutes(LS)
    of "OPTIONS":
      return req.optionsRoutes(LS)
    of "GET":
      return req.getRoutes(LS)
    else:
      return resError(Http501, "Method $1 not implemented" % req.reqMethod) 

setControlCHook(handleCtrlC)

proc serve*(LS: LiteStore) =
  var server = newAsyncHttpServer()
  proc handleHttpRequest(req: Request): Future[void] {.async.} =
    echo getReqInfo(req)
    let res = req.route(LS)
    await req.respond(res.code, res.content, res.headers)
  echo LS.appname, " v", LS.appversion, " started on ", LS.address, ":", LS.port, "." 
  asyncCheck server.serve(LS.port.Port, handleHttpRequest, LS.address)