-
-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathresponse.nim
143 lines (112 loc) · 5.55 KB
/
response.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import std/[times, json, strformat, options, macros]
import ./httpcore/httplogue
import pkg/cookiejar
type
Response* = object ## Response object.
httpVersion*: HttpVersion
code*: HttpCode
headers*: ResponseHeaders
body*: string
func `$`*(response: Response): string =
## Gets the string form of `Response`.
fmt"{response.code} {response.headers}"
func initResponse*(httpVersion: HttpVersion, code: HttpCode, headers =
{"Content-Type": "text/html; charset=UTF-8"}.initResponseHeaders,
body = ""): Response {.inline.} =
## Initializes a response.
Response(httpVersion: httpVersion, code: code, headers: headers, body: body)
func initResponse*(httpVersion: HttpVersion, code: HttpCode,
headers: openArray[(string, string)],
body = ""): Response {.inline.} =
## Initializes a response.
Response(httpVersion: httpVersion, code: code,
headers: headers.initResponseHeaders, body: body)
template hasHeader*(response: Response, key: string): bool =
## Returns true if key is in the `response`.
response.headers.hasKey(key)
template getHeader*(response: Response, key: string): seq[string] =
## Retrieves value of `response.headers[key]`.
response.headers[key]
template getHeaderOrDefault*(response: Response, key: string, default = @[""]): seq[string] =
## Retrieves value of `response.headers[key]`. Otherwise `default` will be returned.
response.headers.getOrDefault(key, default)
template setHeader*(response: var Response, key, value: string) =
## Sets the header values of the response.
response.headers[key] = value
template setHeader*(response: var Response, key: string, value: seq[string]) =
## Sets the header values of the response.
response.headers[key] = value
template addHeader*(response: var Response, key, value: string) =
## Adds header values to the existing `HttpHeaders`.
response.headers.add(key, value)
template setCookie*(response: var Response, key, value: string, expires = "",
maxAge: Option[int] = none(int), domain = "", path = "", secure = false,
httpOnly = false, sameSite = Lax) =
## Sets the cookie of response.
let cookies = initCookie(key, value, expires, maxAge, domain,
path, secure, httpOnly, sameSite)
response.addHeader("Set-Cookie", $cookies)
template setCookie*(response: var Response, key, value: string, expires: DateTime|Time,
maxAge: Option[int] = none(int), domain = "",
path = "", secure = false, httpOnly = false, sameSite = Lax) =
## Sets the cookie of response.
let cookies = initCookie(key, value, expires, maxAge, domain,
path, secure, httpOnly, sameSite)
response.addHeader("Set-Cookie", $cookies)
template deleteCookie*(response: var Response, key: string, value = "", path = "",
domain = "") =
## Deletes the cookie of the response.
response.setCookie(key, value, expires = secondsForward(0), maxAge = some(0),
path = path, domain = domain)
func abort*(code = Http401, body = "", headers = initResponseHeaders(),
version = HttpVer11): Response {.inline.} =
## Returns the response with Http401 code(do not raise exception).
result = initResponse(version, code = code, body = body,
headers = headers)
func redirect*(url: string, code = Http301,
body = "", delay = 0, headers = initResponseHeaders(),
version = HttpVer11): Response {.inline.} =
## Redirects to new url.
result = initResponse(version, code = code, headers = headers, body = body)
if delay == 0:
result.headers.add("Location", url)
else:
result.headers.add("refresh", &"{delay};url=\"{url}\"")
func error404*(code = Http404,
body = "<h1>404 Not Found!</h1>", headers = initResponseHeaders(),
version = HttpVer11): Response {.inline.} =
## Creates an error 404 response.
result = initResponse(version, code = code, body = body, headers = headers)
func htmlResponse*(text: string, code = Http200, headers = initResponseHeaders(),
version = HttpVer11): Response {.inline.} =
## Content-Type: text/html; charset=UTF-8.
result = initResponse(version, code, headers, body = text)
result.headers["Content-Type"] = "text/html; charset=UTF-8"
func plainTextResponse*(text: string, code = Http200,
headers = initResponseHeaders(), version = HttpVer11): Response {.inline.} =
## Content-Type: text/plain.
result = initResponse(version, code, headers, body = text)
result.headers["Content-Type"] = "text/plain"
func jsonResponse*(text: JsonNode, code = Http200, headers = initResponseHeaders(),
version = HttpVer11): Response {.inline.} =
## Content-Type: application/json.
result = initResponse(version, code, headers, body = $text)
result.headers["Content-Type"] = "application/json"
macro respDefault*(code: HttpCode) =
## Uses default error handler registered in the error handler table if existing.
var ctx = ident"ctx"
result = quote do:
`ctx`.response.code = `code`
`ctx`.response.body.setLen(0)
macro resp*(body: string, code = Http200, version = HttpVer11) =
## Handy to make a response of ctx.
var ctx = ident"ctx"
result = quote do:
`ctx`.response.httpVersion = `version`
`ctx`.response.code = `code`
`ctx`.response.body = `body`
macro resp*(response: Response) =
## Handy to make a response of ctx.
var ctx = ident"ctx"
result = quote do:
`ctx`.response = `response`