@srfnstack/spliffy 1.1.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/decorator.mjs +41 -38
- package/src/handler.mjs +11 -4
- package/src/middleware.mjs +1 -0
- package/src/server.mjs +13 -4
- package/src/staticHandler.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@srfnstack/spliffy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"author": "snowbldr",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/narcolepticsnowman/spliffy",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"cookie": "^0.4.1",
|
|
34
34
|
"etag": "^1.8.1",
|
|
35
35
|
"uuid": "^8.3.2",
|
|
36
|
-
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.
|
|
36
|
+
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.40.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"helmet": "^4.6.0",
|
package/src/decorator.mjs
CHANGED
|
@@ -45,20 +45,15 @@ export function decorateRequest (uwsReq, pathParameters, res, {
|
|
|
45
45
|
const query = uwsReq.getQuery()
|
|
46
46
|
req.path = uwsReq.getUrl()
|
|
47
47
|
req.url = `${req.path}${query ? '?' + query : ''}`
|
|
48
|
+
const paramToIndex = pathParameters.reduce((acc, cur, i) => {
|
|
49
|
+
acc[cur] = i
|
|
50
|
+
return acc
|
|
51
|
+
}, {})
|
|
48
52
|
req.spliffyUrl = {
|
|
49
53
|
path: req.path,
|
|
50
54
|
query: (query && parseQuery(query, decodeQueryParameters)) || {},
|
|
51
|
-
|
|
55
|
+
param: name => uwsReq.getParameter(paramToIndex[name])
|
|
52
56
|
}
|
|
53
|
-
if (pathParameters && pathParameters.length > 0) {
|
|
54
|
-
for (const i in pathParameters) {
|
|
55
|
-
req.spliffyUrl.pathParameters[pathParameters[i]] =
|
|
56
|
-
decodePathParameters
|
|
57
|
-
? decodeURIComponent(uwsReq.getParameter(i))
|
|
58
|
-
: uwsReq.getParameter(i)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
req.params = req.spliffyUrl.pathParameters
|
|
62
57
|
req.query = req.spliffyUrl.query
|
|
63
58
|
req.headers = {}
|
|
64
59
|
uwsReq.forEach((header, value) => { req.headers[header] = value })
|
|
@@ -97,19 +92,21 @@ export function decorateResponse (res, req, finalizeResponse, errorTransformer,
|
|
|
97
92
|
if (!res.statusCode) res.statusCode = httpStatusCodes.OK
|
|
98
93
|
if (!res.statusMessage) res.statusMessage = defaultStatusMessages[res.statusCode]
|
|
99
94
|
res.headersSent = true
|
|
100
|
-
res.
|
|
101
|
-
|
|
102
|
-
res.onFlushHeaders
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
95
|
+
res.cork(() => {
|
|
96
|
+
res.writeStatus(`${res.statusCode} ${res.statusMessage}`)
|
|
97
|
+
if (typeof res.onFlushHeaders === 'function') {
|
|
98
|
+
res.onFlushHeaders(res)
|
|
99
|
+
}
|
|
100
|
+
for (const header of Object.keys(res.headers)) {
|
|
101
|
+
if (Array.isArray(res.headers[header])) {
|
|
102
|
+
for (const multiple of res.headers[header]) {
|
|
103
|
+
res.writeHeader(header, multiple.toString())
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
res.writeHeader(header, res.headers[header].toString())
|
|
108
107
|
}
|
|
109
|
-
} else {
|
|
110
|
-
res.writeHeader(header, res.headers[header].toString())
|
|
111
108
|
}
|
|
112
|
-
}
|
|
109
|
+
})
|
|
113
110
|
}
|
|
114
111
|
res.writeHead = (status, headers) => {
|
|
115
112
|
res.statusCode = status
|
|
@@ -128,22 +125,26 @@ export function decorateResponse (res, req, finalizeResponse, errorTransformer,
|
|
|
128
125
|
return this
|
|
129
126
|
}
|
|
130
127
|
|
|
131
|
-
res.
|
|
128
|
+
res.uwsWrite = res.write
|
|
132
129
|
res.write = (chunk, encoding, cb) => {
|
|
133
130
|
try {
|
|
134
|
-
res.streaming = true
|
|
135
|
-
res.flushHeaders()
|
|
136
131
|
let result
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
132
|
+
res.cork(() => {
|
|
133
|
+
res.streaming = true
|
|
134
|
+
res.flushHeaders()
|
|
135
|
+
let data
|
|
136
|
+
if (chunk instanceof Buffer) {
|
|
137
|
+
data = toArrayBuffer(chunk)
|
|
138
|
+
} else if (typeof chunk === 'string') {
|
|
139
|
+
data = toArrayBuffer(Buffer.from(chunk, encoding || 'utf8'))
|
|
140
|
+
} else {
|
|
141
|
+
data = toArrayBuffer(Buffer.from(JSON.stringify(chunk), encoding || 'utf8'))
|
|
142
|
+
}
|
|
143
|
+
result = res.uwsWrite(data)
|
|
144
|
+
if (typeof cb === 'function') {
|
|
145
|
+
cb()
|
|
146
|
+
}
|
|
147
|
+
})
|
|
147
148
|
return result
|
|
148
149
|
} catch (e) {
|
|
149
150
|
if (typeof cb === 'function') {
|
|
@@ -181,10 +182,12 @@ export function decorateResponse (res, req, finalizeResponse, errorTransformer,
|
|
|
181
182
|
}
|
|
182
183
|
// provide writableEnded like node does, with slightly different behavior
|
|
183
184
|
if (!res.writableEnded) {
|
|
184
|
-
res.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
res.cork(() => {
|
|
186
|
+
res.flushHeaders()
|
|
187
|
+
uwsEnd.call(res, body)
|
|
188
|
+
res.writableEnded = true
|
|
189
|
+
res.ended = true
|
|
190
|
+
})
|
|
188
191
|
}
|
|
189
192
|
if (typeof res.onEnd === 'function') {
|
|
190
193
|
res.onEnd()
|
package/src/handler.mjs
CHANGED
|
@@ -47,7 +47,11 @@ const endError = (res, e, refId, errorTransformer) => {
|
|
|
47
47
|
e = errorTransformer(e, refId)
|
|
48
48
|
}
|
|
49
49
|
res.headers['x-ref-id'] = refId
|
|
50
|
-
|
|
50
|
+
const status = e.statusCode || 500
|
|
51
|
+
if (status === 500) {
|
|
52
|
+
log.error(e)
|
|
53
|
+
}
|
|
54
|
+
end(res, status, null, e.body || '')
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
const end = (res, defaultStatusCode, statusCodeOverride, body) => {
|
|
@@ -56,7 +60,6 @@ const end = (res, defaultStatusCode, statusCodeOverride, body) => {
|
|
|
56
60
|
if (body instanceof Readable || res.streaming) {
|
|
57
61
|
res.streaming = true
|
|
58
62
|
if (body instanceof Readable) {
|
|
59
|
-
res.flushHeaders()
|
|
60
63
|
pipeResponse(res, body)
|
|
61
64
|
}
|
|
62
65
|
// handler is responsible for ending the response if they are streaming
|
|
@@ -65,10 +68,14 @@ const end = (res, defaultStatusCode, statusCodeOverride, body) => {
|
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
const ipv6CompressRegex = /\b:?(?:0+:?){2,}/g
|
|
72
|
+
|
|
73
|
+
const compressIpv6 = ip => ip && ip.includes(':') ? ip.replaceAll(ipv6CompressRegex, '::') : ip
|
|
74
|
+
|
|
68
75
|
const writeAccess = function (req, res) {
|
|
69
76
|
const start = new Date().getTime()
|
|
70
77
|
return () => {
|
|
71
|
-
log.access(req.remoteAddress, res.proxiedRemoteAddress || '', res.statusCode, req.method, req.url, new Date().getTime() - start + 'ms')
|
|
78
|
+
log.access(compressIpv6(req.remoteAddress), compressIpv6(res.proxiedRemoteAddress) || '', res.statusCode, req.method, req.url, new Date().getTime() - start + 'ms')
|
|
72
79
|
}
|
|
73
80
|
}
|
|
74
81
|
|
|
@@ -233,7 +240,7 @@ export const createNotFoundHandler = config => {
|
|
|
233
240
|
res.statusCode = 500
|
|
234
241
|
})
|
|
235
242
|
} else {
|
|
236
|
-
res.statusCode =
|
|
243
|
+
res.statusCode = 404
|
|
237
244
|
res.end()
|
|
238
245
|
}
|
|
239
246
|
} else {
|
package/src/middleware.mjs
CHANGED
package/src/server.mjs
CHANGED
|
@@ -39,7 +39,7 @@ const startHttpRedirect = (host, port) => {
|
|
|
39
39
|
uws.App().any('/*',
|
|
40
40
|
(req, res) => {
|
|
41
41
|
try {
|
|
42
|
-
res.writeHead(301, { Location: `https://${req.headers.host}:${port}${req.url}` })
|
|
42
|
+
res.writeHead(301, { Location: `https://${req.headers.get('host')}:${port}${req.url}` })
|
|
43
43
|
res.end()
|
|
44
44
|
} catch (e) {
|
|
45
45
|
log.error(`Failed to handle http request on port ${port}`, req.url, e)
|
|
@@ -91,18 +91,27 @@ export async function startServer (config) {
|
|
|
91
91
|
if (config.defaultRoute && config.defaultRoute.match(routePattern)) {
|
|
92
92
|
config.defaultRouteHandler = route
|
|
93
93
|
}
|
|
94
|
+
let hadSlash = false
|
|
95
|
+
if (route.urlPath.endsWith('/')) {
|
|
96
|
+
hadSlash = true
|
|
97
|
+
route.urlPath = route.urlPath.substring(0, route.urlPath.length - 1)
|
|
98
|
+
}
|
|
94
99
|
for (const method in route.handlers) {
|
|
95
100
|
const theHandler = createHandler(route.handlers[method], route.middleware, route.pathParameters, config)
|
|
96
101
|
app[appMethods[method]](route.urlPath, theHandler)
|
|
97
|
-
if (
|
|
98
|
-
app[appMethods[method]](route.urlPath
|
|
102
|
+
if (hadSlash && config.serveRoutesWithSlash) {
|
|
103
|
+
app[appMethods[method]](route.urlPath + '/', theHandler)
|
|
99
104
|
}
|
|
100
105
|
if (route.urlPath.endsWith('/*')) {
|
|
101
106
|
app[appMethods[method]](route.urlPath.substr(0, route.urlPath.length - 2), theHandler)
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
if (config.autoOptions && !route.handlers.OPTIONS) {
|
|
105
|
-
|
|
110
|
+
const theHandler = optionsHandler(config, route.middleware, Object.keys(route.handlers).join(', '))
|
|
111
|
+
app.options(route.urlPath, theHandler)
|
|
112
|
+
if (hadSlash && config.serveRoutesWithSlash) {
|
|
113
|
+
app.options(route.urlPath + '/', theHandler)
|
|
114
|
+
}
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
|
package/src/staticHandler.mjs
CHANGED