Implemented responses to HEAD requests.
h3rald h3rald@h3rald.com
Sun, 25 Jan 2015 18:01:20 +0100
4 files changed,
66 insertions(+),
26 deletions(-)
M
api.nim
→
api.nim
@@ -4,14 +4,14 @@ import types, core
proc resError*(code: HttpCode, message: string): Response = result.code = code - result.content = """{"code": $1, "message":\"$2\"}""" % [$code, message] + result.content = """{"code": $1, "message":"$2"}""" % [($code)[0..2], message] result.headers = CT_JSON.newStringTable proc resDocumentNotFound*(id): Response = resError(Http404, "Document '$1' not found." % id) -proc getRawDocument*(LS: LiteStore, id: string): Response = - let doc = LS.store.retrieveRawDocument(id) +proc getRawDocument*(LS: LiteStore, id: string, options = newQueryOptions()): Response = + let doc = LS.store.retrieveRawDocument(id, options) result.headers = CT_JSON.newStringTable if doc == "": result = resDocumentNotFound(id)@@ -19,8 +19,8 @@ else:
result.content = doc result.code = Http200 -proc getDocument*(LS: LiteStore, id: string): Response = - let doc = LS.store.retrieveDocument(id) +proc getDocument*(LS: LiteStore, id: string, options = newQueryOptions()): Response = + let doc = LS.store.retrieveDocument(id, options) if doc.data == "": result = resDocumentNotFound(id) else:@@ -28,8 +28,8 @@ result.headers = doc.contenttype.ctHeader
result.content = doc.data result.code = Http200 -proc getRawDocuments*(LS: LiteStore): Response = - let docs = LS.store.retrieveRawDocuments() # TODO Implement query options +proc getRawDocuments*(LS: LiteStore, options = newQueryOptions()): Response = + let docs = LS.store.retrieveRawDocuments(options) # TODO Implement query options if docs.len == 0: result = resError(Http404, "No documents found.") else:
M
server.nim
→
server.nim
@@ -10,27 +10,59 @@ echo "\nExiting..."
quit() proc rDocs(path: string, matches: var seq[string]): bool = - return path.find(peg"""^\/docs\/? {(.*)}""", matches) != -1 + return path.find(peg"""^\/? {(.*)}""", matches) != -1 -proc rTags(path: string, matches: var seq[string]): bool = - return path.find(peg"""^\/tags\/? {(.*)}(\/{.*})?""", 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"): + 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": - var matches = @[""] - if req.url.path.rDocs(matches): - if matches[0] != "": - # Retrieve a single document - if req.url.query.contains("raw=true"): - 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) + return req.getRoutes(LS) else: return resError(Http501, "Method $1 not implemented" % req.reqMethod)
M
types.nim
→
types.nim
@@ -12,6 +12,7 @@ Datastore* = object
db*: TDbConn path*: string QueryOptions* = object + select*: string single*:bool limit*: int orderby*: string@@ -47,4 +48,4 @@ proc ctJsonHeader*(): StringTableRef =
return CT_JSON.newStringTable proc newQueryOptions*(): QueryOptions = - return QueryOptions(single: false, limit: 0, orderby: "", tags: "", search: "") + return QueryOptions(select: "*", single: false, limit: 0, orderby: "", tags: "", search: "")
M
utils.nim
→
utils.nim
@@ -32,7 +32,7 @@ clause == "modified ASC" or
clause == "modified DESC" proc prepareSelectDocumentsQuery*(options: QueryOptions): string = - result = "SELECT * " + result = "SELECT " & options.select & " " if options.search.len > 0: result = result & "FROM documents, searchcontents " result = result & "WHERE documents.id = searchcontents.document_id "@@ -65,9 +65,16 @@ var raw_tags = store.db.getAllRows(SQL_SELECT_DOCUMENT_TAGS, doc[0])
var tags = newSeq[JsonNode](0) for tag in raw_tags: tags.add(%($(tag[0]))) - return %[("id", %doc[0]), + if doc.len > 6: + return % [("id", %doc[0]), ("data", %doc[1]), ("created", %doc[5]), + ("modified", %doc[6]), + ("tags", %tags)] + else: + # data was not retrieved + return % [("id", %doc[0]), + ("created", %doc[4]), ("modified", %doc[5]), ("tags", %tags)]