Add apiutils.
This commit is contained in:
parent
3777e3dbbd
commit
4e0d06bb67
@ -1,7 +1,5 @@
|
|||||||
# This is just an example to get you started. A typical library package
|
import buffoonery/apierror,
|
||||||
# exports the main API in this file. Note that you cannot rename this file
|
buffoonery/apiutils,
|
||||||
# but you can remove it if you wish.
|
buffoonery/auth,
|
||||||
|
buffoonery/jsonutils
|
||||||
proc add*(x, y: int): int =
|
export apierror, apiutils, auth, jsonutils
|
||||||
## Adds two files together.
|
|
||||||
return x + y
|
|
||||||
|
96
src/buffoonery/apiutils.nim
Normal file
96
src/buffoonery/apiutils.nim
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import std/json, std/logging, std/strutils, std/sequtils
|
||||||
|
import jester, namespaced_logging
|
||||||
|
|
||||||
|
import ./apierror
|
||||||
|
|
||||||
|
const CONTENT_TYPE_JSON* = "application/json"
|
||||||
|
|
||||||
|
var logNs {.threadvar.}: LoggingNamespace
|
||||||
|
|
||||||
|
template log(): untyped =
|
||||||
|
if logNs.isNil: logNs = initLoggingNamespace("buffoonery/apiutils", lvlDebug)
|
||||||
|
logNs
|
||||||
|
|
||||||
|
## Response Utilities
|
||||||
|
template halt*(
|
||||||
|
code: HttpCode,
|
||||||
|
headers: RawHeaders,
|
||||||
|
content: string) =
|
||||||
|
## Immediately replies with the specified request. This means any further
|
||||||
|
## code will not be executed after calling this template in the current
|
||||||
|
## route.
|
||||||
|
bind TCActionSend, newHttpHeaders
|
||||||
|
result[0] = CallbackAction.TCActionSend
|
||||||
|
result[1] = code
|
||||||
|
result[2] = if isSome(result[2]): some(result[2].get & headers)
|
||||||
|
else: some(headers)
|
||||||
|
result[3] = content
|
||||||
|
result.matched = true
|
||||||
|
break allRoutes
|
||||||
|
|
||||||
|
template sendJsonResp*(
|
||||||
|
code: HttpCode,
|
||||||
|
body: string = "",
|
||||||
|
knownOrigins: seq[string],
|
||||||
|
headersToSend: RawHeaders) =
|
||||||
|
## Immediately send a JSON response and stop processing the request.
|
||||||
|
let reqOrigin =
|
||||||
|
if headers(request).hasKey("Origin"): $(headers(request)["Origin"])
|
||||||
|
else: ""
|
||||||
|
|
||||||
|
let corsHeaders =
|
||||||
|
if knownOrigins.contains(reqOrigin):
|
||||||
|
@{
|
||||||
|
"Access-Control-Allow-Origin": reqOrigin,
|
||||||
|
"Access-Control-Allow-Credentials": "true",
|
||||||
|
"Access-Control-Allow-Methods": $(reqMethod(request)),
|
||||||
|
"Access-Control-Allow-Headers": "Authorization,X-CSRF-TOKEN"
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
log().warn "Unrecognized Origin '" & reqOrigin & "', excluding CORS headers."
|
||||||
|
@{:}
|
||||||
|
|
||||||
|
halt(
|
||||||
|
code,
|
||||||
|
cast[RawHeaders](headersToSend) & corsHeaders & @{
|
||||||
|
"Content-Type": CONTENT_TYPE_JSON,
|
||||||
|
"Cache-Control": "no-cache"
|
||||||
|
},
|
||||||
|
body
|
||||||
|
)
|
||||||
|
|
||||||
|
proc makeDataBody*(data: JsonNode): string = $(%*{"details":"","data":data })
|
||||||
|
proc makeStatusBody*(details: string): string = $(%*{"details":details})
|
||||||
|
|
||||||
|
template sendErrorResp*(err: ref ApiError, knownOrigins: seq[string]): void =
|
||||||
|
log().debug err.respMsg & ( if err.msg.len > 0: ": " & err.msg else: "")
|
||||||
|
if not err.parent.isNil: log().debug " original exception: " & err.parent.msg
|
||||||
|
sendJsonResp(err.respCode, makeStatusBody(err.respMsg), knownOrigins, @{:})
|
||||||
|
|
||||||
|
## CORS support
|
||||||
|
template sendOptionsResp*(
|
||||||
|
allowedMethods: seq[HttpMethod],
|
||||||
|
knownOrigins: seq[string]) =
|
||||||
|
|
||||||
|
let reqOrigin =
|
||||||
|
if headers(request).hasKey("Origin"): $(headers(request)["Origin"])
|
||||||
|
else: ""
|
||||||
|
|
||||||
|
let corsHeaders =
|
||||||
|
if knownOrigins.contains(reqOrigin):
|
||||||
|
@{
|
||||||
|
"Access-Control-Allow-Origin": reqOrigin,
|
||||||
|
"Access-Control-Allow-Credentials": "true",
|
||||||
|
"Access-Control-Allow-Methods": allowedMethods.mapIt($it).join(", "),
|
||||||
|
"Access-Control-Allow-Headers": "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-CSRF-TOKEN"
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
log().warn "Unrecognized Origin '" & reqOrigin & "', excluding CORS headers."
|
||||||
|
log().debug "Valid origins: " & knownOrigins.join(", ")
|
||||||
|
@{:}
|
||||||
|
|
||||||
|
halt(
|
||||||
|
Http200,
|
||||||
|
corsHeaders,
|
||||||
|
""
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user