routup 0.14.2 → 1.0.0-alpha.2
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/README.md +9 -3
- package/dist/config/index.d.ts +2 -0
- package/dist/config/module.d.ts +8 -0
- package/dist/config/type.d.ts +34 -0
- package/dist/constants.d.ts +39 -0
- package/dist/handler/index.d.ts +0 -1
- package/dist/handler/utils.d.ts +1 -2
- package/dist/helpers/index.d.ts +3 -0
- package/dist/helpers/request/body.d.ts +5 -0
- package/dist/helpers/request/cache.d.ts +2 -0
- package/dist/helpers/request/cookie.d.ts +8 -0
- package/dist/helpers/request/env.d.ts +6 -0
- package/dist/helpers/request/header-accept-charset.d.ts +3 -0
- package/dist/helpers/request/header-accept-encoding.d.ts +4 -0
- package/dist/helpers/request/header-accept-language.d.ts +3 -0
- package/dist/helpers/request/header-accept.d.ts +3 -0
- package/dist/helpers/request/header-content-type.d.ts +2 -0
- package/dist/helpers/request/header.d.ts +5 -0
- package/dist/helpers/request/hostname.d.ts +7 -0
- package/dist/helpers/request/index.d.ts +18 -0
- package/dist/helpers/request/ip.d.ts +7 -0
- package/dist/helpers/request/mount-path.d.ts +3 -0
- package/dist/helpers/request/negotiator.d.ts +3 -0
- package/dist/helpers/request/params.d.ts +5 -0
- package/dist/helpers/request/path.d.ts +2 -0
- package/dist/helpers/request/protocol.d.ts +8 -0
- package/dist/helpers/request/query.d.ts +8 -0
- package/dist/helpers/response/cache.d.ts +7 -0
- package/dist/helpers/response/header-attachment.d.ts +2 -0
- package/dist/helpers/response/header-content-type.d.ts +2 -0
- package/dist/helpers/response/header.d.ts +5 -0
- package/dist/helpers/response/index.d.ts +12 -0
- package/dist/helpers/response/send-accepted.d.ts +2 -0
- package/dist/helpers/response/send-created.d.ts +2 -0
- package/dist/helpers/response/send-file.d.ts +9 -0
- package/dist/helpers/response/send-format.d.ts +6 -0
- package/dist/helpers/response/send-redirect.d.ts +2 -0
- package/dist/helpers/response/send-stream.d.ts +4 -0
- package/dist/helpers/response/send.d.ts +2 -0
- package/dist/helpers/response/utils.d.ts +3 -0
- package/dist/helpers/type.d.ts +3 -0
- package/dist/index.cjs +1085 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.mjs +991 -4
- package/dist/index.mjs.map +1 -1
- package/dist/layer/index.d.ts +0 -1
- package/dist/layer/module.d.ts +1 -3
- package/dist/layer/type.d.ts +0 -1
- package/dist/layer/utils.d.ts +0 -1
- package/dist/path/index.d.ts +0 -1
- package/dist/path/matcher.d.ts +0 -1
- package/dist/path/type.d.ts +0 -1
- package/dist/route/index.d.ts +0 -1
- package/dist/route/module.d.ts +2 -4
- package/dist/route/type.d.ts +0 -1
- package/dist/route/utils.d.ts +0 -1
- package/dist/router/index.d.ts +0 -1
- package/dist/router/module.d.ts +1 -3
- package/dist/router/type.d.ts +0 -1
- package/dist/type.d.ts +9 -1
- package/dist/utils/etag/index.d.ts +2 -0
- package/dist/utils/etag/module.d.ts +12 -0
- package/dist/utils/etag/type.d.ts +16 -0
- package/dist/utils/etag/utils.d.ts +2 -0
- package/dist/utils/index.d.ts +5 -1
- package/dist/utils/is-instance.d.ts +0 -1
- package/dist/utils/mime.d.ts +2 -0
- package/dist/utils/object.d.ts +1 -0
- package/dist/utils/path.d.ts +0 -1
- package/dist/utils/promise.d.ts +0 -1
- package/dist/utils/request.d.ts +1 -2
- package/dist/utils/trust-proxy/index.d.ts +2 -0
- package/dist/utils/trust-proxy/module.d.ts +2 -0
- package/dist/utils/trust-proxy/type.d.ts +2 -0
- package/dist/utils/url.d.ts +7 -0
- package/package.json +30 -13
- package/dist/handler/index.d.ts.map +0 -1
- package/dist/handler/utils.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/layer/index.d.ts.map +0 -1
- package/dist/layer/module.d.ts.map +0 -1
- package/dist/layer/type.d.ts.map +0 -1
- package/dist/layer/utils.d.ts.map +0 -1
- package/dist/path/index.d.ts.map +0 -1
- package/dist/path/matcher.d.ts.map +0 -1
- package/dist/path/type.d.ts.map +0 -1
- package/dist/route/index.d.ts.map +0 -1
- package/dist/route/module.d.ts.map +0 -1
- package/dist/route/type.d.ts.map +0 -1
- package/dist/route/utils.d.ts.map +0 -1
- package/dist/router/index.d.ts.map +0 -1
- package/dist/router/module.d.ts.map +0 -1
- package/dist/router/type.d.ts.map +0 -1
- package/dist/type.d.ts.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/is-instance.d.ts.map +0 -1
- package/dist/utils/path.d.ts.map +0 -1
- package/dist/utils/promise.d.ts.map +0 -1
- package/dist/utils/request.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,112 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var continu = require('continu');
|
|
4
|
+
var process = require('node:process');
|
|
5
|
+
var zod = require('zod');
|
|
4
6
|
var smob = require('smob');
|
|
7
|
+
var crypto = require('node:crypto');
|
|
8
|
+
var node_fs = require('node:fs');
|
|
9
|
+
var proxyAddr = require('proxy-addr');
|
|
10
|
+
var mimeExplorer = require('mime-explorer');
|
|
5
11
|
var http = require('@ebec/http');
|
|
12
|
+
var Negotiator = require('negotiator');
|
|
13
|
+
var node_url = require('node:url');
|
|
14
|
+
var path = require('node:path');
|
|
6
15
|
var pathToRegexp = require('path-to-regexp');
|
|
7
16
|
var node_http = require('node:http');
|
|
8
17
|
|
|
18
|
+
/*
|
|
19
|
+
* Copyright (c) 2022-2023.
|
|
20
|
+
* Author Peter Placzek (tada5hi)
|
|
21
|
+
* For the full copyright and license information,
|
|
22
|
+
* view the LICENSE file that was distributed with this source code.
|
|
23
|
+
*/ function isObject(item) {
|
|
24
|
+
return !!item && typeof item === 'object' && !Array.isArray(item);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Determine if object is a Stats object.
|
|
29
|
+
*
|
|
30
|
+
* @param {object} obj
|
|
31
|
+
* @return {boolean}
|
|
32
|
+
* @api private
|
|
33
|
+
*/ function isStatsObject(obj) {
|
|
34
|
+
// genuine fs.Stats
|
|
35
|
+
if (typeof node_fs.Stats === 'function' && obj instanceof node_fs.Stats) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
// quack quack
|
|
39
|
+
return !!obj && typeof obj === 'object' && 'ctime' in obj && Object.prototype.toString.call(obj.ctime) === '[object Date]' && 'mtime' in obj && Object.prototype.toString.call(obj.mtime) === '[object Date]' && 'ino' in obj && typeof obj.ino === 'number' && 'size' in obj && typeof obj.size === 'number';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generate an ETag.
|
|
43
|
+
*/ function generateETag(input) {
|
|
44
|
+
if (isStatsObject(input)) {
|
|
45
|
+
const mtime = input.mtime.getTime().toString(16);
|
|
46
|
+
const size = input.size.toString(16);
|
|
47
|
+
return `"${size}-${mtime}"`;
|
|
48
|
+
}
|
|
49
|
+
if (input.length === 0) {
|
|
50
|
+
// fast-path empty
|
|
51
|
+
return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"';
|
|
52
|
+
}
|
|
53
|
+
const entity = Buffer.isBuffer(input) ? input.toString('utf-8') : input;
|
|
54
|
+
// compute hash of entity
|
|
55
|
+
const hash = crypto.createHash('sha1').update(entity, 'utf8').digest('base64').substring(0, 27);
|
|
56
|
+
return `"${entity.length.toString(16)}-${hash}"`;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Create a simple ETag.
|
|
60
|
+
*/ function createEtag(input, options) {
|
|
61
|
+
options = options || {};
|
|
62
|
+
const weak = typeof options.weak === 'boolean' ? options.weak : isStatsObject(input);
|
|
63
|
+
// generate entity tag
|
|
64
|
+
const tag = generateETag(input);
|
|
65
|
+
return weak ? `W/${tag}` : tag;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function buildEtagFn(input) {
|
|
69
|
+
if (typeof input === 'function') {
|
|
70
|
+
return input;
|
|
71
|
+
}
|
|
72
|
+
input = input ?? true;
|
|
73
|
+
if (input === false) {
|
|
74
|
+
return ()=>undefined;
|
|
75
|
+
}
|
|
76
|
+
let options = {
|
|
77
|
+
weak: true
|
|
78
|
+
};
|
|
79
|
+
if (isObject(input)) {
|
|
80
|
+
options = smob.merge(input, options);
|
|
81
|
+
}
|
|
82
|
+
return (body, encoding, size)=>{
|
|
83
|
+
const buff = Buffer.isBuffer(body) ? body : Buffer.from(body, encoding);
|
|
84
|
+
if (typeof options.threshold !== 'undefined') {
|
|
85
|
+
size = size ?? Buffer.byteLength(buff);
|
|
86
|
+
if (size <= options.threshold) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return createEtag(buff, options);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function buildTrustProxyFn(input) {
|
|
95
|
+
if (typeof input === 'function') {
|
|
96
|
+
return input;
|
|
97
|
+
}
|
|
98
|
+
if (input === true) {
|
|
99
|
+
return ()=>true;
|
|
100
|
+
}
|
|
101
|
+
if (typeof input === 'number') {
|
|
102
|
+
return (_address, hop)=>hop < input;
|
|
103
|
+
}
|
|
104
|
+
if (typeof input === 'string') {
|
|
105
|
+
input = input.split(',').map((value)=>value.trim());
|
|
106
|
+
}
|
|
107
|
+
return proxyAddr.compile(input || []);
|
|
108
|
+
}
|
|
109
|
+
|
|
9
110
|
/*
|
|
10
111
|
* Copyright (c) 2022-2022.
|
|
11
112
|
* Author Peter Placzek (tada5hi)
|
|
@@ -15,6 +116,23 @@ var node_http = require('node:http');
|
|
|
15
116
|
return typeof input === 'object' && input !== null && input['@instanceof'] === Symbol.for(name);
|
|
16
117
|
}
|
|
17
118
|
|
|
119
|
+
function getMimeType(type) {
|
|
120
|
+
if (type.indexOf('/') !== -1) {
|
|
121
|
+
return type;
|
|
122
|
+
}
|
|
123
|
+
return mimeExplorer.getType(type);
|
|
124
|
+
}
|
|
125
|
+
function getCharsetForMimeType(type) {
|
|
126
|
+
if (/^text\/|^application\/(javascript|json)/.test(type)) {
|
|
127
|
+
return 'utf-8';
|
|
128
|
+
}
|
|
129
|
+
const meta = mimeExplorer.get(type);
|
|
130
|
+
if (meta && meta.charset) {
|
|
131
|
+
return meta.charset.toLowerCase();
|
|
132
|
+
}
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
|
|
18
136
|
/*
|
|
19
137
|
* Copyright (c) 2022.
|
|
20
138
|
* Author Peter Placzek (tada5hi)
|
|
@@ -25,7 +143,7 @@ var node_http = require('node:http');
|
|
|
25
143
|
}
|
|
26
144
|
|
|
27
145
|
function isPromise(p) {
|
|
28
|
-
return
|
|
146
|
+
return isObject(p) && (p instanceof Promise || // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
29
147
|
// @ts-ignore
|
|
30
148
|
typeof p.then === 'function');
|
|
31
149
|
}
|
|
@@ -50,18 +168,888 @@ function isPromise(p) {
|
|
|
50
168
|
});
|
|
51
169
|
}
|
|
52
170
|
|
|
171
|
+
/*
|
|
172
|
+
* Copyright (c) 2022-2023.
|
|
173
|
+
* Author Peter Placzek (tada5hi)
|
|
174
|
+
* For the full copyright and license information,
|
|
175
|
+
* view the LICENSE file that was distributed with this source code.
|
|
176
|
+
*/ const TRAILING_SLASH_RE = /\/$|\/\?/;
|
|
177
|
+
function hasTrailingSlash(input = '', queryParams = false) {
|
|
178
|
+
if (!queryParams) {
|
|
179
|
+
return input.endsWith('/');
|
|
180
|
+
}
|
|
181
|
+
return TRAILING_SLASH_RE.test(input);
|
|
182
|
+
}
|
|
183
|
+
function withoutTrailingSlash(input = '', queryParams = false) {
|
|
184
|
+
if (!queryParams) {
|
|
185
|
+
return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || '/';
|
|
186
|
+
}
|
|
187
|
+
if (!hasTrailingSlash(input, true)) {
|
|
188
|
+
return input || '/';
|
|
189
|
+
}
|
|
190
|
+
const [s0, ...s] = input.split('?');
|
|
191
|
+
return (s0.slice(0, -1) || '/') + (s.length ? `?${s.join('?')}` : '');
|
|
192
|
+
}
|
|
193
|
+
function withTrailingSlash(input = '', queryParams = false) {
|
|
194
|
+
if (!queryParams) {
|
|
195
|
+
return input.endsWith('/') ? input : `${input}/`;
|
|
196
|
+
}
|
|
197
|
+
if (hasTrailingSlash(input, true)) {
|
|
198
|
+
return input || '/';
|
|
199
|
+
}
|
|
200
|
+
const [s0, ...s] = input.split('?');
|
|
201
|
+
return `${s0}/${s.length ? `?${s.join('?')}` : ''}`;
|
|
202
|
+
}
|
|
203
|
+
function hasLeadingSlash(input = '') {
|
|
204
|
+
return input.startsWith('/');
|
|
205
|
+
}
|
|
206
|
+
function withoutLeadingSlash(input = '') {
|
|
207
|
+
return (hasLeadingSlash(input) ? input.substr(1) : input) || '/';
|
|
208
|
+
}
|
|
209
|
+
function withLeadingSlash(input = '') {
|
|
210
|
+
return hasLeadingSlash(input) ? input : `/${input}`;
|
|
211
|
+
}
|
|
212
|
+
function cleanDoubleSlashes(input = '') {
|
|
213
|
+
return input.split('://').map((str)=>str.replace(/\/{2,}/g, '/')).join('://');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let instance;
|
|
217
|
+
function buildConfig() {
|
|
218
|
+
return new continu.Continu({
|
|
219
|
+
defaults: {
|
|
220
|
+
env: process.env.NODE_ENV || 'development',
|
|
221
|
+
trustProxy: ()=>false,
|
|
222
|
+
subdomainOffset: 2,
|
|
223
|
+
etag: buildEtagFn(),
|
|
224
|
+
proxyIpMax: 0
|
|
225
|
+
},
|
|
226
|
+
transformers: {
|
|
227
|
+
etag: (value)=>buildEtagFn(value),
|
|
228
|
+
trustProxy: (value)=>buildTrustProxyFn(value)
|
|
229
|
+
},
|
|
230
|
+
validators: {
|
|
231
|
+
env: (value)=>zod.string().safeParse(value),
|
|
232
|
+
trustProxy: (value)=>zod.any().safeParse(value),
|
|
233
|
+
subdomainOffset: (value)=>zod.number().nonnegative().safeParse(value),
|
|
234
|
+
etag: (value)=>zod.any().safeParse(value),
|
|
235
|
+
proxyIpMax: (value)=>zod.number().nonnegative().safeParse(value)
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function useConfig() {
|
|
240
|
+
if (typeof instance !== 'undefined') {
|
|
241
|
+
return instance;
|
|
242
|
+
}
|
|
243
|
+
instance = buildConfig();
|
|
244
|
+
return instance;
|
|
245
|
+
}
|
|
246
|
+
function setConfig(config) {
|
|
247
|
+
instance = config;
|
|
248
|
+
}
|
|
249
|
+
function setConfigOption(key, value) {
|
|
250
|
+
const config = useConfig();
|
|
251
|
+
config.setRaw(key, value);
|
|
252
|
+
return config.get();
|
|
253
|
+
}
|
|
254
|
+
function getConfigOption(key) {
|
|
255
|
+
const config = useConfig();
|
|
256
|
+
return config.get(key);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/*
|
|
260
|
+
* Copyright (c) 2022-2023.
|
|
261
|
+
* Author Peter Placzek (tada5hi)
|
|
262
|
+
* For the full copyright and license information,
|
|
263
|
+
* view the LICENSE file that was distributed with this source code.
|
|
264
|
+
*/ exports.Method = void 0;
|
|
265
|
+
(function(Method) {
|
|
266
|
+
Method["GET"] = 'get';
|
|
267
|
+
Method["POST"] = 'post';
|
|
268
|
+
Method["PUT"] = 'put';
|
|
269
|
+
Method["PATCH"] = 'patch';
|
|
270
|
+
Method["DELETE"] = 'delete';
|
|
271
|
+
Method["OPTIONS"] = 'options';
|
|
272
|
+
Method["HEAD"] = 'head';
|
|
273
|
+
})(exports.Method || (exports.Method = {}));
|
|
274
|
+
exports.HeaderName = void 0;
|
|
275
|
+
(function(HeaderName) {
|
|
276
|
+
HeaderName["ACCEPT"] = 'accept';
|
|
277
|
+
HeaderName["ACCEPT_CHARSET"] = 'accept-charset';
|
|
278
|
+
HeaderName["ACCEPT_ENCODING"] = 'accept-encoding';
|
|
279
|
+
HeaderName["ACCEPT_LANGUAGE"] = 'accept-language';
|
|
280
|
+
HeaderName["ACCEPT_RANGES"] = 'accept-ranges';
|
|
281
|
+
HeaderName["ALLOW"] = 'allow';
|
|
282
|
+
HeaderName["CACHE_CONTROL"] = 'cache-control';
|
|
283
|
+
HeaderName["CONTENT_DISPOSITION"] = 'content-disposition';
|
|
284
|
+
HeaderName["CONTENT_ENCODING"] = 'content-encoding';
|
|
285
|
+
HeaderName["CONTENT_LENGTH"] = 'content-length';
|
|
286
|
+
HeaderName["CONTENT_RANGE"] = 'content-range';
|
|
287
|
+
HeaderName["CONTENT_TYPE"] = 'content-type';
|
|
288
|
+
HeaderName["COOKIE"] = 'cookie';
|
|
289
|
+
HeaderName["ETag"] = 'etag';
|
|
290
|
+
HeaderName["HOST"] = 'host';
|
|
291
|
+
HeaderName["IF_NONE_MATCH"] = 'if-none-match';
|
|
292
|
+
HeaderName["LAST_MODIFIED"] = 'last-modified';
|
|
293
|
+
HeaderName["LOCATION"] = 'location';
|
|
294
|
+
HeaderName["RANGE"] = 'range';
|
|
295
|
+
HeaderName["RATE_LIMIT_LIMIT"] = 'ratelimit-limit';
|
|
296
|
+
HeaderName["RATE_LIMIT_REMAINING"] = 'ratelimit-remaining';
|
|
297
|
+
HeaderName["RATE_LIMIT_RESET"] = 'ratelimit-reset';
|
|
298
|
+
HeaderName["RETRY_AFTER"] = 'retry-after';
|
|
299
|
+
HeaderName["SET_COOKIE"] = 'set-cookie';
|
|
300
|
+
HeaderName["TRANSFER_ENCODING"] = 'transfer-encoding';
|
|
301
|
+
HeaderName["X_FORWARDED_HOST"] = 'x-forwarded-host';
|
|
302
|
+
HeaderName["X_FORWARDED_FOR"] = 'x-forwarded-for';
|
|
303
|
+
HeaderName["X_FORWARDED_PROTO"] = 'x-forwarded-proto';
|
|
304
|
+
})(exports.HeaderName || (exports.HeaderName = {}));
|
|
305
|
+
|
|
306
|
+
const BodySymbol = Symbol.for('ReqBody');
|
|
307
|
+
function useRequestBody(req, key) {
|
|
308
|
+
let body;
|
|
309
|
+
/* istanbul ignore next */ if ('body' in req) {
|
|
310
|
+
body = req.body;
|
|
311
|
+
}
|
|
312
|
+
if (BodySymbol in req) {
|
|
313
|
+
if (body) {
|
|
314
|
+
body = smob.merge({}, req[BodySymbol], body);
|
|
315
|
+
} else {
|
|
316
|
+
body = req[BodySymbol];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (body) {
|
|
320
|
+
if (typeof key === 'string') {
|
|
321
|
+
return body[key];
|
|
322
|
+
}
|
|
323
|
+
return body;
|
|
324
|
+
}
|
|
325
|
+
return typeof key === 'string' ? undefined : {};
|
|
326
|
+
}
|
|
327
|
+
function setRequestBody(req, key, value) {
|
|
328
|
+
if (BodySymbol in req) {
|
|
329
|
+
if (typeof key === 'object') {
|
|
330
|
+
if (value) {
|
|
331
|
+
req[BodySymbol] = smob.merge(req[BodySymbol], key);
|
|
332
|
+
} else {
|
|
333
|
+
req[BodySymbol] = key;
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
req[BodySymbol][key] = value;
|
|
337
|
+
}
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (typeof key === 'object') {
|
|
341
|
+
req[BodySymbol] = key;
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
req[BodySymbol] = {
|
|
345
|
+
[key]: value
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/*
|
|
350
|
+
* Copyright (c) 2022.
|
|
351
|
+
* Author Peter Placzek (tada5hi)
|
|
352
|
+
* For the full copyright and license information,
|
|
353
|
+
* view the LICENSE file that was distributed with this source code.
|
|
354
|
+
*/ function isRequestCacheable(req, modifiedTime) {
|
|
355
|
+
const modifiedSince = req.headers['if-modified-since'];
|
|
356
|
+
if (!modifiedSince) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
modifiedTime = typeof modifiedTime === 'string' ? new Date(modifiedTime) : modifiedTime;
|
|
360
|
+
return new Date(modifiedSince) >= modifiedTime;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const CookieSymbol = Symbol.for('ReqCookie');
|
|
364
|
+
let requestFn$1;
|
|
365
|
+
function setRequestCookieFn(fn) {
|
|
366
|
+
requestFn$1 = fn;
|
|
367
|
+
}
|
|
368
|
+
function useRequestCookies(req) {
|
|
369
|
+
if (!(CookieSymbol in req) && typeof requestFn$1 !== 'undefined') {
|
|
370
|
+
req[CookieSymbol] = requestFn$1(req);
|
|
371
|
+
}
|
|
372
|
+
if (CookieSymbol in req) {
|
|
373
|
+
return req[CookieSymbol];
|
|
374
|
+
}
|
|
375
|
+
return {};
|
|
376
|
+
}
|
|
377
|
+
function hasRequestCookies(req) {
|
|
378
|
+
return CookieSymbol in req && isObject(req[CookieSymbol]);
|
|
379
|
+
}
|
|
380
|
+
function useRequestCookie(req, name) {
|
|
381
|
+
return useRequestCookies(req)[name];
|
|
382
|
+
}
|
|
383
|
+
function setRequestCookies(req, record, mergeIt) {
|
|
384
|
+
if (CookieSymbol in req) {
|
|
385
|
+
if (mergeIt) {
|
|
386
|
+
req[CookieSymbol] = smob.merge(req[CookieSymbol], record);
|
|
387
|
+
}
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
req[CookieSymbol] = record;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const envSymbol = Symbol.for('ReqEnv');
|
|
394
|
+
function setRequestEnv(req, key, value) {
|
|
395
|
+
if (envSymbol in req) {
|
|
396
|
+
if (typeof key === 'object') {
|
|
397
|
+
if (value) {
|
|
398
|
+
req[envSymbol] = smob.merge(req[envSymbol], key);
|
|
399
|
+
} else {
|
|
400
|
+
req[envSymbol] = key;
|
|
401
|
+
}
|
|
402
|
+
} else {
|
|
403
|
+
req[envSymbol][key] = value;
|
|
404
|
+
}
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (typeof key === 'object') {
|
|
408
|
+
req[envSymbol] = key;
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
req[envSymbol] = {
|
|
412
|
+
[key]: value
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
function useRequestEnv(req, key) {
|
|
416
|
+
if (envSymbol in req) {
|
|
417
|
+
if (typeof key === 'string') {
|
|
418
|
+
return req[envSymbol][key];
|
|
419
|
+
}
|
|
420
|
+
return req[envSymbol];
|
|
421
|
+
}
|
|
422
|
+
if (typeof key === 'string') {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
425
|
+
return {};
|
|
426
|
+
}
|
|
427
|
+
function unsetRequestEnv(req, key) {
|
|
428
|
+
if (envSymbol in req) {
|
|
429
|
+
if (smob.hasOwnProperty(req[envSymbol], key)) {
|
|
430
|
+
delete req[envSymbol][key];
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/*
|
|
436
|
+
* Copyright (c) 2022.
|
|
437
|
+
* Author Peter Placzek (tada5hi)
|
|
438
|
+
* For the full copyright and license information,
|
|
439
|
+
* view the LICENSE file that was distributed with this source code.
|
|
440
|
+
*/ function getRequestHeader(req, name) {
|
|
441
|
+
return req.headers[name];
|
|
442
|
+
}
|
|
443
|
+
function setRequestHeader(req, name, value) {
|
|
444
|
+
req.headers[name] = value;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const NegotiatorSymbol = Symbol.for('ReqNegotiator');
|
|
448
|
+
function useRequestNegotiator(req) {
|
|
449
|
+
if (NegotiatorSymbol in req) {
|
|
450
|
+
return req[NegotiatorSymbol];
|
|
451
|
+
}
|
|
452
|
+
return new Negotiator(req);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function getRequestAcceptableContentTypes(req) {
|
|
456
|
+
const negotiator = useRequestNegotiator(req);
|
|
457
|
+
return negotiator.mediaTypes();
|
|
458
|
+
}
|
|
459
|
+
function getRequestAcceptableContentType(req, input) {
|
|
460
|
+
input = input || [];
|
|
461
|
+
const items = Array.isArray(input) ? input : [
|
|
462
|
+
input
|
|
463
|
+
];
|
|
464
|
+
if (items.length === 0) {
|
|
465
|
+
return getRequestAcceptableContentTypes(req).shift();
|
|
466
|
+
}
|
|
467
|
+
const header = getRequestHeader(req, exports.HeaderName.ACCEPT);
|
|
468
|
+
if (!header) {
|
|
469
|
+
return items[0];
|
|
470
|
+
}
|
|
471
|
+
let polluted = false;
|
|
472
|
+
const mimeTypes = [];
|
|
473
|
+
for(let i = 0; i < items.length; i++){
|
|
474
|
+
const mimeType = getMimeType(items[i]);
|
|
475
|
+
if (mimeType) {
|
|
476
|
+
mimeTypes.push(mimeType);
|
|
477
|
+
} else {
|
|
478
|
+
polluted = true;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const negotiator = useRequestNegotiator(req);
|
|
482
|
+
const matches = negotiator.mediaTypes(mimeTypes);
|
|
483
|
+
if (matches.length > 0) {
|
|
484
|
+
if (polluted) {
|
|
485
|
+
return items[0];
|
|
486
|
+
}
|
|
487
|
+
return items[mimeTypes.indexOf(matches[0])];
|
|
488
|
+
}
|
|
489
|
+
return undefined;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function getRequestAcceptableCharsets(req) {
|
|
493
|
+
const negotiator = useRequestNegotiator(req);
|
|
494
|
+
return negotiator.charsets();
|
|
495
|
+
}
|
|
496
|
+
function getRequestAcceptableCharset(req, input) {
|
|
497
|
+
input = input || [];
|
|
498
|
+
const items = Array.isArray(input) ? input : [
|
|
499
|
+
input
|
|
500
|
+
];
|
|
501
|
+
if (items.length === 0) {
|
|
502
|
+
return getRequestAcceptableCharsets(req).shift();
|
|
503
|
+
}
|
|
504
|
+
const negotiator = useRequestNegotiator(req);
|
|
505
|
+
return negotiator.charsets(items).shift() || undefined;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function getRequestAcceptableEncodings(req) {
|
|
509
|
+
const negotiator = useRequestNegotiator(req);
|
|
510
|
+
return negotiator.encodings();
|
|
511
|
+
}
|
|
512
|
+
function getRequestAcceptableEncoding(req, input) {
|
|
513
|
+
input = input || [];
|
|
514
|
+
const items = Array.isArray(input) ? input : [
|
|
515
|
+
input
|
|
516
|
+
];
|
|
517
|
+
if (items.length === 0) {
|
|
518
|
+
return getRequestAcceptableEncodings(req).shift();
|
|
519
|
+
}
|
|
520
|
+
const negotiator = useRequestNegotiator(req);
|
|
521
|
+
return negotiator.encodings(items).shift() || undefined;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function getRequestAcceptableLanguages(req) {
|
|
525
|
+
const negotiator = useRequestNegotiator(req);
|
|
526
|
+
return negotiator.languages();
|
|
527
|
+
}
|
|
528
|
+
function getRequestAcceptableLanguage(req, input) {
|
|
529
|
+
input = input || [];
|
|
530
|
+
const items = Array.isArray(input) ? input : [
|
|
531
|
+
input
|
|
532
|
+
];
|
|
533
|
+
if (items.length === 0) {
|
|
534
|
+
return getRequestAcceptableLanguages(req).shift();
|
|
535
|
+
}
|
|
536
|
+
const negotiator = useRequestNegotiator(req);
|
|
537
|
+
return negotiator.languages(items).shift() || undefined;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function matchRequestContentType(req, contentType) {
|
|
541
|
+
const header = getRequestHeader(req, exports.HeaderName.CONTENT_TYPE);
|
|
542
|
+
if (!header) {
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
/* istanbul ignore next */ if (Array.isArray(header)) {
|
|
546
|
+
if (header.length === 0) {
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
return header[0] === getMimeType(contentType);
|
|
550
|
+
}
|
|
551
|
+
return header.split('; ').shift() === getMimeType(contentType);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function getRequestHostName(req, options) {
|
|
555
|
+
options = options || {};
|
|
556
|
+
let trustProxy;
|
|
557
|
+
if (typeof options.trustProxy !== 'undefined') {
|
|
558
|
+
trustProxy = buildTrustProxyFn(options.trustProxy);
|
|
559
|
+
} else {
|
|
560
|
+
const config = useConfig();
|
|
561
|
+
trustProxy = config.get('trustProxy');
|
|
562
|
+
}
|
|
563
|
+
let hostname = req.headers[exports.HeaderName.X_FORWARDED_HOST];
|
|
564
|
+
if (!hostname || !req.socket.remoteAddress || !trustProxy(req.socket.remoteAddress, 0)) {
|
|
565
|
+
hostname = req.headers[exports.HeaderName.HOST];
|
|
566
|
+
} else {
|
|
567
|
+
hostname = Array.isArray(hostname) ? hostname.pop() : hostname;
|
|
568
|
+
if (hostname && hostname.indexOf(',') !== -1) {
|
|
569
|
+
hostname = hostname.substring(0, hostname.indexOf(',')).trimEnd();
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (!hostname) {
|
|
573
|
+
return undefined;
|
|
574
|
+
}
|
|
575
|
+
// IPv6 literal support
|
|
576
|
+
const offset = hostname[0] === '[' ? hostname.indexOf(']') + 1 : 0;
|
|
577
|
+
const index = hostname.indexOf(':', offset);
|
|
578
|
+
return index !== -1 ? hostname.substring(0, index) : hostname;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function getRequestIP(req, options) {
|
|
582
|
+
options = options || {};
|
|
583
|
+
let trustProxy;
|
|
584
|
+
if (typeof options.trustProxy !== 'undefined') {
|
|
585
|
+
trustProxy = buildTrustProxyFn(options.trustProxy);
|
|
586
|
+
} else {
|
|
587
|
+
const config = useConfig();
|
|
588
|
+
trustProxy = config.get('trustProxy');
|
|
589
|
+
}
|
|
590
|
+
return proxyAddr(req, trustProxy);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/*
|
|
594
|
+
* Copyright (c) 2022.
|
|
595
|
+
* Author Peter Placzek (tada5hi)
|
|
596
|
+
* For the full copyright and license information,
|
|
597
|
+
* view the LICENSE file that was distributed with this source code.
|
|
598
|
+
*/ const ReqMountPathSymbol = Symbol.for('ReqMountPath');
|
|
599
|
+
function useRequestMountPath(req) {
|
|
600
|
+
if (ReqMountPathSymbol in req) {
|
|
601
|
+
return req[ReqMountPathSymbol];
|
|
602
|
+
}
|
|
603
|
+
return '/';
|
|
604
|
+
}
|
|
605
|
+
function setRequestMountPath(req, basePath) {
|
|
606
|
+
req[ReqMountPathSymbol] = basePath;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/*
|
|
610
|
+
* Copyright (c) 2022.
|
|
611
|
+
* Author Peter Placzek (tada5hi)
|
|
612
|
+
* For the full copyright and license information,
|
|
613
|
+
* view the LICENSE file that was distributed with this source code.
|
|
614
|
+
*/ const ParamsSymbol = Symbol.for('ReqParams');
|
|
615
|
+
function useRequestParams(req) {
|
|
616
|
+
if ('params' in req) {
|
|
617
|
+
return req.params;
|
|
618
|
+
}
|
|
619
|
+
if (ParamsSymbol in req) {
|
|
620
|
+
return req[ParamsSymbol];
|
|
621
|
+
}
|
|
622
|
+
return {};
|
|
623
|
+
}
|
|
624
|
+
function useRequestParam(req, key) {
|
|
625
|
+
return useRequestParams(req)[key];
|
|
626
|
+
}
|
|
627
|
+
function setRequestParams(req, data) {
|
|
628
|
+
req[ParamsSymbol] = data;
|
|
629
|
+
}
|
|
630
|
+
function setRequestParam(req, key, value) {
|
|
631
|
+
const params = useRequestParams(req);
|
|
632
|
+
params[key] = value;
|
|
633
|
+
setRequestParams(req, params);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function useRequestPath(req) {
|
|
637
|
+
if ('path' in req) {
|
|
638
|
+
return req.path;
|
|
639
|
+
}
|
|
640
|
+
if (typeof req.url === 'undefined') {
|
|
641
|
+
return '/';
|
|
642
|
+
}
|
|
643
|
+
const parsed = new node_url.URL(req.url, 'http://localhost/');
|
|
644
|
+
return parsed.pathname;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function getRequestProtocol(req, options) {
|
|
648
|
+
options = options || {};
|
|
649
|
+
let trustProxy;
|
|
650
|
+
if (typeof options.trustProxy !== 'undefined') {
|
|
651
|
+
trustProxy = buildTrustProxyFn(options.trustProxy);
|
|
652
|
+
} else {
|
|
653
|
+
const config = useConfig();
|
|
654
|
+
trustProxy = config.get('trustProxy');
|
|
655
|
+
}
|
|
656
|
+
let protocol = options.default;
|
|
657
|
+
/* istanbul ignore next */ if (smob.hasOwnProperty(req.socket, 'encrypted') && !!req.socket.encrypted) {
|
|
658
|
+
protocol = 'https';
|
|
659
|
+
} else if (!protocol) {
|
|
660
|
+
protocol = 'http';
|
|
661
|
+
}
|
|
662
|
+
if (!req.socket.remoteAddress || !trustProxy(req.socket.remoteAddress, 0)) {
|
|
663
|
+
return protocol;
|
|
664
|
+
}
|
|
665
|
+
let header = req.headers[exports.HeaderName.X_FORWARDED_PROTO];
|
|
666
|
+
/* istanbul ignore next */ if (Array.isArray(header)) {
|
|
667
|
+
header = header.pop();
|
|
668
|
+
}
|
|
669
|
+
if (!header) {
|
|
670
|
+
return protocol;
|
|
671
|
+
}
|
|
672
|
+
const index = header.indexOf(',');
|
|
673
|
+
return index !== -1 ? header.substring(0, index).trim() : header.trim();
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const QuerySymbol = Symbol.for('ReqQuery');
|
|
677
|
+
let requestFn;
|
|
678
|
+
function setRequestQueryFn(fn) {
|
|
679
|
+
requestFn = fn;
|
|
680
|
+
}
|
|
681
|
+
function useRequestQuery(req, key) {
|
|
682
|
+
/* istanbul ignore if */ if ('query' in req) {
|
|
683
|
+
if (typeof key === 'string') {
|
|
684
|
+
return req.query[key];
|
|
685
|
+
}
|
|
686
|
+
return req.query;
|
|
687
|
+
}
|
|
688
|
+
if (!(QuerySymbol in req) && typeof requestFn !== 'undefined') {
|
|
689
|
+
req[QuerySymbol] = requestFn(req);
|
|
690
|
+
}
|
|
691
|
+
if (QuerySymbol in req) {
|
|
692
|
+
if (typeof key === 'string') {
|
|
693
|
+
return req[QuerySymbol][key];
|
|
694
|
+
}
|
|
695
|
+
return req[QuerySymbol];
|
|
696
|
+
}
|
|
697
|
+
return {};
|
|
698
|
+
}
|
|
699
|
+
function hasRequestQuery(req) {
|
|
700
|
+
return QuerySymbol in req && isObject(req[QuerySymbol]);
|
|
701
|
+
}
|
|
702
|
+
function setRequestQuery(req, key, value) {
|
|
703
|
+
if (QuerySymbol in req) {
|
|
704
|
+
if (typeof key === 'object') {
|
|
705
|
+
if (value) {
|
|
706
|
+
req[QuerySymbol] = smob.merge(req[QuerySymbol], key);
|
|
707
|
+
} else {
|
|
708
|
+
req[QuerySymbol] = key;
|
|
709
|
+
}
|
|
710
|
+
} else {
|
|
711
|
+
req[QuerySymbol][key] = value;
|
|
712
|
+
}
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (typeof key === 'object') {
|
|
716
|
+
req[QuerySymbol] = key;
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
req[QuerySymbol] = {
|
|
720
|
+
[key]: value
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/*
|
|
725
|
+
* Copyright (c) 2022.
|
|
726
|
+
* Author Peter Placzek (tada5hi)
|
|
727
|
+
* For the full copyright and license information,
|
|
728
|
+
* view the LICENSE file that was distributed with this source code.
|
|
729
|
+
*/ function setResponseCacheHeaders(res, options) {
|
|
730
|
+
options = options || {};
|
|
731
|
+
const cacheControls = [
|
|
732
|
+
'public'
|
|
733
|
+
].concat(options.cacheControls || []);
|
|
734
|
+
if (options.maxAge !== undefined) {
|
|
735
|
+
cacheControls.push(`max-age=${+options.maxAge}`, `s-maxage=${+options.maxAge}`);
|
|
736
|
+
}
|
|
737
|
+
if (options.modifiedTime) {
|
|
738
|
+
const modifiedTime = typeof options.modifiedTime === 'string' ? new Date(options.modifiedTime) : options.modifiedTime;
|
|
739
|
+
res.setHeader('last-modified', modifiedTime.toUTCString());
|
|
740
|
+
}
|
|
741
|
+
res.setHeader('cache-control', cacheControls.join(', '));
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/*
|
|
745
|
+
* Copyright (c) 2022.
|
|
746
|
+
* Author Peter Placzek (tada5hi)
|
|
747
|
+
* For the full copyright and license information,
|
|
748
|
+
* view the LICENSE file that was distributed with this source code.
|
|
749
|
+
*/ function appendResponseHeader(res, name, value) {
|
|
750
|
+
let header = res.getHeader(name);
|
|
751
|
+
if (!header) {
|
|
752
|
+
res.setHeader(name, value);
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (!Array.isArray(header)) {
|
|
756
|
+
header = [
|
|
757
|
+
header.toString()
|
|
758
|
+
];
|
|
759
|
+
}
|
|
760
|
+
res.setHeader(name, [
|
|
761
|
+
...header,
|
|
762
|
+
value
|
|
763
|
+
]);
|
|
764
|
+
}
|
|
765
|
+
function appendResponseHeaderDirective(res, name, value) {
|
|
766
|
+
let header = res.getHeader(name);
|
|
767
|
+
if (!header) {
|
|
768
|
+
if (Array.isArray(value)) {
|
|
769
|
+
res.setHeader(name, value.join('; '));
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
res.setHeader(name, value);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
if (!Array.isArray(header)) {
|
|
776
|
+
if (typeof header === 'string') {
|
|
777
|
+
// split header by directive(s)
|
|
778
|
+
header = header.split('; ');
|
|
779
|
+
}
|
|
780
|
+
if (typeof header === 'number') {
|
|
781
|
+
header = [
|
|
782
|
+
header.toString()
|
|
783
|
+
];
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
if (Array.isArray(value)) {
|
|
787
|
+
header.push(...value);
|
|
788
|
+
} else {
|
|
789
|
+
header.push(`${value}`);
|
|
790
|
+
}
|
|
791
|
+
header = [
|
|
792
|
+
...new Set(header)
|
|
793
|
+
];
|
|
794
|
+
res.setHeader(name, header.join('; '));
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function setResponseContentTypeByFileName(res, fileName) {
|
|
798
|
+
const ext = path.extname(fileName);
|
|
799
|
+
if (ext) {
|
|
800
|
+
let type = getMimeType(ext.substring(1));
|
|
801
|
+
if (type) {
|
|
802
|
+
const charset = getCharsetForMimeType(type);
|
|
803
|
+
if (charset) {
|
|
804
|
+
type += `; charset=${charset}`;
|
|
805
|
+
}
|
|
806
|
+
res.setHeader(exports.HeaderName.CONTENT_TYPE, type);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
function onResponseFinished(res, cb) {
|
|
811
|
+
let called;
|
|
812
|
+
const callCallback = (err)=>{
|
|
813
|
+
if (called) return;
|
|
814
|
+
called = true;
|
|
815
|
+
cb(err);
|
|
816
|
+
};
|
|
817
|
+
res.on('finish', async ()=>{
|
|
818
|
+
callCallback();
|
|
819
|
+
});
|
|
820
|
+
res.on('close', async ()=>{
|
|
821
|
+
callCallback();
|
|
822
|
+
});
|
|
823
|
+
res.on('error', async (err)=>{
|
|
824
|
+
callCallback(err);
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
function setResponseHeaderAttachment(res, filename) {
|
|
829
|
+
if (typeof filename === 'string') {
|
|
830
|
+
setResponseContentTypeByFileName(res, filename);
|
|
831
|
+
}
|
|
832
|
+
res.setHeader(exports.HeaderName.CONTENT_DISPOSITION, `attachment${filename ? `; filename="${filename}"` : ''}`);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
function setResponseHeaderContentType(res, input, ifNotExists) {
|
|
836
|
+
if (ifNotExists) {
|
|
837
|
+
const header = res.getHeader(exports.HeaderName.CONTENT_TYPE);
|
|
838
|
+
if (header) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
const contentType = getMimeType(input);
|
|
843
|
+
if (contentType) {
|
|
844
|
+
res.setHeader(exports.HeaderName.CONTENT_TYPE, contentType);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
function send(res, chunk) {
|
|
849
|
+
switch(typeof chunk){
|
|
850
|
+
case 'string':
|
|
851
|
+
{
|
|
852
|
+
setResponseHeaderContentType(res, 'html', true);
|
|
853
|
+
break;
|
|
854
|
+
}
|
|
855
|
+
case 'boolean':
|
|
856
|
+
case 'number':
|
|
857
|
+
case 'object':
|
|
858
|
+
{
|
|
859
|
+
if (chunk === null) {
|
|
860
|
+
chunk = '';
|
|
861
|
+
} else if (Buffer.isBuffer(chunk)) {
|
|
862
|
+
setResponseHeaderContentType(res, 'bin', true);
|
|
863
|
+
} else {
|
|
864
|
+
chunk = JSON.stringify(chunk);
|
|
865
|
+
setResponseHeaderContentType(res, 'application/json', true);
|
|
866
|
+
}
|
|
867
|
+
break;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
let encoding;
|
|
871
|
+
if (typeof chunk === 'string') {
|
|
872
|
+
res.setHeader(exports.HeaderName.CONTENT_ENCODING, 'utf-8');
|
|
873
|
+
appendResponseHeaderDirective(res, exports.HeaderName.CONTENT_TYPE, 'charset=utf-8');
|
|
874
|
+
encoding = 'utf-8';
|
|
875
|
+
}
|
|
876
|
+
// populate Content-Length
|
|
877
|
+
let len;
|
|
878
|
+
if (chunk !== undefined) {
|
|
879
|
+
if (Buffer.isBuffer(chunk)) {
|
|
880
|
+
// get length of Buffer
|
|
881
|
+
len = chunk.length;
|
|
882
|
+
} else if (chunk.length < 1000) {
|
|
883
|
+
// just calculate length when no ETag + small chunk
|
|
884
|
+
len = Buffer.byteLength(chunk, encoding);
|
|
885
|
+
} else {
|
|
886
|
+
// convert chunk to Buffer and calculate
|
|
887
|
+
chunk = Buffer.from(chunk, encoding);
|
|
888
|
+
encoding = undefined;
|
|
889
|
+
len = chunk.length;
|
|
890
|
+
}
|
|
891
|
+
res.setHeader(exports.HeaderName.CONTENT_LENGTH, `${len}`);
|
|
892
|
+
}
|
|
893
|
+
const config = useConfig();
|
|
894
|
+
const etagFn = config.get('etag');
|
|
895
|
+
if (typeof len !== 'undefined') {
|
|
896
|
+
const chunkHash = etagFn(chunk, encoding, len);
|
|
897
|
+
if (typeof chunkHash === 'string') {
|
|
898
|
+
res.setHeader(exports.HeaderName.ETag, chunkHash);
|
|
899
|
+
if (res.req.headers[exports.HeaderName.IF_NONE_MATCH] === chunkHash) {
|
|
900
|
+
res.statusCode = 304;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
// strip irrelevant headers
|
|
905
|
+
if (res.statusCode === 204 || res.statusCode === 304) {
|
|
906
|
+
res.removeHeader(exports.HeaderName.CONTENT_TYPE);
|
|
907
|
+
res.removeHeader(exports.HeaderName.CONTENT_LENGTH);
|
|
908
|
+
res.removeHeader(exports.HeaderName.TRANSFER_ENCODING);
|
|
909
|
+
chunk = '';
|
|
910
|
+
}
|
|
911
|
+
// alter headers for 205
|
|
912
|
+
if (res.statusCode === 205) {
|
|
913
|
+
res.setHeader(exports.HeaderName.CONTENT_LENGTH, 0);
|
|
914
|
+
res.removeHeader(exports.HeaderName.TRANSFER_ENCODING);
|
|
915
|
+
chunk = '';
|
|
916
|
+
}
|
|
917
|
+
if (res.req.method === 'HEAD') {
|
|
918
|
+
// skip body for HEAD
|
|
919
|
+
res.end();
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
if (typeof encoding !== 'undefined') {
|
|
923
|
+
res.end(chunk, encoding);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
res.end(chunk);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
function sendAccepted(res, chunk) {
|
|
930
|
+
res.statusCode = 202;
|
|
931
|
+
res.statusMessage = 'Accepted';
|
|
932
|
+
return send(res, chunk);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
function sendCreated(res, chunk) {
|
|
936
|
+
res.statusCode = 201;
|
|
937
|
+
res.statusMessage = 'Created';
|
|
938
|
+
return send(res, chunk);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/*
|
|
942
|
+
* Copyright (c) 2022.
|
|
943
|
+
* Author Peter Placzek (tada5hi)
|
|
944
|
+
* For the full copyright and license information,
|
|
945
|
+
* view the LICENSE file that was distributed with this source code.
|
|
946
|
+
*/ function sendStream(res, stream, fn) {
|
|
947
|
+
stream.on('open', ()=>{
|
|
948
|
+
stream.pipe(res);
|
|
949
|
+
});
|
|
950
|
+
stream.on('error', (err)=>{
|
|
951
|
+
if (typeof fn === 'function') {
|
|
952
|
+
fn(err);
|
|
953
|
+
} else {
|
|
954
|
+
res.statusCode = 400;
|
|
955
|
+
res.end();
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
stream.on('close', ()=>{
|
|
959
|
+
if (typeof fn === 'function') {
|
|
960
|
+
fn();
|
|
961
|
+
} else {
|
|
962
|
+
res.end();
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
function resolveStats(options, cb) {
|
|
968
|
+
if (options.stats) {
|
|
969
|
+
cb(null, options.stats);
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
node_fs.stat(options.filePath, (err, stats)=>cb(err, stats));
|
|
973
|
+
}
|
|
974
|
+
function sendFile(res, filePath, fn) {
|
|
975
|
+
let options;
|
|
976
|
+
if (typeof filePath === 'string') {
|
|
977
|
+
options = {
|
|
978
|
+
filePath
|
|
979
|
+
};
|
|
980
|
+
} else {
|
|
981
|
+
options = filePath;
|
|
982
|
+
}
|
|
983
|
+
const fileName = path.basename(options.filePath);
|
|
984
|
+
if (options.attachment) {
|
|
985
|
+
const dispositionHeader = res.getHeader(exports.HeaderName.CONTENT_DISPOSITION);
|
|
986
|
+
if (!dispositionHeader) {
|
|
987
|
+
setResponseHeaderAttachment(res, fileName);
|
|
988
|
+
}
|
|
989
|
+
} else {
|
|
990
|
+
setResponseContentTypeByFileName(res, fileName);
|
|
991
|
+
}
|
|
992
|
+
resolveStats(options, (err, stats)=>{
|
|
993
|
+
if (err) {
|
|
994
|
+
if (typeof fn === 'function') {
|
|
995
|
+
fn(err);
|
|
996
|
+
} else {
|
|
997
|
+
res.statusCode = 404;
|
|
998
|
+
res.end();
|
|
999
|
+
}
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
const streamOptions = {};
|
|
1003
|
+
const rangeHeader = res.req.headers[exports.HeaderName.RANGE];
|
|
1004
|
+
if (rangeHeader) {
|
|
1005
|
+
const [x, y] = rangeHeader.replace('bytes=', '').split('-');
|
|
1006
|
+
streamOptions.end = Math.min(parseInt(y, 10) || stats.size - 1, stats.size - 1);
|
|
1007
|
+
streamOptions.start = parseInt(x, 10) || 0;
|
|
1008
|
+
if (streamOptions.start >= stats.size || streamOptions.end >= stats.size) {
|
|
1009
|
+
res.setHeader(exports.HeaderName.CONTENT_RANGE, `bytes */${stats.size}`);
|
|
1010
|
+
res.statusCode = 416;
|
|
1011
|
+
res.end();
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
res.setHeader(exports.HeaderName.CONTENT_RANGE, `bytes ${streamOptions.start}-${streamOptions.end}/${stats.size}`);
|
|
1015
|
+
res.setHeader(exports.HeaderName.CONTENT_LENGTH, streamOptions.end - streamOptions.start + 1);
|
|
1016
|
+
} else {
|
|
1017
|
+
res.setHeader(exports.HeaderName.CONTENT_LENGTH, stats.size);
|
|
1018
|
+
}
|
|
1019
|
+
res.setHeader(exports.HeaderName.ACCEPT_RANGES, 'bytes');
|
|
1020
|
+
res.setHeader(exports.HeaderName.LAST_MODIFIED, stats.mtime.toUTCString());
|
|
1021
|
+
res.setHeader(exports.HeaderName.ETag, `W/"${stats.size}-${stats.mtime.getTime()}"`);
|
|
1022
|
+
sendStream(res, node_fs.createReadStream(options?.filePath, streamOptions), fn);
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
/*
|
|
1027
|
+
* Copyright (c) 2022.
|
|
1028
|
+
* Author Peter Placzek (tada5hi)
|
|
1029
|
+
* For the full copyright and license information,
|
|
1030
|
+
* view the LICENSE file that was distributed with this source code.
|
|
1031
|
+
*/ function sendFormat(_res, _format) {}
|
|
1032
|
+
|
|
1033
|
+
function sendRedirect(res, location, statusCode = 302) {
|
|
1034
|
+
res.statusCode = statusCode;
|
|
1035
|
+
res.setHeader('location', location);
|
|
1036
|
+
const encodedLoc = location.replace(/"/g, '%22');
|
|
1037
|
+
const html = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${encodedLoc}"></head></html>`;
|
|
1038
|
+
return send(res, html);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
53
1041
|
function processHandlerExecutionOutput(res, next, output) {
|
|
54
1042
|
if (isPromise(output)) {
|
|
55
1043
|
output.then((r)=>{
|
|
56
1044
|
if (typeof r !== 'undefined') {
|
|
57
|
-
|
|
1045
|
+
send(res, r);
|
|
58
1046
|
}
|
|
59
1047
|
return r;
|
|
60
1048
|
}).catch(next);
|
|
61
1049
|
return;
|
|
62
1050
|
}
|
|
63
1051
|
if (typeof output !== 'undefined') {
|
|
64
|
-
|
|
1052
|
+
send(res, output);
|
|
65
1053
|
}
|
|
66
1054
|
}
|
|
67
1055
|
|
|
@@ -132,8 +1120,8 @@ class Layer {
|
|
|
132
1120
|
return this.fn.length === 4;
|
|
133
1121
|
}
|
|
134
1122
|
dispatch(req, res, meta, next, err) {
|
|
135
|
-
|
|
136
|
-
|
|
1123
|
+
setRequestParams(req, meta.params || {});
|
|
1124
|
+
setRequestMountPath(req, meta.mountPath || '/');
|
|
137
1125
|
if (typeof err !== 'undefined') {
|
|
138
1126
|
if (this.fn.length === 4) {
|
|
139
1127
|
try {
|
|
@@ -195,16 +1183,16 @@ class Route {
|
|
|
195
1183
|
}
|
|
196
1184
|
matchMethod(method) {
|
|
197
1185
|
let name = method.toLowerCase();
|
|
198
|
-
if (name ===
|
|
199
|
-
name =
|
|
1186
|
+
if (name === exports.Method.HEAD && !smob.hasOwnProperty(this.layers, name)) {
|
|
1187
|
+
name = exports.Method.GET;
|
|
200
1188
|
}
|
|
201
1189
|
return Object.prototype.hasOwnProperty.call(this.layers, name);
|
|
202
1190
|
}
|
|
203
1191
|
// --------------------------------------------------
|
|
204
1192
|
getMethods() {
|
|
205
1193
|
const keys = Object.keys(this.layers);
|
|
206
|
-
if (smob.hasOwnProperty(this.layers,
|
|
207
|
-
keys.push(
|
|
1194
|
+
if (smob.hasOwnProperty(this.layers, exports.Method.GET) && !smob.hasOwnProperty(this.layers, exports.Method.HEAD)) {
|
|
1195
|
+
keys.push(exports.Method.HEAD);
|
|
208
1196
|
}
|
|
209
1197
|
return keys;
|
|
210
1198
|
}
|
|
@@ -215,8 +1203,8 @@ class Route {
|
|
|
215
1203
|
return;
|
|
216
1204
|
}
|
|
217
1205
|
let name = req.method.toLowerCase();
|
|
218
|
-
if (name ===
|
|
219
|
-
name =
|
|
1206
|
+
if (name === exports.Method.HEAD && !smob.hasOwnProperty(this.layers, name)) {
|
|
1207
|
+
name = exports.Method.GET;
|
|
220
1208
|
}
|
|
221
1209
|
const layers = this.layers[name];
|
|
222
1210
|
/* istanbul ignore next */ if (typeof layers === 'undefined' || layers.length === 0 || typeof meta.path === 'undefined') {
|
|
@@ -260,25 +1248,25 @@ class Route {
|
|
|
260
1248
|
}
|
|
261
1249
|
}
|
|
262
1250
|
get(...handlers) {
|
|
263
|
-
return this.register(
|
|
1251
|
+
return this.register(exports.Method.GET, ...handlers);
|
|
264
1252
|
}
|
|
265
1253
|
post(...handlers) {
|
|
266
|
-
return this.register(
|
|
1254
|
+
return this.register(exports.Method.POST, ...handlers);
|
|
267
1255
|
}
|
|
268
1256
|
put(...handlers) {
|
|
269
|
-
return this.register(
|
|
1257
|
+
return this.register(exports.Method.PUT, ...handlers);
|
|
270
1258
|
}
|
|
271
1259
|
patch(...handlers) {
|
|
272
|
-
return this.register(
|
|
1260
|
+
return this.register(exports.Method.PATCH, ...handlers);
|
|
273
1261
|
}
|
|
274
1262
|
delete(...handlers) {
|
|
275
|
-
return this.register(
|
|
1263
|
+
return this.register(exports.Method.DELETE, ...handlers);
|
|
276
1264
|
}
|
|
277
1265
|
head(...handlers) {
|
|
278
|
-
return this.register(
|
|
1266
|
+
return this.register(exports.Method.HEAD, ...handlers);
|
|
279
1267
|
}
|
|
280
1268
|
options(...handlers) {
|
|
281
|
-
return this.register(
|
|
1269
|
+
return this.register(exports.Method.OPTIONS, ...handlers);
|
|
282
1270
|
}
|
|
283
1271
|
// --------------------------------------------------
|
|
284
1272
|
isStrictPath() {
|
|
@@ -319,7 +1307,7 @@ class Router {
|
|
|
319
1307
|
return;
|
|
320
1308
|
}
|
|
321
1309
|
if (typeof value === 'string') {
|
|
322
|
-
this.path =
|
|
1310
|
+
this.path = withLeadingSlash(withoutTrailingSlash(`${value}`));
|
|
323
1311
|
} else {
|
|
324
1312
|
this.path = value;
|
|
325
1313
|
}
|
|
@@ -363,24 +1351,24 @@ class Router {
|
|
|
363
1351
|
res.end();
|
|
364
1352
|
return;
|
|
365
1353
|
}
|
|
366
|
-
if (req.method && req.method.toLowerCase() ===
|
|
1354
|
+
if (req.method && req.method.toLowerCase() === exports.Method.OPTIONS) {
|
|
367
1355
|
const options = allowedMethods.map((key)=>key.toUpperCase()).join(',');
|
|
368
|
-
res.setHeader(
|
|
369
|
-
|
|
1356
|
+
res.setHeader(exports.HeaderName.ALLOW, options);
|
|
1357
|
+
send(res, options);
|
|
370
1358
|
return;
|
|
371
1359
|
}
|
|
372
1360
|
res.statusCode = 404;
|
|
373
1361
|
res.end();
|
|
374
1362
|
};
|
|
375
|
-
let path = meta.path ||
|
|
1363
|
+
let path = meta.path || useRequestPath(req);
|
|
376
1364
|
if (this.pathMatcher) {
|
|
377
1365
|
const output = this.pathMatcher.exec(path);
|
|
378
1366
|
if (typeof output !== 'undefined') {
|
|
379
|
-
meta.mountPath =
|
|
1367
|
+
meta.mountPath = cleanDoubleSlashes(`${meta.mountPath || ''}/${output.path}`);
|
|
380
1368
|
if (path === output.path) {
|
|
381
1369
|
path = '/';
|
|
382
1370
|
} else {
|
|
383
|
-
path =
|
|
1371
|
+
path = withLeadingSlash(path.substring(output.path.length));
|
|
384
1372
|
}
|
|
385
1373
|
meta.params = smob.merge(meta.params || {}, output.params);
|
|
386
1374
|
}
|
|
@@ -412,7 +1400,7 @@ class Router {
|
|
|
412
1400
|
match = layer.matchPath(path);
|
|
413
1401
|
if (req.method && !layer.matchMethod(req.method)) {
|
|
414
1402
|
match = false;
|
|
415
|
-
if (req.method.toLowerCase() ===
|
|
1403
|
+
if (req.method.toLowerCase() === exports.Method.OPTIONS) {
|
|
416
1404
|
allowedMethods = smob.mergeArrays(allowedMethods, layer.getMethods(), true);
|
|
417
1405
|
}
|
|
418
1406
|
}
|
|
@@ -429,7 +1417,7 @@ class Router {
|
|
|
429
1417
|
const output = layer.exec(path);
|
|
430
1418
|
if (output) {
|
|
431
1419
|
layerMeta.params = smob.merge(output.params, layerMeta.params || {});
|
|
432
|
-
layerMeta.mountPath =
|
|
1420
|
+
layerMeta.mountPath = cleanDoubleSlashes(`${layerMeta.mountPath || ''}/${output.path}`);
|
|
433
1421
|
}
|
|
434
1422
|
}
|
|
435
1423
|
if (err) {
|
|
@@ -458,7 +1446,7 @@ class Router {
|
|
|
458
1446
|
// --------------------------------------------------
|
|
459
1447
|
route(path) {
|
|
460
1448
|
if (typeof path === 'string' && path.length > 0) {
|
|
461
|
-
path =
|
|
1449
|
+
path = withLeadingSlash(path);
|
|
462
1450
|
}
|
|
463
1451
|
const index = this.stack.findIndex((item)=>isRouteInstance(item) && item.path === path);
|
|
464
1452
|
if (index !== -1) {
|
|
@@ -562,18 +1550,80 @@ exports.Layer = Layer;
|
|
|
562
1550
|
exports.PathMatcher = PathMatcher;
|
|
563
1551
|
exports.Route = Route;
|
|
564
1552
|
exports.Router = Router;
|
|
1553
|
+
exports.appendResponseHeader = appendResponseHeader;
|
|
1554
|
+
exports.appendResponseHeaderDirective = appendResponseHeaderDirective;
|
|
1555
|
+
exports.buildConfig = buildConfig;
|
|
1556
|
+
exports.buildEtagFn = buildEtagFn;
|
|
1557
|
+
exports.buildTrustProxyFn = buildTrustProxyFn;
|
|
1558
|
+
exports.cleanDoubleSlashes = cleanDoubleSlashes;
|
|
565
1559
|
exports.createRequestTimeout = createRequestTimeout;
|
|
1560
|
+
exports.getCharsetForMimeType = getCharsetForMimeType;
|
|
1561
|
+
exports.getConfigOption = getConfigOption;
|
|
1562
|
+
exports.getMimeType = getMimeType;
|
|
1563
|
+
exports.getRequestAcceptableCharset = getRequestAcceptableCharset;
|
|
1564
|
+
exports.getRequestAcceptableCharsets = getRequestAcceptableCharsets;
|
|
1565
|
+
exports.getRequestAcceptableContentType = getRequestAcceptableContentType;
|
|
1566
|
+
exports.getRequestAcceptableContentTypes = getRequestAcceptableContentTypes;
|
|
1567
|
+
exports.getRequestAcceptableEncoding = getRequestAcceptableEncoding;
|
|
1568
|
+
exports.getRequestAcceptableEncodings = getRequestAcceptableEncodings;
|
|
1569
|
+
exports.getRequestAcceptableLanguage = getRequestAcceptableLanguage;
|
|
1570
|
+
exports.getRequestAcceptableLanguages = getRequestAcceptableLanguages;
|
|
1571
|
+
exports.getRequestHeader = getRequestHeader;
|
|
1572
|
+
exports.getRequestHostName = getRequestHostName;
|
|
1573
|
+
exports.getRequestIP = getRequestIP;
|
|
1574
|
+
exports.getRequestProtocol = getRequestProtocol;
|
|
1575
|
+
exports.hasLeadingSlash = hasLeadingSlash;
|
|
1576
|
+
exports.hasRequestCookies = hasRequestCookies;
|
|
1577
|
+
exports.hasRequestQuery = hasRequestQuery;
|
|
1578
|
+
exports.hasTrailingSlash = hasTrailingSlash;
|
|
566
1579
|
exports.isInstance = isInstance;
|
|
567
1580
|
exports.isLayerInstance = isLayerInstance;
|
|
1581
|
+
exports.isObject = isObject;
|
|
568
1582
|
exports.isPath = isPath;
|
|
569
1583
|
exports.isPromise = isPromise;
|
|
1584
|
+
exports.isRequestCacheable = isRequestCacheable;
|
|
570
1585
|
exports.isRouteInstance = isRouteInstance;
|
|
571
1586
|
exports.isRouterInstance = isRouterInstance;
|
|
1587
|
+
exports.matchRequestContentType = matchRequestContentType;
|
|
1588
|
+
exports.onResponseFinished = onResponseFinished;
|
|
572
1589
|
exports.processHandlerExecutionOutput = processHandlerExecutionOutput;
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
1590
|
+
exports.send = send;
|
|
1591
|
+
exports.sendAccepted = sendAccepted;
|
|
1592
|
+
exports.sendCreated = sendCreated;
|
|
1593
|
+
exports.sendFile = sendFile;
|
|
1594
|
+
exports.sendFormat = sendFormat;
|
|
1595
|
+
exports.sendRedirect = sendRedirect;
|
|
1596
|
+
exports.sendStream = sendStream;
|
|
1597
|
+
exports.setConfig = setConfig;
|
|
1598
|
+
exports.setConfigOption = setConfigOption;
|
|
1599
|
+
exports.setRequestBody = setRequestBody;
|
|
1600
|
+
exports.setRequestCookieFn = setRequestCookieFn;
|
|
1601
|
+
exports.setRequestCookies = setRequestCookies;
|
|
1602
|
+
exports.setRequestEnv = setRequestEnv;
|
|
1603
|
+
exports.setRequestHeader = setRequestHeader;
|
|
1604
|
+
exports.setRequestMountPath = setRequestMountPath;
|
|
1605
|
+
exports.setRequestParam = setRequestParam;
|
|
1606
|
+
exports.setRequestParams = setRequestParams;
|
|
1607
|
+
exports.setRequestQuery = setRequestQuery;
|
|
1608
|
+
exports.setRequestQueryFn = setRequestQueryFn;
|
|
1609
|
+
exports.setResponseCacheHeaders = setResponseCacheHeaders;
|
|
1610
|
+
exports.setResponseContentTypeByFileName = setResponseContentTypeByFileName;
|
|
1611
|
+
exports.setResponseHeaderAttachment = setResponseHeaderAttachment;
|
|
1612
|
+
exports.setResponseHeaderContentType = setResponseHeaderContentType;
|
|
1613
|
+
exports.unsetRequestEnv = unsetRequestEnv;
|
|
1614
|
+
exports.useConfig = useConfig;
|
|
1615
|
+
exports.useRequestBody = useRequestBody;
|
|
1616
|
+
exports.useRequestCookie = useRequestCookie;
|
|
1617
|
+
exports.useRequestCookies = useRequestCookies;
|
|
1618
|
+
exports.useRequestEnv = useRequestEnv;
|
|
1619
|
+
exports.useRequestMountPath = useRequestMountPath;
|
|
1620
|
+
exports.useRequestNegotiator = useRequestNegotiator;
|
|
1621
|
+
exports.useRequestParam = useRequestParam;
|
|
1622
|
+
exports.useRequestParams = useRequestParams;
|
|
1623
|
+
exports.useRequestPath = useRequestPath;
|
|
1624
|
+
exports.useRequestQuery = useRequestQuery;
|
|
1625
|
+
exports.withLeadingSlash = withLeadingSlash;
|
|
1626
|
+
exports.withTrailingSlash = withTrailingSlash;
|
|
1627
|
+
exports.withoutLeadingSlash = withoutLeadingSlash;
|
|
1628
|
+
exports.withoutTrailingSlash = withoutTrailingSlash;
|
|
579
1629
|
//# sourceMappingURL=index.cjs.map
|