all repos — litestore @ c8eb2c121c366045a17bda258b3e14bc8ace8b62

A minimalist nosql document store.

Implemented local directory web server.
* Closes #33.
h3rald h3rald@h3rald.com
Sat, 28 Nov 2015 12:17:06 +0100
commit

c8eb2c121c366045a17bda258b3e14bc8ace8b62

parent

094f3b9bdf681b94b6bca11bdce28a79d18f92e2

7 files changed, 40 insertions(+), 14 deletions(-)

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

@@ -14,7 +14,7 @@ var

operation = opRun directory:string = nil readonly = false - logLevel = "info" + logLevel = "warn" mount = false let

@@ -34,7 +34,7 @@ vacuum Vacuum datastore.

Options: -a, --address Specify server address (default: 127.0.0.1). - -d, --directory Specify a directory to import, export, delete, or mount. + -d, --directory Specify a directory to serve, import, export, delete, or mount. -h, --help Display this message. -l, --log Specify the log level: debug, info, warn, error, none (default: info) -m, --mount Mirror database changes to the specified directory on the filesystem.
M lib/contenttypes.nimlib/contenttypes.nim

@@ -7,9 +7,11 @@ const raw_json = "lib/contenttypes.json".slurp

let json = raw_json.parseJson for item in json.items: for pair in item.pairs: - result[$pair.key] = $pair.val + result[$pair.key] = $pair.val.getStr -let CONTENT_TYPES* = loadContentTypes() +var CONTENT_TYPES* {.threadvar.}: StringTableRef + +CONTENT_TYPES = loadContentTypes() proc isBinary*(ct: string): bool = if ct.endsWith "xml":
M lib/core.nimlib/core.nim

@@ -294,7 +294,7 @@ var d_id = f.replace("\\", "/")

var d_contents = f.readFile var d_ct = "application/octet-stream" if CONTENT_TYPES.hasKey(ext): - d_ct = CONTENT_TYPES[ext].replace("\"", "") + d_ct = CONTENT_TYPES[ext].getStr var d_binary = 0 var d_searchable = 1 if d_ct.isBinary:
M lib/logger.nimlib/logger.nim

@@ -36,4 +36,4 @@ logger.msg(" DEBUG", message, params)

var LOG* {.threadvar.}: Logger -LOG.level = lvInfo +LOG.level = lvWarn
M lib/server.nimlib/server.nim

@@ -6,9 +6,11 @@ strutils,

pegs, strtabs, logger, - cgi + cgi, + os import types, + contenttypes, utils, api_v1

@@ -25,15 +27,37 @@ echo ""

LOG.info("Exiting...") quit() +proc serveFile(req: Request, LS: LiteStore, id: string): Response = + let path = LS.directory / id + if path.fileExists: + try: + let contents = path.readFile + let parts = path.splitFile + if CONTENT_TYPES.hasKey(parts.ext): + result.headers = CONTENT_TYPES[parts.ext].ctHeader + else: + result.headers = ctHeader("text/plain") + result.content = contents + result.code = Http200 + except: + return resError(Http500, "Unable to read file '$1'." % path) + else: + return resError(Http404, "File '$1' not found." % path) + 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) + elif info.version == "v1" and info.resource.match(peg"^dir$"): + if LS.directory != nil: + return serveFile(req, LS, info.id) + else: + return resError(Http400, "Bad request - Not serving any directory." % info.version) 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) + return resError(Http400, "Bad request - No resource specified." % info.resource) else: return resError(Http400, "Bad request - Invalid resource: $1" % info.resource)

@@ -52,7 +76,7 @@ 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 + result.headers = ctHeader("image/x-icon") return result req.route PEG_DEFAULT_URL: info.version = "v1"

@@ -82,8 +106,8 @@ proc handleHttpRequest(req: Request): Future[void] {.async, gcsafe, closure.} =

LOG.info(getReqInfo(req).replace("$", "$$")) let res = req.process(LS) await req.respond(res.code, res.content, res.headers) - LOG.info(LS.appname & " v" & LS.appversion & " started on " & LS.address & ":" & $LS.port & ".") + echo(LS.appname & " v" & LS.appversion & " started on " & LS.address & ":" & $LS.port & ".") if LS.mount: - LOG.info("Mirroring datastore changes to: " & LS.directory) + echo("Mirroring datastore changes to: " & LS.directory) asyncCheck server.serve(LS.port.Port, handleHttpRequest, LS.address)
M lib/types.nimlib/types.nim

@@ -79,7 +79,7 @@ PEG_URL* {.threadvar.}: Peg

PEG_TAG = peg"""^\$? [a-zA-Z0-9_\-?~:.@#^!+]+$""" PEG_USER_TAG = peg"""^[a-zA-Z0-9_\-?~:.@#^!+]+$""" -PEG_DEFAULT_URL = peg"""^\/{(docs / info)} (\/ {(.+)} / \/?)$""" +PEG_DEFAULT_URL = peg"""^\/{(docs / info / dir)} (\/ {(.+)} / \/?)$""" PEG_URL = peg"""^\/({(v\d+)} \/) {([^\/]+)} (\/ {(.+)} / \/?)$""" # Initialize LiteStore
M litestore.nimblelitestore.nimble

@@ -1,10 +1,10 @@

[Package] name = "litestore" -version = "1.0.2" +version = "1.0.3" author = "Fabio Cevasco" description = "Self-contained, lightweight, RESTful document store." license = "MIT" bin = "litestore" [Deps] -requires: "nimrod >= 0.11.2" +requires: "nimrod >= 0.12.0"