forked from itsumura-h/nim-basolato
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrouting.nim
185 lines (165 loc) · 5.47 KB
/
routing.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import json, strformat, options, strutils, macros, re
# framework
import
base, response, logger, middleware, resources/errorPage, resources/ddPage,
header
from controller import redirect, render, errorRedirect
# 3rd party
import ./core/core
# framework
export base, response, middleware, redirect, render, errorRedirect
# 3rd party
# export core except redirect, setCookie, resp
export core
template route*(responseArg: Response) =
block:
let response = responseArg
var headers = response.headers
case response.responseType:
of String:
if not headers.hasKey("Content-Type"):
headers.add(("Content-Type", "text/html;charset=utf-8"))
of Json:
if not headers.hasKey("Content-Type"):
headers.add(("Content-Type", "application/json;charset=utf-8"))
response.bodyString = $(response.bodyJson)
of Redirect:
logger($response.status &
&" {request.ip} {request.reqMethod} {request.path}")
headers.add(("Location", response.url))
resp response.status, headers, ""
if response.status == Http200:
logger($response.status &
&" {request.ip} {request.reqMethod} {request.path}")
logger($headers)
elif response.status.is4xx() or response.status.is5xx():
echoErrorMsg($request.params)
echoErrorMsg($response.status &
&" {request.ip} {request.reqMethod} {request.path}")
echoErrorMsg($headers)
resp response.status, headers, response.bodyString
proc joinHeader(headers:openArray[Headers]): Headers =
## join seq and children tuple if each headers have same key in child tuple
##
## .. code-block:: nim
## let t1 = @[("key1", "val1"),("key2", "val2")]
## let t2 = @[("key1", "val1++"),("key3", "val3")]
## let t3 = joinHeader([t1, t2])
##
## echo t3
## >> @[
## ("key1", "val1, val1++"),
## ("key2", "val2"),
## ("key3", "val3"),
## ]
##
var newHeader: Headers
var tmp = result.toTable
for header in headers:
let headerTable = header.toOrderedTable
for key, value in headerTable.pairs:
if tmp.hasKey(key):
tmp[key] = [tmp[key], headerTable[key]].join(", ")
else:
tmp[key] = headerTable[key]
for key, val in tmp.pairs:
newHeader.add(
(key:key, val:val)
)
return newHeader
template route*(respinseArg:Response,
headersArg:openArray[Headers]) =
block:
let response = respinseArg
var headersMiddleware = @headersArg
var newHeaders: Headers
headersMiddleware.add(response.headers) # headerMiddleware + headerController
newHeaders = joinHeader(headersMiddleware)
case response.responseType:
of String:
newHeaders.add(("Content-Type", "text/html;charset=utf-8"))
of Json:
newHeaders.add(("Content-Type", "application/json"))
response.bodyString = $(response.bodyJson)
of Redirect:
logger($response.status &
&" {request.ip} {request.reqMethod} {request.path}")
newHeaders.add(("Location", response.url))
resp response.status, newHeaders, ""
if response.status == Http200:
logger($response.status &
&" {request.ip} {request.reqMethod} {request.path}")
logger($newHeaders)
elif response.status.is4xx() or response.status.is5xx():
echoErrorMsg($response.status &
&" {request.ip} {request.reqMethod} {request.path}")
echoErrorMsg($newHeaders)
resp response.status, newHeaders, response.bodyString
macro createHttpCodeError():untyped =
var strBody = ""
for num in errorStatusArray:
strBody.add(fmt"""
of "Error{num.repr}":
return Http{num.repr}
""")
return parseStmt(fmt"""
case $exception.name
{strBody}
else:
return Http500
""")
proc checkHttpCode(exception:ref Exception):HttpCode =
## Generated by macro createHttpCodeError.
## List is httpCodeArray
## .. code-block:: nim
## case $exception.name
## of Error505:
## return Http505
## of Error504:
## return Http504
## of Error503:
## return Http503
## .
## .
createHttpCodeError
template exceptionRoute*(pagePath="") =
defer: GCunref exception
if exception.name == "ErrorAuthRedirect".cstring:
var cookie = newCookie(request)
cookie.delete("session_id")
route(errorRedirect(exception.msg).setCookie(cookie))
if exception.name == "DD".cstring:
var msg = exception.msg
msg = msg.replace(re"Async traceback:[.\s\S]*")
route(render(Http200, ddPage(msg)))
let status = checkHttpCode(exception)
if status.is4xx() or status.is5xx():
echoErrorMsg($request.params)
echoErrorMsg($status &
&" {request.reqMethod} {request.ip} {request.path} {exception.msg}")
if pagePath == "":
if exception.msg == "Invalid session id":
var cookie = newCookie(request)
cookie.delete("session_id")
route(render(status, errorPage(status, exception.msg)).setCookie(cookie))
else:
route(render(status, errorPage(status, exception.msg)))
else:
route(render(status, html(pagePath)))
else:
route(errorRedirect(exception.msg))
template http404Route*(pagePath="") =
if not request.path.contains("favicon"):
echoErrorMsg(&"{$Http404} {request.ip} {request.path}")
if pagePath == "":
route(render(Http404, errorPage(Http404, "route not match")))
else:
route(render(Http404, html(pagePath)))
template middleware*(procs:varargs[Response]) =
for p in procs:
if p == nil:
# echo getCurrentExceptionMsg()
discard
else:
route(p)
break