Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
185 lines (154 sloc) 4.83 KB
import uri, cgi, tables, logging, strutils, re, options
import jester/private/utils
when useHttpBeast:
import httpbeast except Settings
import options, httpcore
type
NativeRequest* = httpbeast.Request
else:
import asynchttpserver
type
NativeRequest* = asynchttpserver.Request
type
Request* = object
req: NativeRequest
patternParams: Option[Table[string, string]]
reMatches: array[MaxSubpatterns, string]
settings*: Settings
proc body*(req: Request): string =
## Body of the request, only for POST.
##
## You're probably looking for ``formData``
## instead.
when useHttpBeast:
req.req.body.get("")
else:
req.req.body
proc headers*(req: Request): HttpHeaders =
## Headers received with the request.
## Retrieving these is case insensitive.
when useHttpBeast:
if req.req.headers.isNone:
newHttpHeaders()
else:
req.req.headers.get()
else:
req.req.headers
proc path*(req: Request): string =
## Path of request without the query string.
when useHttpBeast:
let p = req.req.path.get("")
let queryStart = p.find('?')
if unlikely(queryStart != -1):
return p[0 .. queryStart-1]
else:
return p
else:
let u = req.req.url
return u.path
proc reqMethod*(req: Request): HttpMethod =
## Request method, eg. HttpGet, HttpPost
when useHttpBeast:
req.req.httpMethod.get()
else:
req.req.reqMethod
proc reqMeth*(req: Request): HttpMethod {.deprecated.} =
req.reqMethod
proc ip*(req: Request): string =
## IP address of the requesting client.
when useHttpBeast:
result = req.req.ip
else:
result = req.req.hostname
let headers = req.headers
if headers.hasKey("REMOTE_ADDR"):
result = headers["REMOTE_ADDR"]
if headers.hasKey("x-forwarded-for"):
result = headers["x-forwarded-for"]
proc params*(req: Request): Table[string, string] =
## Parameters from the pattern and the query string.
if req.patternParams.isSome():
result = req.patternParams.get()
else:
result = initTable[string, string]()
when useHttpBeast:
let query = req.req.path.get("").parseUri().query
else:
let query = req.req.url.query
try:
for key, val in cgi.decodeData(query):
result[key] = val
except CgiError:
logging.warn("Incorrect query. Got: $1" % [query])
let contentType = req.headers.getOrDefault("Content-Type")
if contentType.startswith("application/x-www-form-urlencoded"):
try:
parseUrlQuery(req.body, result)
except:
logging.warn("Could not parse URL query.")
proc formData*(req: Request): MultiData =
let contentType = req.headers.getOrDefault("Content-Type")
if contentType.startsWith("multipart/form-data"):
result = parseMPFD(contentType, req.body)
proc matches*(req: Request): array[MaxSubpatterns, string] =
req.reMatches
proc secure*(req: Request): bool =
if req.headers.hasKey("x-forwarded-proto"):
let proto = req.headers["x-forwarded-proto"]
case proto.toLowerAscii()
of "https":
result = true
of "http":
result = false
else:
logging.warn("Unknown x-forwarded-proto ", proto)
proc port*(req: Request): int =
if (let p = req.headers.getOrDefault("SERVER_PORT"); p != ""):
result = p.parseInt
else:
result = if req.secure: 443 else: 80
proc host*(req: Request): string =
req.headers.getOrDefault("HOST")
proc appName*(req: Request): string =
## This is set by the user in ``run``, it is
## overriden by the "SCRIPT_NAME" scgi
## parameter.
req.settings.appName
proc stripAppName(path, appName: string): string =
result = path
if appname.len > 0:
var slashAppName = appName
if slashAppName[0] != '/' and path[0] == '/':
slashAppName = '/' & slashAppName
if path.startsWith(slashAppName):
if slashAppName.len() == path.len:
return "/"
else:
return path[slashAppName.len .. path.len-1]
else:
raise newException(ValueError,
"Expected script name at beginning of path. Got path: " &
path & " script name: " & slashAppName)
proc pathInfo*(req: Request): string =
## This is ``.path`` without ``.appName``.
req.path.stripAppName(req.appName)
# TODO: Can cookie keys be duplicated?
proc cookies*(req: Request): Table[string, string] =
## Cookies from the browser.
if (let cookie = req.headers.getOrDefault("Cookie"); cookie != ""):
result = parseCookies(cookie)
else:
result = initTable[string, string]()
#[ Protected procs ]#
proc initRequest*(req: NativeRequest, settings: Settings): Request {.inline.} =
Request(
req: req,
settings: settings
)
proc getNativeReq*(req: Request): NativeRequest =
req.req
#[ Only to be used by our route macro. ]#
proc setPatternParams*(req: var Request, p: Table[string, string]) =
req.patternParams = some(p)
proc setReMatches*(req: var Request, r: array[MaxSubpatterns, string]) =
req.reMatches = r
You can’t perform that action at this time.