expediate 1.0.5 → 1.0.6
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/CHANGELOG.md +138 -0
- package/CONTRIBUTING.md +150 -0
- package/README.md +278 -779
- package/dist/apis.d.ts +372 -12
- package/dist/apis.d.ts.map +1 -1
- package/dist/apis.js +483 -65
- package/dist/apis.js.map +1 -1
- package/dist/cjs/index.js +2290 -807
- package/dist/git.d.ts +1 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +5 -5
- package/dist/git.js.map +1 -1
- package/dist/http-objects.d.ts +26 -0
- package/dist/http-objects.d.ts.map +1 -0
- package/dist/http-objects.js +588 -0
- package/dist/http-objects.js.map +1 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/jwt-auth.d.ts +11 -0
- package/dist/jwt-auth.d.ts.map +1 -1
- package/dist/jwt-auth.js +9 -9
- package/dist/jwt-auth.js.map +1 -1
- package/dist/middleware.js +2 -2
- package/dist/middleware.js.map +1 -1
- package/dist/mimetypes.json +882 -1
- package/dist/misc.d.ts +161 -25
- package/dist/misc.d.ts.map +1 -1
- package/dist/misc.js +228 -80
- package/dist/misc.js.map +1 -1
- package/dist/openapi.d.ts +156 -13
- package/dist/openapi.d.ts.map +1 -1
- package/dist/openapi.js +214 -71
- package/dist/openapi.js.map +1 -1
- package/dist/router-types.d.ts +760 -0
- package/dist/router-types.d.ts.map +1 -0
- package/dist/router-types.js +23 -0
- package/dist/router-types.js.map +1 -0
- package/dist/router.d.ts +7 -530
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +128 -375
- package/dist/router.js.map +1 -1
- package/dist/static.d.ts +2 -2
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +77 -22
- package/dist/static.js.map +1 -1
- package/docs/THREAT_MODEL.md +52 -0
- package/docs/api-builder-v2-design.md +644 -0
- package/docs/api-builder-v3-design.md +397 -0
- package/docs/api-builder.md +454 -0
- package/docs/benchmark.md +27 -0
- package/docs/body-parsing.md +223 -0
- package/docs/errors.md +359 -0
- package/docs/expediate.png +0 -0
- package/docs/git.md +139 -0
- package/docs/jwt-auth.md +251 -0
- package/docs/logo.svg +12 -0
- package/docs/middleware.md +264 -0
- package/docs/openapi.md +180 -0
- package/docs/router.md +356 -0
- package/docs/static.md +128 -0
- package/docs/wiki.json +123 -0
- package/package.json +30 -8
- package/dist/cjs/apis.js +0 -327
- package/dist/cjs/git.js +0 -293
- package/dist/cjs/jwt-auth.js +0 -532
- package/dist/cjs/middleware.js +0 -511
- package/dist/cjs/mimetypes.json +0 -1
- package/dist/cjs/misc.js +0 -787
- package/dist/cjs/openapi.js +0 -485
- package/dist/cjs/router.js +0 -898
- package/dist/cjs/static.js +0 -669
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
/* Copyright 2021 Fabien Bavent
|
|
2
|
+
*
|
|
3
|
+
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
4
|
+
* copy of this software and associated documentation files (the "Software"),
|
|
5
|
+
* to deal in the Software without restriction, including without limitation
|
|
6
|
+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
7
|
+
* and/or sell copies of the Software, and to permit persons to whom the
|
|
8
|
+
* Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
*
|
|
10
|
+
* The above copyright notice and this permission notice shall be included
|
|
11
|
+
* in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
14
|
+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
16
|
+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
18
|
+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
19
|
+
* DEALINGS IN THE SOFTWARE.
|
|
20
|
+
*/
|
|
21
|
+
'use strict';
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// HTTP request/response augmentation
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Holds `updateHttpObjects()` — which prepares each req/res pair for router
|
|
26
|
+
// middleware — together with the cookie encode/decode/sign/verify helpers it
|
|
27
|
+
// depends on.
|
|
28
|
+
//
|
|
29
|
+
// Performance note (the reason this file looks the way it does):
|
|
30
|
+
// the Express-compatible req/res helpers (`send`, `json`, `status`, `cookie`,
|
|
31
|
+
// `download`, `text`, `formData`, …) are defined ONCE on two shared prototype
|
|
32
|
+
// objects, not re-allocated as closures on every request. `updateHttpObjects`
|
|
33
|
+
// only sets the genuinely per-request DATA fields (path, params, cookies, ip…)
|
|
34
|
+
// and then splices the shared prototype into the object's chain via
|
|
35
|
+
// `Object.setPrototypeOf`. The helpers read `this` instead of capturing the
|
|
36
|
+
// `req`/`res`/`secret` in a closure, so nothing per-helper is allocated.
|
|
37
|
+
// The only per-request state the helpers cannot read from `this` directly —
|
|
38
|
+
// the cookie-signing secret — is stashed on the response under a private
|
|
39
|
+
// symbol; `res.download` reaches the request through Node's standard `res.req`.
|
|
40
|
+
import * as crypto from 'crypto';
|
|
41
|
+
import * as fs from 'fs';
|
|
42
|
+
import * as path from 'path';
|
|
43
|
+
import { mime, serveFile } from './static.js';
|
|
44
|
+
import { parseMultipartBody, extractCharset, readReqBody } from './misc.js';
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Cookie helpers
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
/**
|
|
49
|
+
* Decode a raw cookie value, stripping the `j:` prefix and JSON-parsing the
|
|
50
|
+
* payload when present. Plain string values are returned unchanged.
|
|
51
|
+
*
|
|
52
|
+
* @param raw - The raw cookie value as it appears after the `=` in the header.
|
|
53
|
+
* @returns The decoded value: a JS value for `j:` cookies, or the raw string.
|
|
54
|
+
*/
|
|
55
|
+
function decodeJsonCookie(raw) {
|
|
56
|
+
if (!raw.startsWith('j:'))
|
|
57
|
+
return raw;
|
|
58
|
+
try {
|
|
59
|
+
return JSON.parse(raw.slice(2));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return raw; // malformed JSON — fall back to raw string
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Percent-encode a cookie value for safe transport in a `Set-Cookie` header.
|
|
67
|
+
*
|
|
68
|
+
* RFC 6265 forbids whitespace, double quotes, commas, semicolons, and
|
|
69
|
+
* backslashes in a bare cookie value. `encodeURIComponent` escapes all of
|
|
70
|
+
* these (and the `:` / `{` / `}` / `"` produced by the `s:` and `j:` wire
|
|
71
|
+
* formats), and {@link decodeCookieValue} reverses it on the way in.
|
|
72
|
+
*
|
|
73
|
+
* @param value - The raw cookie value (may include an `s:`/`j:` prefix).
|
|
74
|
+
* @returns The percent-encoded value.
|
|
75
|
+
*/
|
|
76
|
+
function encodeCookieValue(value) {
|
|
77
|
+
return encodeURIComponent(value);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Decode a raw cookie value taken from a `Cookie` request header.
|
|
81
|
+
*
|
|
82
|
+
* Strips an optional surrounding double-quoted form (RFC 6265 quoted-string),
|
|
83
|
+
* then percent-decodes the result. Malformed percent-sequences fall back to
|
|
84
|
+
* the (de-quoted) raw string so a single bad cookie never throws.
|
|
85
|
+
*
|
|
86
|
+
* @param raw - The raw value as it appears after `=` in the header.
|
|
87
|
+
* @returns The decoded value, ready for `s:`/`j:` interpretation.
|
|
88
|
+
*/
|
|
89
|
+
function decodeCookieValue(raw) {
|
|
90
|
+
let val = raw;
|
|
91
|
+
if (val.length >= 2 && val.charCodeAt(0) === 0x22 && val.charCodeAt(val.length - 1) === 0x22)
|
|
92
|
+
val = val.slice(1, -1); // strip surrounding double quotes
|
|
93
|
+
try {
|
|
94
|
+
return decodeURIComponent(val);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return val; // malformed percent-encoding — use the raw (de-quoted) string
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Sign a cookie value with HMAC-SHA256.
|
|
102
|
+
*
|
|
103
|
+
* The produced string follows the `cookie-signature` wire format:
|
|
104
|
+
* `s:<value>.<base64url-HMAC>`, where `<value>` is the raw (possibly
|
|
105
|
+
* `j:`-prefixed) string and the HMAC is computed over that raw string.
|
|
106
|
+
*
|
|
107
|
+
* @param value - The raw cookie value to sign (may include a `j:` prefix).
|
|
108
|
+
* @param secret - The HMAC secret.
|
|
109
|
+
* @returns The signed cookie string with the `s:` prefix.
|
|
110
|
+
*/
|
|
111
|
+
function signCookieValue(value, secret) {
|
|
112
|
+
const sig = crypto
|
|
113
|
+
.createHmac('sha256', secret)
|
|
114
|
+
.update(value)
|
|
115
|
+
.digest('base64url');
|
|
116
|
+
return `s:${value}.${sig}`;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Verify and decode a signed cookie value.
|
|
120
|
+
*
|
|
121
|
+
* The input must start with `s:` and follow the format produced by
|
|
122
|
+
* {@link signCookieValue}: `s:<value>.<base64url-HMAC>`.
|
|
123
|
+
*
|
|
124
|
+
* Uses `crypto.timingSafeEqual` to prevent timing-based signature attacks.
|
|
125
|
+
*
|
|
126
|
+
* @param signed - The raw `Set-Cookie` value including the `s:` prefix.
|
|
127
|
+
* @param secret - The HMAC secret to verify against.
|
|
128
|
+
* @returns The inner value string on success, or `false` when the signature
|
|
129
|
+
* is absent or does not match (indicating a tampered cookie).
|
|
130
|
+
*/
|
|
131
|
+
function verifyCookieValue(signed, secret) {
|
|
132
|
+
if (!signed.startsWith('s:'))
|
|
133
|
+
return false;
|
|
134
|
+
const withoutPrefix = signed.slice(2);
|
|
135
|
+
const lastDot = withoutPrefix.lastIndexOf('.');
|
|
136
|
+
if (lastDot === -1)
|
|
137
|
+
return false;
|
|
138
|
+
const value = withoutPrefix.slice(0, lastDot);
|
|
139
|
+
const received = withoutPrefix.slice(lastDot + 1);
|
|
140
|
+
const expected = crypto
|
|
141
|
+
.createHmac('sha256', secret)
|
|
142
|
+
.update(value)
|
|
143
|
+
.digest('base64url');
|
|
144
|
+
const receivedBuf = Buffer.from(received, 'base64url');
|
|
145
|
+
const expectedBuf = Buffer.from(expected, 'base64url');
|
|
146
|
+
if (receivedBuf.length !== expectedBuf.length)
|
|
147
|
+
return false;
|
|
148
|
+
if (!crypto.timingSafeEqual(receivedBuf, expectedBuf))
|
|
149
|
+
return false;
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// Per-request state carried on the object (not via closures)
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
/**
|
|
156
|
+
* Private key under which the cookie-signing secret is stashed on each
|
|
157
|
+
* response. The shared prototype's `cookie()` reads it from `this` instead of
|
|
158
|
+
* closing over a per-request `secret` variable.
|
|
159
|
+
*/
|
|
160
|
+
const kSecret = Symbol('expediate.secret');
|
|
161
|
+
/**
|
|
162
|
+
* Private key linking a request back to its response. `req.json()/text()/
|
|
163
|
+
* formData()` pass it to {@link readReqBody} so the optional `verify` hook is
|
|
164
|
+
* invoked with `(req, res, buf)` — Node's `IncomingMessage` has no `res`
|
|
165
|
+
* backlink of its own, so the router threads it on here.
|
|
166
|
+
*/
|
|
167
|
+
const kRes = Symbol('expediate.res');
|
|
168
|
+
/**
|
|
169
|
+
* Resolve user-supplied {@link BodyOptions} into the concrete option object
|
|
170
|
+
* expected by {@link readReqBody}. A free function (no per-request closure):
|
|
171
|
+
* it depends only on its `opts` argument.
|
|
172
|
+
*/
|
|
173
|
+
function resolveReqOpts(opts) {
|
|
174
|
+
return {
|
|
175
|
+
limit: opts?.limit ?? '100kb',
|
|
176
|
+
inflate: opts?.inflate ?? true,
|
|
177
|
+
reviver: null,
|
|
178
|
+
strict: opts?.strict ?? false,
|
|
179
|
+
// readReqBody takes its expected mimetype as an explicit argument, so the
|
|
180
|
+
// type matcher here is unused; null keeps the object shape-compatible.
|
|
181
|
+
type: null,
|
|
182
|
+
verify: opts?.verify ?? null,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** Status-line reason phrases used by `res.sendStatus()` (hoisted, shared). */
|
|
186
|
+
const STATUS_MESSAGES = {
|
|
187
|
+
100: 'Continue', 101: 'Switching Protocols', 102: 'Processing',
|
|
188
|
+
200: 'OK', 201: 'Created', 202: 'Accepted', 204: 'No Content',
|
|
189
|
+
206: 'Partial Content', 207: 'Multi-Status',
|
|
190
|
+
300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found',
|
|
191
|
+
303: 'See Other', 304: 'Not Modified', 307: 'Temporary Redirect',
|
|
192
|
+
308: 'Permanent Redirect',
|
|
193
|
+
400: 'Bad Request', 401: 'Unauthorized', 402: 'Payment Required',
|
|
194
|
+
403: 'Forbidden', 404: 'Not Found', 405: 'Method Not Allowed',
|
|
195
|
+
406: 'Not Acceptable', 408: 'Request Timeout', 409: 'Conflict',
|
|
196
|
+
410: 'Gone', 411: 'Length Required', 413: 'Payload Too Large',
|
|
197
|
+
415: 'Unsupported Media Type', 422: 'Unprocessable Entity',
|
|
198
|
+
429: 'Too Many Requests',
|
|
199
|
+
500: 'Internal Server Error', 501: 'Not Implemented',
|
|
200
|
+
502: 'Bad Gateway', 503: 'Service Unavailable', 504: 'Gateway Timeout',
|
|
201
|
+
};
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
// Shared request helpers (defined once; spliced onto each req via prototype)
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
const requestHelpers = {
|
|
206
|
+
/** Read and parse the request body as JSON (cached after first read). */
|
|
207
|
+
json(opts) {
|
|
208
|
+
// If a body-parsing middleware already consumed the stream, return the cached value.
|
|
209
|
+
if ('body' in this)
|
|
210
|
+
return Promise.resolve(this.body ?? null);
|
|
211
|
+
return readReqBody(this, resolveReqOpts(opts), 'application/json', this[kRes])
|
|
212
|
+
.then(ret => {
|
|
213
|
+
if (ret == null)
|
|
214
|
+
return null;
|
|
215
|
+
const charset = extractCharset(ret.mimetype);
|
|
216
|
+
try {
|
|
217
|
+
const parsed = JSON.parse(ret.content.toString(charset), opts?.reviver ?? undefined);
|
|
218
|
+
this.body = parsed;
|
|
219
|
+
return parsed;
|
|
220
|
+
}
|
|
221
|
+
catch (ex) {
|
|
222
|
+
return Promise.reject({ status: 400, message: 'Bad Request: ' + ex.message });
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
},
|
|
226
|
+
/** Read and decode the request body as plain text (cached after first read). */
|
|
227
|
+
text(opts) {
|
|
228
|
+
const cached = this.body;
|
|
229
|
+
if (typeof cached === 'string')
|
|
230
|
+
return Promise.resolve(cached);
|
|
231
|
+
return readReqBody(this, resolveReqOpts(opts), null, this[kRes])
|
|
232
|
+
.then(ret => {
|
|
233
|
+
if (ret == null)
|
|
234
|
+
return null;
|
|
235
|
+
const charset = extractCharset(ret.mimetype);
|
|
236
|
+
return ret.content.toString(charset);
|
|
237
|
+
});
|
|
238
|
+
},
|
|
239
|
+
/** Read and parse the request body as `multipart/form-data` (cached). */
|
|
240
|
+
formData(opts) {
|
|
241
|
+
const cached = this.body;
|
|
242
|
+
if (Array.isArray(cached))
|
|
243
|
+
return Promise.resolve(cached);
|
|
244
|
+
return readReqBody(this, resolveReqOpts(opts), 'multipart/form-data', this[kRes])
|
|
245
|
+
.then(ret => {
|
|
246
|
+
if (ret == null)
|
|
247
|
+
return null;
|
|
248
|
+
try {
|
|
249
|
+
const parts = parseMultipartBody(ret.mimetype, ret.content);
|
|
250
|
+
this.body = parts;
|
|
251
|
+
return parts;
|
|
252
|
+
}
|
|
253
|
+
catch (ex) {
|
|
254
|
+
const e = ex;
|
|
255
|
+
return Promise.reject({ status: e.status ?? 500, message: e.message ?? String(ex) });
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
},
|
|
259
|
+
/** Read a request header by name (case-insensitive; referer/referrer alias). */
|
|
260
|
+
header(name) {
|
|
261
|
+
const key = name.toLowerCase();
|
|
262
|
+
// Express treats the two spellings of the referer header as equivalent.
|
|
263
|
+
if (key === 'referer' || key === 'referrer')
|
|
264
|
+
return this.headers.referer ?? this.headers.referrer;
|
|
265
|
+
return this.headers[key];
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// Shared response helpers (defined once; spliced onto each res via prototype)
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
const responseHelpers = {
|
|
272
|
+
send(data) {
|
|
273
|
+
if (data)
|
|
274
|
+
this.write(data);
|
|
275
|
+
this.end();
|
|
276
|
+
},
|
|
277
|
+
json(data) {
|
|
278
|
+
this.setHeader('Content-Type', 'application/json');
|
|
279
|
+
this.write(JSON.stringify(data));
|
|
280
|
+
this.end();
|
|
281
|
+
},
|
|
282
|
+
status(code, headers) {
|
|
283
|
+
if (!Number.isInteger(code) || code < 100 || code > 999)
|
|
284
|
+
throw new RangeError(`Invalid status code: ${code}. Must be an integer between 100 and 999.`);
|
|
285
|
+
this.statusCode = code;
|
|
286
|
+
if (headers)
|
|
287
|
+
for (const [k, v] of Object.entries(headers))
|
|
288
|
+
this.setHeader(k, v);
|
|
289
|
+
return this;
|
|
290
|
+
},
|
|
291
|
+
redirect(url) {
|
|
292
|
+
this.setHeader('location', url);
|
|
293
|
+
this.writeHead(302);
|
|
294
|
+
this.write(`Found. Redirecting to ${url}`);
|
|
295
|
+
this.end();
|
|
296
|
+
},
|
|
297
|
+
cookie(name, value, options) {
|
|
298
|
+
const opts = options ?? {};
|
|
299
|
+
// Serialise: objects get the j: prefix so the reader can JSON-decode them.
|
|
300
|
+
let val = typeof value === 'object' ? 'j:' + JSON.stringify(value) : String(value);
|
|
301
|
+
if (opts.signed) {
|
|
302
|
+
const secret = this[kSecret];
|
|
303
|
+
if (!secret)
|
|
304
|
+
throw new Error('Signed cookies require a secret — pass { secret } to createRouter()');
|
|
305
|
+
val = signCookieValue(val, secret);
|
|
306
|
+
}
|
|
307
|
+
// Percent-encode the final value (after any j:/s: wrapping) so special
|
|
308
|
+
// characters are transmitted safely; decodeCookieValue() reverses it.
|
|
309
|
+
let txt = `${name}=${encodeCookieValue(val)}`;
|
|
310
|
+
if (opts.maxAge != null) {
|
|
311
|
+
const maxAgeMs = opts.maxAge;
|
|
312
|
+
const maxAgeSec = Math.floor(maxAgeMs / 1000);
|
|
313
|
+
// Only derive Expires from maxAge when maxAge > 0; a zero maxAge is used
|
|
314
|
+
// for clearing cookies and the caller may have already set opts.expires
|
|
315
|
+
// to the epoch — do not overwrite it.
|
|
316
|
+
if (maxAgeMs > 0)
|
|
317
|
+
opts.expires = new Date(Date.now() + maxAgeMs);
|
|
318
|
+
txt += `; Max-Age=${maxAgeSec}`;
|
|
319
|
+
}
|
|
320
|
+
if (opts.expires)
|
|
321
|
+
txt += `; Expires=${opts.expires.toUTCString()}`;
|
|
322
|
+
txt += `; Path=${opts.path ?? '/'}`;
|
|
323
|
+
if (opts.httpOnly)
|
|
324
|
+
txt += '; HttpOnly';
|
|
325
|
+
if (opts.secure)
|
|
326
|
+
txt += '; Secure';
|
|
327
|
+
if (opts.sameSite)
|
|
328
|
+
txt += `; SameSite=${opts.sameSite}`;
|
|
329
|
+
// Append rather than overwrite so multiple cookies can be set on the same
|
|
330
|
+
// response. res.setHeader() would replace any previously set Set-Cookie
|
|
331
|
+
// header; instead, accumulate into an array.
|
|
332
|
+
const existing = this.getHeader('Set-Cookie');
|
|
333
|
+
if (existing == null) {
|
|
334
|
+
this.setHeader('Set-Cookie', txt);
|
|
335
|
+
}
|
|
336
|
+
else if (Array.isArray(existing)) {
|
|
337
|
+
this.setHeader('Set-Cookie', [...existing, txt]);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
this.setHeader('Set-Cookie', [existing, txt]);
|
|
341
|
+
}
|
|
342
|
+
return this;
|
|
343
|
+
},
|
|
344
|
+
download(filepath, filename) {
|
|
345
|
+
const rReq = this.req;
|
|
346
|
+
const name = filename ?? path.basename(filepath);
|
|
347
|
+
// Use double-quotes and escape any double-quote in the filename per RFC 6266.
|
|
348
|
+
const safeName = name.replace(/"/g, '\\"');
|
|
349
|
+
this.setHeader('Content-Disposition', `attachment; filename="${safeName}"`);
|
|
350
|
+
// Guard: return 404 when the file does not exist (serveFile would send 500
|
|
351
|
+
// for any stat error; we want the conventional 404 for downloads).
|
|
352
|
+
fs.access(filepath, fs.constants.F_OK, (err) => {
|
|
353
|
+
if (err) {
|
|
354
|
+
if (!this.writableEnded)
|
|
355
|
+
this.status(404).end('Not Found');
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
serveFile(filepath)(rReq, this, () => { });
|
|
359
|
+
});
|
|
360
|
+
},
|
|
361
|
+
type(mimeType) {
|
|
362
|
+
this.setHeader('Content-Type', mimeType);
|
|
363
|
+
return this;
|
|
364
|
+
},
|
|
365
|
+
etag(value, strong = false) {
|
|
366
|
+
this.setHeader('ETag', strong ? `"${value}"` : `W/"${value}"`);
|
|
367
|
+
return this;
|
|
368
|
+
},
|
|
369
|
+
header(field, value) {
|
|
370
|
+
this.setHeader(field, value);
|
|
371
|
+
return this;
|
|
372
|
+
},
|
|
373
|
+
append(field, value) {
|
|
374
|
+
const existing = this.getHeader(field);
|
|
375
|
+
if (existing == null) {
|
|
376
|
+
this.setHeader(field, value);
|
|
377
|
+
}
|
|
378
|
+
else if (field.toLowerCase() === 'set-cookie') {
|
|
379
|
+
// Set-Cookie must accumulate as an array (multiple values not comma-joinable).
|
|
380
|
+
const prev = Array.isArray(existing) ? existing : [String(existing)];
|
|
381
|
+
const next = Array.isArray(value) ? value : [value];
|
|
382
|
+
this.setHeader(field, [...prev, ...next]);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
const prev = Array.isArray(existing) ? existing.join(', ') : String(existing);
|
|
386
|
+
const added = Array.isArray(value) ? value.join(', ') : value;
|
|
387
|
+
this.setHeader(field, `${prev}, ${added}`);
|
|
388
|
+
}
|
|
389
|
+
return this;
|
|
390
|
+
},
|
|
391
|
+
vary(field) {
|
|
392
|
+
const fields = Array.isArray(field) ? field : [field];
|
|
393
|
+
const existing = this.getHeader('Vary');
|
|
394
|
+
const current = existing
|
|
395
|
+
? (Array.isArray(existing) ? existing : [String(existing)])
|
|
396
|
+
.join(', ')
|
|
397
|
+
.split(',')
|
|
398
|
+
.map(s => s.trim().toLowerCase())
|
|
399
|
+
: [];
|
|
400
|
+
for (const f of fields) {
|
|
401
|
+
if (!current.includes(f.toLowerCase())) {
|
|
402
|
+
current.push(f.toLowerCase());
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
this.setHeader('Vary', current.join(', '));
|
|
406
|
+
return this;
|
|
407
|
+
},
|
|
408
|
+
location(url) {
|
|
409
|
+
this.setHeader('Location', url);
|
|
410
|
+
return this;
|
|
411
|
+
},
|
|
412
|
+
clearCookie(name, options) {
|
|
413
|
+
const opts = { ...options, expires: new Date(0), maxAge: 0 };
|
|
414
|
+
// Remove signed flag — clearing does not need signing.
|
|
415
|
+
delete opts.signed;
|
|
416
|
+
this.cookie(name, '', opts);
|
|
417
|
+
return this;
|
|
418
|
+
},
|
|
419
|
+
sendStatus(code) {
|
|
420
|
+
this.setHeader('Content-Type', 'text/plain');
|
|
421
|
+
this.statusCode = code;
|
|
422
|
+
this.end(STATUS_MESSAGES[code] ?? String(code));
|
|
423
|
+
},
|
|
424
|
+
attachment(filename) {
|
|
425
|
+
if (filename) {
|
|
426
|
+
const mimeType = mime.lookup(filename, 'application/octet-stream');
|
|
427
|
+
this.setHeader('Content-Type', mimeType);
|
|
428
|
+
const safeName = path.basename(filename).replace(/"/g, '\\"');
|
|
429
|
+
this.setHeader('Content-Disposition', `attachment; filename="${safeName}"`);
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
this.setHeader('Content-Disposition', 'attachment');
|
|
433
|
+
}
|
|
434
|
+
return this;
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
// ---------------------------------------------------------------------------
|
|
438
|
+
// Prototype derivation — one custom prototype per native base, cached
|
|
439
|
+
// ---------------------------------------------------------------------------
|
|
440
|
+
/**
|
|
441
|
+
* Cache of derived prototypes keyed by the object's native prototype. There is
|
|
442
|
+
* one entry per transport kind (HTTP/1 request, HTTP/1 response, HTTP/2
|
|
443
|
+
* request, HTTP/2 response), so these maps hold at most a handful of entries
|
|
444
|
+
* for the lifetime of the process.
|
|
445
|
+
*/
|
|
446
|
+
const reqProtoCache = new WeakMap();
|
|
447
|
+
const resProtoCache = new WeakMap();
|
|
448
|
+
/**
|
|
449
|
+
* Return a prototype that layers `helpers` on top of `obj`'s current native
|
|
450
|
+
* prototype, creating and caching it on first use. The returned prototype keeps
|
|
451
|
+
* every native method (it chains to the original prototype) and adds ours.
|
|
452
|
+
*/
|
|
453
|
+
function ensureProto(cache, obj, helpers) {
|
|
454
|
+
const base = Object.getPrototypeOf(obj);
|
|
455
|
+
let proto = cache.get(base);
|
|
456
|
+
if (proto === undefined) {
|
|
457
|
+
proto = Object.assign(Object.create(base), helpers);
|
|
458
|
+
cache.set(base, proto);
|
|
459
|
+
}
|
|
460
|
+
return proto;
|
|
461
|
+
}
|
|
462
|
+
// ---------------------------------------------------------------------------
|
|
463
|
+
// HTTP object augmentation
|
|
464
|
+
// ---------------------------------------------------------------------------
|
|
465
|
+
/**
|
|
466
|
+
* Prepare a raw `http.IncomingMessage` / `http.ServerResponse` pair for router
|
|
467
|
+
* middleware: attach the shared helper prototypes and populate the per-request
|
|
468
|
+
* data fields the helpers (and the router) rely on.
|
|
469
|
+
*
|
|
470
|
+
* This function is idempotent — it exits immediately when `req.queries` is
|
|
471
|
+
* already defined, so it is safe to call multiple times on the same pair (as
|
|
472
|
+
* happens with nested routers sharing one request object).
|
|
473
|
+
*
|
|
474
|
+
* **Fields added to `req`:** `originalUrl`, `path`, `params`, `query`,
|
|
475
|
+
* `queries`, `cookies`, `ip`, `ips`, `protocol`, `secure`, `hostname`,
|
|
476
|
+
* `baseUrl`. Helper methods (`json`, `text`, `formData`, `header`) come from
|
|
477
|
+
* the shared request prototype.
|
|
478
|
+
*
|
|
479
|
+
* **Fields added to `res`:** `locals` and the cookie-signing secret (under a
|
|
480
|
+
* private symbol). Helper methods (`send`, `json`, `status`, `cookie`,
|
|
481
|
+
* `download`, …) come from the shared response prototype.
|
|
482
|
+
*
|
|
483
|
+
* @param req - The raw incoming message to augment.
|
|
484
|
+
* @param res - The raw server response to augment.
|
|
485
|
+
* @param secret - Optional cookie-signing secret.
|
|
486
|
+
* @param trustProxy - When `true`, resolve `req.ip` from `X-Forwarded-For`.
|
|
487
|
+
*/
|
|
488
|
+
export function updateHttpObjects(req, res, secret, trustProxy) {
|
|
489
|
+
const rReq = req;
|
|
490
|
+
const rRes = res;
|
|
491
|
+
if (rReq.queries)
|
|
492
|
+
return; // Already augmented.
|
|
493
|
+
// Splice the shared helper prototypes into the chain once, before any other
|
|
494
|
+
// mutation. The helpers read `this`, so no per-request closures are created.
|
|
495
|
+
Object.setPrototypeOf(req, ensureProto(reqProtoCache, req, requestHelpers));
|
|
496
|
+
Object.setPrototypeOf(res, ensureProto(resProtoCache, res, responseHelpers));
|
|
497
|
+
rReq.queries = {};
|
|
498
|
+
// Resolve the client IP address and proxy-related fields.
|
|
499
|
+
// When trustProxy is true the leftmost value in X-Forwarded-For is used
|
|
500
|
+
// (the originating client behind the proxy chain). Otherwise we read the
|
|
501
|
+
// raw TCP remote address directly from the socket, which cannot be spoofed.
|
|
502
|
+
if (trustProxy) {
|
|
503
|
+
const xff = req.headers['x-forwarded-for'];
|
|
504
|
+
const xffStr = Array.isArray(xff) ? xff.join(',') : (xff ?? '');
|
|
505
|
+
rReq.ips = xffStr ? xffStr.split(',').map(s => s.trim()) : [];
|
|
506
|
+
rReq.ip = rReq.ips[0] ?? req.socket?.remoteAddress ?? '';
|
|
507
|
+
const xProto = req.headers['x-forwarded-proto'];
|
|
508
|
+
rReq.protocol = (Array.isArray(xProto) ? xProto[0] : xProto)?.split(',')[0].trim() ?? 'http';
|
|
509
|
+
const xHost = req.headers['x-forwarded-host'];
|
|
510
|
+
const hostHeader = (Array.isArray(xHost) ? xHost[0] : xHost) ?? req.headers.host ?? '';
|
|
511
|
+
rReq.hostname = hostHeader.replace(/:\d+$/, '');
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
rReq.ip = req.socket?.remoteAddress ?? '';
|
|
515
|
+
rReq.ips = [];
|
|
516
|
+
rReq.protocol = req.socket?.encrypted ? 'https' : 'http';
|
|
517
|
+
rReq.hostname = (req.headers.host ?? '').replace(/:\d+$/, '');
|
|
518
|
+
}
|
|
519
|
+
rReq.secure = rReq.protocol === 'https';
|
|
520
|
+
rReq.baseUrl = rReq.baseUrl ?? '';
|
|
521
|
+
const qry = new URL(`http://${req.headers.host}${req.url}`);
|
|
522
|
+
rReq.originalUrl = req.url;
|
|
523
|
+
rReq.path = qry.pathname;
|
|
524
|
+
// Parse URL query parameters.
|
|
525
|
+
// FEAT-03: repeated keys (e.g. ?tag=a&tag=b) accumulate into arrays.
|
|
526
|
+
const urlParams = {};
|
|
527
|
+
for (const [key, value] of qry.searchParams.entries()) {
|
|
528
|
+
const existing = urlParams[key];
|
|
529
|
+
if (existing === undefined) {
|
|
530
|
+
urlParams[key] = value;
|
|
531
|
+
}
|
|
532
|
+
else if (Array.isArray(existing)) {
|
|
533
|
+
existing.push(value);
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
urlParams[key] = [existing, value];
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
rReq.queries.url = urlParams;
|
|
540
|
+
// params stays StringMap — use first value for repeated keys.
|
|
541
|
+
const flatParams = {};
|
|
542
|
+
for (const [key, value] of Object.entries(urlParams)) {
|
|
543
|
+
flatParams[key] = Array.isArray(value) ? value[0] : value;
|
|
544
|
+
}
|
|
545
|
+
rReq.params = flatParams;
|
|
546
|
+
rReq.query = urlParams;
|
|
547
|
+
// Parse cookies.
|
|
548
|
+
if (rReq.cookies == null) {
|
|
549
|
+
rReq.cookies = {};
|
|
550
|
+
if (req.headers.cookie) {
|
|
551
|
+
for (const part of req.headers.cookie.split(';')) {
|
|
552
|
+
const eqIdx = part.indexOf('=');
|
|
553
|
+
if (eqIdx === -1)
|
|
554
|
+
continue;
|
|
555
|
+
const name = part.slice(0, eqIdx).trim();
|
|
556
|
+
// De-quote and percent-decode before interpreting s:/j: prefixes, so
|
|
557
|
+
// values containing semicolons, commas, quotes, or spaces round-trip.
|
|
558
|
+
const rawVal = decodeCookieValue(part.slice(eqIdx + 1).trim());
|
|
559
|
+
if (rawVal.startsWith('s:')) {
|
|
560
|
+
// Signed cookie — verify the HMAC signature.
|
|
561
|
+
if (secret) {
|
|
562
|
+
const inner = verifyCookieValue(rawVal, secret);
|
|
563
|
+
if (inner === false)
|
|
564
|
+
continue; // tampered — silently omit
|
|
565
|
+
rReq.cookies[name] = decodeJsonCookie(inner);
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
// No secret configured — include the raw value so the application
|
|
569
|
+
// can at least inspect that a signed cookie was sent.
|
|
570
|
+
rReq.cookies[name] = rawVal;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
// Plain or JSON-encoded cookie.
|
|
575
|
+
rReq.cookies[name] = decodeJsonCookie(rawVal);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
// Stash the signing secret so res.cookie()/clearCookie() can read it from the
|
|
581
|
+
// object rather than from a captured closure variable, and link req → res so
|
|
582
|
+
// the body readers can forward the response to readReqBody's verify hook.
|
|
583
|
+
rRes[kSecret] = secret;
|
|
584
|
+
rReq[kRes] = rRes;
|
|
585
|
+
rRes.locals = {};
|
|
586
|
+
rRes.setHeader('X-Powered-By', 'Expediate');
|
|
587
|
+
}
|
|
588
|
+
//# sourceMappingURL=http-objects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-objects.js","sourceRoot":"","sources":["../src/http-objects.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import createRouter from './router.js';
|
|
6
6
|
export { createRouter };
|
|
7
|
-
export type { Router, RouterOptions, RouterRequest, RouterResponse, Middleware, MiddlewareArg, NextFunction, ErrorHandler, Layer, RouteInfo, CookieOptions, TlsOptions, StringMap, } from './router.js';
|
|
7
|
+
export type { Router, RouterOptions, RouterRequest, RouterResponse, Middleware, MiddlewareArg, NextFunction, ErrorHandler, ErrorMiddleware, Layer, RouteInfo, RouteBuilder, CookieOptions, TlsOptions, StringMap, } from './router.js';
|
|
8
8
|
export { serveStatic, serveFile, sendFile, mime } from './static.js';
|
|
9
9
|
export type { StaticOptions, Mime } from './static.js';
|
|
10
|
-
export { json, formData, formEncoded, parseBody, logger, cors, streamFormData, parseMultipartBody } from './misc.js';
|
|
11
|
-
export type { BodyOptions, LoggerOptions, FormPart, FormPartStream, CorsOptions, } from './misc.js';
|
|
10
|
+
export { json, formData, formEncoded, raw, text, parseBody, logger, cors, streamFormData, parseMultipartBody } from './misc.js';
|
|
11
|
+
export type { BodyOptions, BodyTypeMatcher, VerifyFn, LoggerOptions, FormPart, FormPartStream, CorsOptions, } from './misc.js';
|
|
12
12
|
import createJwtPlugin from './jwt-auth.js';
|
|
13
13
|
export { createJwtPlugin };
|
|
14
14
|
export { createMapTokenStore } from './jwt-auth.js';
|
|
@@ -17,9 +17,10 @@ export { gitHandler, gitCreate } from './git.js';
|
|
|
17
17
|
export type { GitHandlerOptions, } from './git.js';
|
|
18
18
|
import apiBuilder from './apis.js';
|
|
19
19
|
export { apiBuilder };
|
|
20
|
-
export
|
|
20
|
+
export { defineController } from './apis.js';
|
|
21
|
+
export type { ApiError, ServiceMethod, ServiceInstance, ServiceMethods, RouteMap, ServiceDefinition, ControllerDefinition, Guard, AuthBinding, ApiBuilderOptions, ApiRouter, ApiRouterExtensions, ApiContext, } from './apis.js';
|
|
21
22
|
export { describe, openApiSpec, serializeSpec, DESCRIBE_META } from './openapi.js';
|
|
22
|
-
export type { JsonSchema, ParameterObject, RequestBodyObject, ResponseObject, OperationMeta, OpenApiServiceMeta, SpecOptions, SpecFormat, OpenApiDocument, } from './openapi.js';
|
|
23
|
+
export type { JsonSchema, ParameterObject, RequestBodyObject, ResponseObject, OperationMeta, OpenApiServiceMeta, RouteOpenApi, ControllerOpenApi, ServiceOpenApi, OpenApiSource, SpecOptions, SpecFormat, OpenApiDocument, } from './openapi.js';
|
|
23
24
|
export { compress, requestId, rateLimit, cacheControl, csrf, securityHeaders, conditionalGet } from './middleware.js';
|
|
24
25
|
export type { CompressOptions, RequestIdOptions, RateLimitOptions, CacheControlOptions, CsrfOptions, SecurityHeadersOptions, } from './middleware.js';
|
|
25
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AAGH,OAAO,YAAY,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EACV,MAAM,EACN,aAAa,EACb,aAAa,EACb,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,SAAS,GACV,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EACV,aAAa,EACb,IAAI,EACL,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AAGH,OAAO,YAAY,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EACV,MAAM,EACN,aAAa,EACb,aAAa,EACb,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,KAAK,EACL,SAAS,EACT,YAAY,EACZ,aAAa,EACb,UAAU,EACV,SAAS,GACV,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EACV,aAAa,EACb,IAAI,EACL,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAChI,YAAY,EACV,WAAW,EACX,eAAe,EACf,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AAGnB,OAAO,eAAe,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,UAAU,GACX,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACjD,YAAY,EACR,iBAAiB,GACpB,MAAM,UAAU,CAAC;AAGlB,OAAO,UAAU,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,CAAA;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EACR,QAAQ,EACR,aAAa,EACb,eAAe,EACf,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,mBAAmB,EACnB,UAAU,GACb,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACnF,YAAY,EACR,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,WAAW,EACX,UAAU,EACV,eAAe,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtH,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,sBAAsB,GACvB,MAAM,iBAAiB,CAAC"}
|