@wooksjs/event-http 0.5.25 → 0.6.1
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/dist/index.cjs +475 -299
- package/dist/index.d.ts +66 -3
- package/dist/index.mjs +453 -277
- package/package.json +7 -8
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { attachHook, createAsyncEventContext, useAsyncEventContext, useEventId, useEventLogger, useRouteParams } from "@wooksjs/event-core";
|
|
1
|
+
import { attachHook, createAsyncEventContext, useAsyncEventContext, useEventId, useEventLogger, useEventLogger as useEventLogger$1, useRouteParams } from "@wooksjs/event-core";
|
|
2
2
|
import { Buffer as Buffer$1 } from "buffer";
|
|
3
|
+
import { Readable, pipeline } from "node:stream";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { createBrotliCompress, createBrotliDecompress, createDeflate, createGunzip, createGzip, createInflate } from "node:zlib";
|
|
3
6
|
import { URLSearchParams } from "url";
|
|
4
7
|
import http from "http";
|
|
5
8
|
import { WooksAdapterBase } from "wooks";
|
|
6
|
-
import { Readable } from "stream";
|
|
9
|
+
import { Readable as Readable$1 } from "stream";
|
|
7
10
|
|
|
8
11
|
//#region packages/event-http/src/event-http.ts
|
|
9
12
|
function createHttpContext(data, options) {
|
|
@@ -15,6 +18,10 @@ function createHttpContext(data, options) {
|
|
|
15
18
|
options
|
|
16
19
|
});
|
|
17
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Wrapper on useEventContext with HTTP event types
|
|
23
|
+
* @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
|
|
24
|
+
*/
|
|
18
25
|
function useHttpContext() {
|
|
19
26
|
return useAsyncEventContext("HTTP");
|
|
20
27
|
}
|
|
@@ -49,12 +56,12 @@ function convertTime(time, unit = "ms") {
|
|
|
49
56
|
const units = {
|
|
50
57
|
ms: 1,
|
|
51
58
|
s: 1e3,
|
|
52
|
-
m:
|
|
53
|
-
h:
|
|
54
|
-
d:
|
|
55
|
-
w:
|
|
56
|
-
M:
|
|
57
|
-
Y:
|
|
59
|
+
m: 1e3 * 60,
|
|
60
|
+
h: 1e3 * 60 * 60,
|
|
61
|
+
d: 1e3 * 60 * 60 * 24,
|
|
62
|
+
w: 1e3 * 60 * 60 * 24 * 7,
|
|
63
|
+
M: 1e3 * 60 * 60 * 24 * 30,
|
|
64
|
+
Y: 1e3 * 60 * 60 * 24 * 365
|
|
58
65
|
};
|
|
59
66
|
|
|
60
67
|
//#endregion
|
|
@@ -80,35 +87,426 @@ const cookieAttrFunc = {
|
|
|
80
87
|
sameSite: (v) => v ? `SameSite=${typeof v === "string" ? v : "Strict"}` : ""
|
|
81
88
|
};
|
|
82
89
|
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region packages/event-http/src/compressor/body-compressor.ts
|
|
92
|
+
const compressors = { identity: {
|
|
93
|
+
compress: (v) => v,
|
|
94
|
+
uncompress: (v) => v,
|
|
95
|
+
stream: {
|
|
96
|
+
compress: (data) => data,
|
|
97
|
+
uncompress: (data) => data
|
|
98
|
+
}
|
|
99
|
+
} };
|
|
100
|
+
function encodingSupportsStream(encodings) {
|
|
101
|
+
return encodings.every((enc) => compressors[enc]?.stream);
|
|
102
|
+
}
|
|
103
|
+
async function uncompressBody(encodings, compressed) {
|
|
104
|
+
let buf = compressed;
|
|
105
|
+
for (const enc of encodings.slice().reverse()) {
|
|
106
|
+
const c = compressors[enc];
|
|
107
|
+
if (!c) throw new Error(`Unsupported compression type "${enc}".`);
|
|
108
|
+
buf = await c.uncompress(buf);
|
|
109
|
+
}
|
|
110
|
+
return buf;
|
|
111
|
+
}
|
|
112
|
+
async function uncompressBodyStream(encodings, src) {
|
|
113
|
+
if (!encodingSupportsStream(encodings)) throw new Error("Some encodings lack a streaming decompressor");
|
|
114
|
+
let out = src;
|
|
115
|
+
for (const enc of Array.from(encodings).reverse()) out = await compressors[enc].stream.uncompress(out);
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region packages/event-http/src/compressor/zlib-compressors.ts
|
|
121
|
+
const pipeline$1 = pipeline;
|
|
122
|
+
function iterableToReadable(src) {
|
|
123
|
+
return Readable.from(src, { objectMode: false });
|
|
124
|
+
}
|
|
125
|
+
function pump(src, transform) {
|
|
126
|
+
pipeline$1(iterableToReadable(src), transform, (err) => {
|
|
127
|
+
if (err) transform.destroy(err);
|
|
128
|
+
});
|
|
129
|
+
return transform;
|
|
130
|
+
}
|
|
131
|
+
function addStreamCodec(name, createDeflater, createInflater) {
|
|
132
|
+
const c = compressors[name] ?? (compressors[name] = {
|
|
133
|
+
compress: (v) => v,
|
|
134
|
+
uncompress: (v) => v
|
|
135
|
+
});
|
|
136
|
+
c.stream = {
|
|
137
|
+
compress: async (src) => pump(src, createDeflater()),
|
|
138
|
+
uncompress: async (src) => pump(src, createInflater())
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
addStreamCodec("gzip", createGzip, createGunzip);
|
|
142
|
+
addStreamCodec("deflate", createDeflate, createInflate);
|
|
143
|
+
addStreamCodec("br", createBrotliCompress, createBrotliDecompress);
|
|
144
|
+
let zp;
|
|
145
|
+
async function zlib() {
|
|
146
|
+
if (!zp) {
|
|
147
|
+
const { gzip, gunzip, deflate, inflate, brotliCompress, brotliDecompress } = await import("node:zlib");
|
|
148
|
+
zp = {
|
|
149
|
+
gzip: promisify(gzip),
|
|
150
|
+
gunzip: promisify(gunzip),
|
|
151
|
+
deflate: promisify(deflate),
|
|
152
|
+
inflate: promisify(inflate),
|
|
153
|
+
brotliCompress: promisify(brotliCompress),
|
|
154
|
+
brotliDecompress: promisify(brotliDecompress)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return zp;
|
|
158
|
+
}
|
|
159
|
+
compressors.gzip.compress = async (b) => (await zlib()).gzip(b);
|
|
160
|
+
compressors.gzip.uncompress = async (b) => (await zlib()).gunzip(b);
|
|
161
|
+
compressors.deflate.compress = async (b) => (await zlib()).deflate(b);
|
|
162
|
+
compressors.deflate.uncompress = async (b) => (await zlib()).inflate(b);
|
|
163
|
+
compressors.br.compress = async (b) => (await zlib()).brotliCompress(b);
|
|
164
|
+
compressors.br.uncompress = async (b) => (await zlib()).brotliDecompress(b);
|
|
165
|
+
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region packages/event-http/src/response/renderer.ts
|
|
168
|
+
var BaseHttpResponseRenderer = class {
|
|
169
|
+
render(response) {
|
|
170
|
+
if (typeof response.body === "string" || typeof response.body === "boolean" || typeof response.body === "number") {
|
|
171
|
+
if (!response.getContentType()) response.setContentType("text/plain");
|
|
172
|
+
return response.body.toString();
|
|
173
|
+
}
|
|
174
|
+
if (response.body === void 0) return "";
|
|
175
|
+
if (response.body instanceof Uint8Array) return response.body;
|
|
176
|
+
if (typeof response.body === "object") {
|
|
177
|
+
if (!response.getContentType()) response.setContentType("application/json");
|
|
178
|
+
return JSON.stringify(response.body);
|
|
179
|
+
}
|
|
180
|
+
throw new Error(`Unsupported body format "${typeof response.body}"`);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region packages/event-http/src/utils/status-codes.ts
|
|
186
|
+
const httpStatusCodes = {
|
|
187
|
+
100: "Continue",
|
|
188
|
+
101: "Switching protocols",
|
|
189
|
+
102: "Processing",
|
|
190
|
+
103: "Early Hints",
|
|
191
|
+
200: "OK",
|
|
192
|
+
201: "Created",
|
|
193
|
+
202: "Accepted",
|
|
194
|
+
203: "Non-Authoritative Information",
|
|
195
|
+
204: "No Content",
|
|
196
|
+
205: "Reset Content",
|
|
197
|
+
206: "Partial Content",
|
|
198
|
+
207: "Multi-Status",
|
|
199
|
+
208: "Already Reported",
|
|
200
|
+
226: "IM Used",
|
|
201
|
+
300: "Multiple Choices",
|
|
202
|
+
301: "Moved Permanently",
|
|
203
|
+
302: "Found (Previously \"Moved Temporarily\")",
|
|
204
|
+
303: "See Other",
|
|
205
|
+
304: "Not Modified",
|
|
206
|
+
305: "Use Proxy",
|
|
207
|
+
306: "Switch Proxy",
|
|
208
|
+
307: "Temporary Redirect",
|
|
209
|
+
308: "Permanent Redirect",
|
|
210
|
+
400: "Bad Request",
|
|
211
|
+
401: "Unauthorized",
|
|
212
|
+
402: "Payment Required",
|
|
213
|
+
403: "Forbidden",
|
|
214
|
+
404: "Not Found",
|
|
215
|
+
405: "Method Not Allowed",
|
|
216
|
+
406: "Not Acceptable",
|
|
217
|
+
407: "Proxy Authentication Required",
|
|
218
|
+
408: "Request Timeout",
|
|
219
|
+
409: "Conflict",
|
|
220
|
+
410: "Gone",
|
|
221
|
+
411: "Length Required",
|
|
222
|
+
412: "Precondition Failed",
|
|
223
|
+
413: "Payload Too Large",
|
|
224
|
+
414: "URI Too Long",
|
|
225
|
+
415: "Unsupported Media Type",
|
|
226
|
+
416: "Range Not Satisfiable",
|
|
227
|
+
417: "Expectation Failed",
|
|
228
|
+
418: "I'm a Teapot",
|
|
229
|
+
421: "Misdirected Request",
|
|
230
|
+
422: "Unprocessable Entity",
|
|
231
|
+
423: "Locked",
|
|
232
|
+
424: "Failed Dependency",
|
|
233
|
+
425: "Too Early",
|
|
234
|
+
426: "Upgrade Required",
|
|
235
|
+
428: "Precondition Required",
|
|
236
|
+
429: "Too Many Requests",
|
|
237
|
+
431: "Request Header Fields Too Large",
|
|
238
|
+
451: "Unavailable For Legal Reasons",
|
|
239
|
+
500: "Internal Server Error",
|
|
240
|
+
501: "Not Implemented",
|
|
241
|
+
502: "Bad Gateway",
|
|
242
|
+
503: "Service Unavailable",
|
|
243
|
+
504: "Gateway Timeout",
|
|
244
|
+
505: "HTTP Version Not Supported",
|
|
245
|
+
506: "Variant Also Negotiates",
|
|
246
|
+
507: "Insufficient Storage",
|
|
247
|
+
508: "Loop Detected",
|
|
248
|
+
510: "Not Extended",
|
|
249
|
+
511: "Network Authentication Required"
|
|
250
|
+
};
|
|
251
|
+
let EHttpStatusCode = /* @__PURE__ */ function(EHttpStatusCode$1) {
|
|
252
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Continue"] = 100] = "Continue";
|
|
253
|
+
EHttpStatusCode$1[EHttpStatusCode$1["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
|
254
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Processing"] = 102] = "Processing";
|
|
255
|
+
EHttpStatusCode$1[EHttpStatusCode$1["EarlyHints"] = 103] = "EarlyHints";
|
|
256
|
+
EHttpStatusCode$1[EHttpStatusCode$1["OK"] = 200] = "OK";
|
|
257
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Created"] = 201] = "Created";
|
|
258
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Accepted"] = 202] = "Accepted";
|
|
259
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
|
260
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NoContent"] = 204] = "NoContent";
|
|
261
|
+
EHttpStatusCode$1[EHttpStatusCode$1["ResetContent"] = 205] = "ResetContent";
|
|
262
|
+
EHttpStatusCode$1[EHttpStatusCode$1["PartialContent"] = 206] = "PartialContent";
|
|
263
|
+
EHttpStatusCode$1[EHttpStatusCode$1["MultiStatus"] = 207] = "MultiStatus";
|
|
264
|
+
EHttpStatusCode$1[EHttpStatusCode$1["AlreadyReported"] = 208] = "AlreadyReported";
|
|
265
|
+
EHttpStatusCode$1[EHttpStatusCode$1["IMUsed"] = 226] = "IMUsed";
|
|
266
|
+
EHttpStatusCode$1[EHttpStatusCode$1["MultipleChoices"] = 300] = "MultipleChoices";
|
|
267
|
+
EHttpStatusCode$1[EHttpStatusCode$1["MovedPermanently"] = 301] = "MovedPermanently";
|
|
268
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Found"] = 302] = "Found";
|
|
269
|
+
EHttpStatusCode$1[EHttpStatusCode$1["SeeOther"] = 303] = "SeeOther";
|
|
270
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NotModified"] = 304] = "NotModified";
|
|
271
|
+
EHttpStatusCode$1[EHttpStatusCode$1["UseProxy"] = 305] = "UseProxy";
|
|
272
|
+
EHttpStatusCode$1[EHttpStatusCode$1["SwitchProxy"] = 306] = "SwitchProxy";
|
|
273
|
+
EHttpStatusCode$1[EHttpStatusCode$1["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
|
274
|
+
EHttpStatusCode$1[EHttpStatusCode$1["PermanentRedirect"] = 308] = "PermanentRedirect";
|
|
275
|
+
EHttpStatusCode$1[EHttpStatusCode$1["BadRequest"] = 400] = "BadRequest";
|
|
276
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Unauthorized"] = 401] = "Unauthorized";
|
|
277
|
+
EHttpStatusCode$1[EHttpStatusCode$1["PaymentRequired"] = 402] = "PaymentRequired";
|
|
278
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Forbidden"] = 403] = "Forbidden";
|
|
279
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NotFound"] = 404] = "NotFound";
|
|
280
|
+
EHttpStatusCode$1[EHttpStatusCode$1["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
|
281
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NotAcceptable"] = 406] = "NotAcceptable";
|
|
282
|
+
EHttpStatusCode$1[EHttpStatusCode$1["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
|
283
|
+
EHttpStatusCode$1[EHttpStatusCode$1["RequestTimeout"] = 408] = "RequestTimeout";
|
|
284
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Conflict"] = 409] = "Conflict";
|
|
285
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Gone"] = 410] = "Gone";
|
|
286
|
+
EHttpStatusCode$1[EHttpStatusCode$1["LengthRequired"] = 411] = "LengthRequired";
|
|
287
|
+
EHttpStatusCode$1[EHttpStatusCode$1["PreconditionFailed"] = 412] = "PreconditionFailed";
|
|
288
|
+
EHttpStatusCode$1[EHttpStatusCode$1["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
|
289
|
+
EHttpStatusCode$1[EHttpStatusCode$1["URITooLong"] = 414] = "URITooLong";
|
|
290
|
+
EHttpStatusCode$1[EHttpStatusCode$1["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
|
291
|
+
EHttpStatusCode$1[EHttpStatusCode$1["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
|
292
|
+
EHttpStatusCode$1[EHttpStatusCode$1["ExpectationFailed"] = 417] = "ExpectationFailed";
|
|
293
|
+
EHttpStatusCode$1[EHttpStatusCode$1["ImATeapot"] = 418] = "ImATeapot";
|
|
294
|
+
EHttpStatusCode$1[EHttpStatusCode$1["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
|
295
|
+
EHttpStatusCode$1[EHttpStatusCode$1["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
|
296
|
+
EHttpStatusCode$1[EHttpStatusCode$1["Locked"] = 423] = "Locked";
|
|
297
|
+
EHttpStatusCode$1[EHttpStatusCode$1["FailedDependency"] = 424] = "FailedDependency";
|
|
298
|
+
EHttpStatusCode$1[EHttpStatusCode$1["TooEarly"] = 425] = "TooEarly";
|
|
299
|
+
EHttpStatusCode$1[EHttpStatusCode$1["UpgradeRequired"] = 426] = "UpgradeRequired";
|
|
300
|
+
EHttpStatusCode$1[EHttpStatusCode$1["PreconditionRequired"] = 428] = "PreconditionRequired";
|
|
301
|
+
EHttpStatusCode$1[EHttpStatusCode$1["TooManyRequests"] = 429] = "TooManyRequests";
|
|
302
|
+
EHttpStatusCode$1[EHttpStatusCode$1["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
|
303
|
+
EHttpStatusCode$1[EHttpStatusCode$1["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
|
304
|
+
EHttpStatusCode$1[EHttpStatusCode$1["InternalServerError"] = 500] = "InternalServerError";
|
|
305
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NotImplemented"] = 501] = "NotImplemented";
|
|
306
|
+
EHttpStatusCode$1[EHttpStatusCode$1["BadGateway"] = 502] = "BadGateway";
|
|
307
|
+
EHttpStatusCode$1[EHttpStatusCode$1["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
|
308
|
+
EHttpStatusCode$1[EHttpStatusCode$1["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
309
|
+
EHttpStatusCode$1[EHttpStatusCode$1["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
|
|
310
|
+
EHttpStatusCode$1[EHttpStatusCode$1["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
|
311
|
+
EHttpStatusCode$1[EHttpStatusCode$1["InsufficientStorage"] = 507] = "InsufficientStorage";
|
|
312
|
+
EHttpStatusCode$1[EHttpStatusCode$1["LoopDetected"] = 508] = "LoopDetected";
|
|
313
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NotExtended"] = 510] = "NotExtended";
|
|
314
|
+
EHttpStatusCode$1[EHttpStatusCode$1["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
|
315
|
+
return EHttpStatusCode$1;
|
|
316
|
+
}({});
|
|
317
|
+
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region packages/event-http/src/errors/error-renderer.ts
|
|
320
|
+
const preStyles = "font-family: monospace;width: 100%;max-width: 900px;padding: 10px;margin: 20px auto;border-radius: 8px;background-color: #494949;box-shadow: 0px 0px 3px 2px rgb(255 255 255 / 20%);";
|
|
321
|
+
var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
|
|
322
|
+
renderHtml(response) {
|
|
323
|
+
const data = response.body || {};
|
|
324
|
+
response.setContentType("text/html");
|
|
325
|
+
const keys = Object.keys(data).filter((key) => ![
|
|
326
|
+
"statusCode",
|
|
327
|
+
"error",
|
|
328
|
+
"message"
|
|
329
|
+
].includes(key));
|
|
330
|
+
return `<html style="background-color: #333; color: #bbb;"><head><title>${data.statusCode} ${httpStatusCodes[data.statusCode]}</title></head><body><center><h1>${data.statusCode} ${httpStatusCodes[data.statusCode]}</h1></center><center><h4>${data.message}</h1></center><hr color="#666"><center style="color: #666;"> Wooks v0.6.0 </center>${keys.length > 0 ? `<pre style="${preStyles}">${JSON.stringify({
|
|
331
|
+
...data,
|
|
332
|
+
statusCode: void 0,
|
|
333
|
+
message: void 0,
|
|
334
|
+
error: void 0
|
|
335
|
+
}, null, " ")}</pre>` : ""}</body></html>`;
|
|
336
|
+
}
|
|
337
|
+
renderText(response) {
|
|
338
|
+
const data = response.body || {};
|
|
339
|
+
response.setContentType("text/plain");
|
|
340
|
+
const keys = Object.keys(data).filter((key) => ![
|
|
341
|
+
"statusCode",
|
|
342
|
+
"error",
|
|
343
|
+
"message"
|
|
344
|
+
].includes(key));
|
|
345
|
+
return `${data.statusCode} ${httpStatusCodes[data.statusCode]}\n${data.message}\n\n${keys.length > 0 ? `${JSON.stringify({
|
|
346
|
+
...data,
|
|
347
|
+
statusCode: void 0,
|
|
348
|
+
message: void 0,
|
|
349
|
+
error: void 0
|
|
350
|
+
}, null, " ")}` : ""}`;
|
|
351
|
+
}
|
|
352
|
+
renderJson(response) {
|
|
353
|
+
const data = response.body || {};
|
|
354
|
+
response.setContentType("application/json");
|
|
355
|
+
const keys = Object.keys(data).filter((key) => ![
|
|
356
|
+
"statusCode",
|
|
357
|
+
"error",
|
|
358
|
+
"message"
|
|
359
|
+
].includes(key));
|
|
360
|
+
return `{"statusCode":${escapeQuotes(data.statusCode)},"error":"${escapeQuotes(data.error)}","message":"${escapeQuotes(data.message)}"${keys.length > 0 ? `,${keys.map((k) => `"${escapeQuotes(k)}":${JSON.stringify(data[k])}`).join(",")}` : ""}}`;
|
|
361
|
+
}
|
|
362
|
+
render(response) {
|
|
363
|
+
const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
|
|
364
|
+
response.status = response.body?.statusCode || 500;
|
|
365
|
+
if (acceptsJson()) return this.renderJson(response);
|
|
366
|
+
else if (acceptsHtml()) return this.renderHtml(response);
|
|
367
|
+
else if (acceptsText()) return this.renderText(response);
|
|
368
|
+
else return this.renderJson(response);
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
function escapeQuotes(s) {
|
|
372
|
+
return (typeof s === "number" ? s : s || "").toString().replace(/"/gu, "\\\"");
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region packages/event-http/src/errors/http-error.ts
|
|
377
|
+
var HttpError = class extends Error {
|
|
378
|
+
name = "HttpError";
|
|
379
|
+
constructor(code = 500, _body = "") {
|
|
380
|
+
super(typeof _body === "string" ? _body : _body.message);
|
|
381
|
+
this.code = code;
|
|
382
|
+
this._body = _body;
|
|
383
|
+
}
|
|
384
|
+
get body() {
|
|
385
|
+
return typeof this._body === "string" ? {
|
|
386
|
+
statusCode: this.code,
|
|
387
|
+
message: this.message,
|
|
388
|
+
error: httpStatusCodes[this.code]
|
|
389
|
+
} : {
|
|
390
|
+
...this._body,
|
|
391
|
+
statusCode: this.code,
|
|
392
|
+
message: this.message,
|
|
393
|
+
error: httpStatusCodes[this.code]
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
renderer;
|
|
397
|
+
attachRenderer(renderer) {
|
|
398
|
+
this.renderer = renderer;
|
|
399
|
+
}
|
|
400
|
+
getRenderer() {
|
|
401
|
+
return this.renderer;
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
83
405
|
//#endregion
|
|
84
406
|
//#region packages/event-http/src/composables/request.ts
|
|
85
407
|
const xForwardedFor = "x-forwarded-for";
|
|
408
|
+
const DEFAULT_LIMITS = {
|
|
409
|
+
maxCompressed: 1 * 1024 * 1024,
|
|
410
|
+
maxInflated: 10 * 1024 * 1024,
|
|
411
|
+
maxRatio: 100,
|
|
412
|
+
readTimeoutMs: 1e4
|
|
413
|
+
};
|
|
86
414
|
function useRequest() {
|
|
87
415
|
const { store } = useHttpContext();
|
|
88
|
-
const { init } = store("request");
|
|
416
|
+
const { init, get, set } = store("request");
|
|
89
417
|
const event = store("event");
|
|
90
418
|
const req = event.get("req");
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
419
|
+
const contentEncoding = req.headers["content-encoding"];
|
|
420
|
+
const contentEncodings = () => init("contentEncodings", () => (contentEncoding || "").split(",").map((p) => p.trim()).filter((p) => !!p));
|
|
421
|
+
const isCompressed = () => init("isCompressed", () => {
|
|
422
|
+
const parts = contentEncodings();
|
|
423
|
+
for (const p of parts) if ([
|
|
424
|
+
"deflate",
|
|
425
|
+
"gzip",
|
|
426
|
+
"br"
|
|
427
|
+
].includes(p)) return true;
|
|
428
|
+
return false;
|
|
429
|
+
});
|
|
430
|
+
const getMaxCompressed = () => get("maxCompressed") ?? DEFAULT_LIMITS.maxCompressed;
|
|
431
|
+
const setMaxCompressed = (limit) => set("maxCompressed", limit);
|
|
432
|
+
const getReadTimeoutMs = () => get("readTimeoutMs") ?? DEFAULT_LIMITS.readTimeoutMs;
|
|
433
|
+
const setReadTimeoutMs = (limit) => set("readTimeoutMs", limit);
|
|
434
|
+
const getMaxInflated = () => get("maxInflated") ?? DEFAULT_LIMITS.maxInflated;
|
|
435
|
+
const setMaxInflated = (limit) => set("maxInflated", limit);
|
|
436
|
+
const rawBody = () => init("rawBody", async () => {
|
|
437
|
+
const encs = contentEncodings();
|
|
438
|
+
const isZip = isCompressed();
|
|
439
|
+
const streamable = isZip && encodingSupportsStream(encs);
|
|
440
|
+
const maxCompressed = getMaxCompressed();
|
|
441
|
+
const maxInflated = getMaxInflated();
|
|
442
|
+
const timeoutMs = getReadTimeoutMs();
|
|
443
|
+
const cl = Number(req.headers["content-length"] ?? 0);
|
|
444
|
+
const upfrontLimit = isZip ? maxCompressed : maxInflated;
|
|
445
|
+
if (cl && cl > upfrontLimit) throw new HttpError(413, "Payload Too Large");
|
|
446
|
+
for (const enc of encs) if (!compressors[enc]) throw new HttpError(415, `Unsupported Content-Encoding "${enc}"`);
|
|
447
|
+
let timer = null;
|
|
448
|
+
function resetTimer() {
|
|
449
|
+
if (timeoutMs === 0) return;
|
|
450
|
+
clearTimer();
|
|
451
|
+
timer = setTimeout(() => {
|
|
452
|
+
clearTimer();
|
|
453
|
+
req.destroy();
|
|
454
|
+
}, timeoutMs);
|
|
455
|
+
}
|
|
456
|
+
function clearTimer() {
|
|
457
|
+
if (timer) {
|
|
458
|
+
clearTimeout(timer);
|
|
459
|
+
timer = null;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
let rawBytes = 0;
|
|
463
|
+
async function* limitedCompressed() {
|
|
464
|
+
resetTimer();
|
|
465
|
+
try {
|
|
466
|
+
for await (const chunk of req) {
|
|
467
|
+
rawBytes += chunk.length;
|
|
468
|
+
if (rawBytes > upfrontLimit) {
|
|
469
|
+
req.destroy();
|
|
470
|
+
throw new HttpError(413, "Payload Too Large");
|
|
471
|
+
}
|
|
472
|
+
resetTimer();
|
|
473
|
+
yield chunk;
|
|
474
|
+
}
|
|
475
|
+
} finally {
|
|
476
|
+
clearTimer();
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
let stream = limitedCompressed();
|
|
480
|
+
if (streamable) stream = await uncompressBodyStream(encs, stream);
|
|
481
|
+
const chunks = [];
|
|
482
|
+
let inflatedBytes = 0;
|
|
483
|
+
try {
|
|
484
|
+
for await (const chunk of stream) {
|
|
485
|
+
inflatedBytes += chunk.length;
|
|
486
|
+
if (inflatedBytes > maxInflated) throw new HttpError(413, "Inflated body too large");
|
|
487
|
+
chunks.push(chunk);
|
|
488
|
+
}
|
|
489
|
+
} catch (error) {
|
|
490
|
+
if (error instanceof HttpError) throw error;
|
|
491
|
+
throw new HttpError(408, "Request body timeout");
|
|
492
|
+
}
|
|
493
|
+
let body = Buffer$1.concat(chunks);
|
|
494
|
+
if (!streamable && isZip) {
|
|
495
|
+
body = await uncompressBody(encs, body);
|
|
496
|
+
inflatedBytes = body.byteLength;
|
|
497
|
+
if (inflatedBytes > maxInflated) throw new HttpError(413, "Inflated body too large");
|
|
498
|
+
}
|
|
499
|
+
return body;
|
|
500
|
+
});
|
|
103
501
|
const reqId = useEventId().getId;
|
|
104
502
|
const forwardedIp = () => init("forwardedIp", () => {
|
|
105
503
|
if (typeof req.headers[xForwardedFor] === "string" && req.headers[xForwardedFor]) return req.headers[xForwardedFor].split(",").shift()?.trim();
|
|
106
|
-
else return "";
|
|
504
|
+
else return "";
|
|
107
505
|
});
|
|
108
506
|
const remoteIp = () => init("remoteIp", () => req.socket.remoteAddress || req.connection.remoteAddress || "");
|
|
109
507
|
function getIp(options) {
|
|
110
508
|
if (options?.trustProxy) return forwardedIp() || getIp();
|
|
111
|
-
else return remoteIp();
|
|
509
|
+
else return remoteIp();
|
|
112
510
|
}
|
|
113
511
|
const getIpList = () => init("ipList", () => ({
|
|
114
512
|
remoteIp: req.socket.remoteAddress || req.connection.remoteAddress || "",
|
|
@@ -122,7 +520,14 @@ else return remoteIp();
|
|
|
122
520
|
rawBody,
|
|
123
521
|
reqId,
|
|
124
522
|
getIp,
|
|
125
|
-
getIpList
|
|
523
|
+
getIpList,
|
|
524
|
+
isCompressed,
|
|
525
|
+
getMaxCompressed,
|
|
526
|
+
setMaxCompressed,
|
|
527
|
+
getReadTimeoutMs,
|
|
528
|
+
setReadTimeoutMs,
|
|
529
|
+
getMaxInflated,
|
|
530
|
+
setMaxInflated
|
|
126
531
|
};
|
|
127
532
|
}
|
|
128
533
|
|
|
@@ -282,7 +687,7 @@ function useAuthorization() {
|
|
|
282
687
|
function renderCacheControl(data) {
|
|
283
688
|
let attrs = "";
|
|
284
689
|
for (const [a, v] of Object.entries(data)) {
|
|
285
|
-
if (v ===
|
|
690
|
+
if (v === void 0) continue;
|
|
286
691
|
const func = cacheControlFunc[a];
|
|
287
692
|
if (typeof func === "function") {
|
|
288
693
|
const val = func(v);
|
|
@@ -363,11 +768,15 @@ function useStatus() {
|
|
|
363
768
|
//#region packages/event-http/src/utils/url-search-params.ts
|
|
364
769
|
var WooksURLSearchParams = class extends URLSearchParams {
|
|
365
770
|
toJson() {
|
|
366
|
-
const json =
|
|
771
|
+
const json = Object.create(null);
|
|
367
772
|
for (const [key, value] of this.entries()) if (isArrayParam(key)) {
|
|
368
773
|
const a = json[key] = json[key] || [];
|
|
369
774
|
a.push(value);
|
|
370
|
-
} else
|
|
775
|
+
} else {
|
|
776
|
+
if (key === "__proto__") throw new HttpError(400, `Illegal key name "${key}"`);
|
|
777
|
+
if (key in json) throw new HttpError(400, `Duplicate key "${key}"`);
|
|
778
|
+
json[key] = value;
|
|
779
|
+
}
|
|
371
780
|
return json;
|
|
372
781
|
}
|
|
373
782
|
};
|
|
@@ -393,245 +802,6 @@ function useSearchParams() {
|
|
|
393
802
|
};
|
|
394
803
|
}
|
|
395
804
|
|
|
396
|
-
//#endregion
|
|
397
|
-
//#region packages/event-http/src/response/renderer.ts
|
|
398
|
-
var BaseHttpResponseRenderer = class {
|
|
399
|
-
render(response) {
|
|
400
|
-
if (typeof response.body === "string" || typeof response.body === "boolean" || typeof response.body === "number") {
|
|
401
|
-
if (!response.getContentType()) response.setContentType("text/plain");
|
|
402
|
-
return response.body.toString();
|
|
403
|
-
}
|
|
404
|
-
if (response.body === undefined) return "";
|
|
405
|
-
if (response.body instanceof Uint8Array) return response.body;
|
|
406
|
-
if (typeof response.body === "object") {
|
|
407
|
-
if (!response.getContentType()) response.setContentType("application/json");
|
|
408
|
-
return JSON.stringify(response.body);
|
|
409
|
-
}
|
|
410
|
-
throw new Error(`Unsupported body format "${typeof response.body}"`);
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
//#endregion
|
|
415
|
-
//#region packages/event-http/src/utils/status-codes.ts
|
|
416
|
-
const httpStatusCodes = {
|
|
417
|
-
100: "Continue",
|
|
418
|
-
101: "Switching protocols",
|
|
419
|
-
102: "Processing",
|
|
420
|
-
103: "Early Hints",
|
|
421
|
-
200: "OK",
|
|
422
|
-
201: "Created",
|
|
423
|
-
202: "Accepted",
|
|
424
|
-
203: "Non-Authoritative Information",
|
|
425
|
-
204: "No Content",
|
|
426
|
-
205: "Reset Content",
|
|
427
|
-
206: "Partial Content",
|
|
428
|
-
207: "Multi-Status",
|
|
429
|
-
208: "Already Reported",
|
|
430
|
-
226: "IM Used",
|
|
431
|
-
300: "Multiple Choices",
|
|
432
|
-
301: "Moved Permanently",
|
|
433
|
-
302: "Found (Previously \"Moved Temporarily\")",
|
|
434
|
-
303: "See Other",
|
|
435
|
-
304: "Not Modified",
|
|
436
|
-
305: "Use Proxy",
|
|
437
|
-
306: "Switch Proxy",
|
|
438
|
-
307: "Temporary Redirect",
|
|
439
|
-
308: "Permanent Redirect",
|
|
440
|
-
400: "Bad Request",
|
|
441
|
-
401: "Unauthorized",
|
|
442
|
-
402: "Payment Required",
|
|
443
|
-
403: "Forbidden",
|
|
444
|
-
404: "Not Found",
|
|
445
|
-
405: "Method Not Allowed",
|
|
446
|
-
406: "Not Acceptable",
|
|
447
|
-
407: "Proxy Authentication Required",
|
|
448
|
-
408: "Request Timeout",
|
|
449
|
-
409: "Conflict",
|
|
450
|
-
410: "Gone",
|
|
451
|
-
411: "Length Required",
|
|
452
|
-
412: "Precondition Failed",
|
|
453
|
-
413: "Payload Too Large",
|
|
454
|
-
414: "URI Too Long",
|
|
455
|
-
415: "Unsupported Media Type",
|
|
456
|
-
416: "Range Not Satisfiable",
|
|
457
|
-
417: "Expectation Failed",
|
|
458
|
-
418: "I'm a Teapot",
|
|
459
|
-
421: "Misdirected Request",
|
|
460
|
-
422: "Unprocessable Entity",
|
|
461
|
-
423: "Locked",
|
|
462
|
-
424: "Failed Dependency",
|
|
463
|
-
425: "Too Early",
|
|
464
|
-
426: "Upgrade Required",
|
|
465
|
-
428: "Precondition Required",
|
|
466
|
-
429: "Too Many Requests",
|
|
467
|
-
431: "Request Header Fields Too Large",
|
|
468
|
-
451: "Unavailable For Legal Reasons",
|
|
469
|
-
500: "Internal Server Error",
|
|
470
|
-
501: "Not Implemented",
|
|
471
|
-
502: "Bad Gateway",
|
|
472
|
-
503: "Service Unavailable",
|
|
473
|
-
504: "Gateway Timeout",
|
|
474
|
-
505: "HTTP Version Not Supported",
|
|
475
|
-
506: "Variant Also Negotiates",
|
|
476
|
-
507: "Insufficient Storage",
|
|
477
|
-
508: "Loop Detected",
|
|
478
|
-
510: "Not Extended",
|
|
479
|
-
511: "Network Authentication Required"
|
|
480
|
-
};
|
|
481
|
-
let EHttpStatusCode = function(EHttpStatusCode$1) {
|
|
482
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Continue"] = 100] = "Continue";
|
|
483
|
-
EHttpStatusCode$1[EHttpStatusCode$1["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
|
484
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Processing"] = 102] = "Processing";
|
|
485
|
-
EHttpStatusCode$1[EHttpStatusCode$1["EarlyHints"] = 103] = "EarlyHints";
|
|
486
|
-
EHttpStatusCode$1[EHttpStatusCode$1["OK"] = 200] = "OK";
|
|
487
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Created"] = 201] = "Created";
|
|
488
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Accepted"] = 202] = "Accepted";
|
|
489
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
|
490
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NoContent"] = 204] = "NoContent";
|
|
491
|
-
EHttpStatusCode$1[EHttpStatusCode$1["ResetContent"] = 205] = "ResetContent";
|
|
492
|
-
EHttpStatusCode$1[EHttpStatusCode$1["PartialContent"] = 206] = "PartialContent";
|
|
493
|
-
EHttpStatusCode$1[EHttpStatusCode$1["MultiStatus"] = 207] = "MultiStatus";
|
|
494
|
-
EHttpStatusCode$1[EHttpStatusCode$1["AlreadyReported"] = 208] = "AlreadyReported";
|
|
495
|
-
EHttpStatusCode$1[EHttpStatusCode$1["IMUsed"] = 226] = "IMUsed";
|
|
496
|
-
EHttpStatusCode$1[EHttpStatusCode$1["MultipleChoices"] = 300] = "MultipleChoices";
|
|
497
|
-
EHttpStatusCode$1[EHttpStatusCode$1["MovedPermanently"] = 301] = "MovedPermanently";
|
|
498
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Found"] = 302] = "Found";
|
|
499
|
-
EHttpStatusCode$1[EHttpStatusCode$1["SeeOther"] = 303] = "SeeOther";
|
|
500
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NotModified"] = 304] = "NotModified";
|
|
501
|
-
EHttpStatusCode$1[EHttpStatusCode$1["UseProxy"] = 305] = "UseProxy";
|
|
502
|
-
EHttpStatusCode$1[EHttpStatusCode$1["SwitchProxy"] = 306] = "SwitchProxy";
|
|
503
|
-
EHttpStatusCode$1[EHttpStatusCode$1["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
|
504
|
-
EHttpStatusCode$1[EHttpStatusCode$1["PermanentRedirect"] = 308] = "PermanentRedirect";
|
|
505
|
-
EHttpStatusCode$1[EHttpStatusCode$1["BadRequest"] = 400] = "BadRequest";
|
|
506
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Unauthorized"] = 401] = "Unauthorized";
|
|
507
|
-
EHttpStatusCode$1[EHttpStatusCode$1["PaymentRequired"] = 402] = "PaymentRequired";
|
|
508
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Forbidden"] = 403] = "Forbidden";
|
|
509
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NotFound"] = 404] = "NotFound";
|
|
510
|
-
EHttpStatusCode$1[EHttpStatusCode$1["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
|
511
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NotAcceptable"] = 406] = "NotAcceptable";
|
|
512
|
-
EHttpStatusCode$1[EHttpStatusCode$1["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
|
513
|
-
EHttpStatusCode$1[EHttpStatusCode$1["RequestTimeout"] = 408] = "RequestTimeout";
|
|
514
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Conflict"] = 409] = "Conflict";
|
|
515
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Gone"] = 410] = "Gone";
|
|
516
|
-
EHttpStatusCode$1[EHttpStatusCode$1["LengthRequired"] = 411] = "LengthRequired";
|
|
517
|
-
EHttpStatusCode$1[EHttpStatusCode$1["PreconditionFailed"] = 412] = "PreconditionFailed";
|
|
518
|
-
EHttpStatusCode$1[EHttpStatusCode$1["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
|
519
|
-
EHttpStatusCode$1[EHttpStatusCode$1["URITooLong"] = 414] = "URITooLong";
|
|
520
|
-
EHttpStatusCode$1[EHttpStatusCode$1["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
|
521
|
-
EHttpStatusCode$1[EHttpStatusCode$1["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
|
522
|
-
EHttpStatusCode$1[EHttpStatusCode$1["ExpectationFailed"] = 417] = "ExpectationFailed";
|
|
523
|
-
EHttpStatusCode$1[EHttpStatusCode$1["ImATeapot"] = 418] = "ImATeapot";
|
|
524
|
-
EHttpStatusCode$1[EHttpStatusCode$1["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
|
525
|
-
EHttpStatusCode$1[EHttpStatusCode$1["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
|
526
|
-
EHttpStatusCode$1[EHttpStatusCode$1["Locked"] = 423] = "Locked";
|
|
527
|
-
EHttpStatusCode$1[EHttpStatusCode$1["FailedDependency"] = 424] = "FailedDependency";
|
|
528
|
-
EHttpStatusCode$1[EHttpStatusCode$1["TooEarly"] = 425] = "TooEarly";
|
|
529
|
-
EHttpStatusCode$1[EHttpStatusCode$1["UpgradeRequired"] = 426] = "UpgradeRequired";
|
|
530
|
-
EHttpStatusCode$1[EHttpStatusCode$1["PreconditionRequired"] = 428] = "PreconditionRequired";
|
|
531
|
-
EHttpStatusCode$1[EHttpStatusCode$1["TooManyRequests"] = 429] = "TooManyRequests";
|
|
532
|
-
EHttpStatusCode$1[EHttpStatusCode$1["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
|
533
|
-
EHttpStatusCode$1[EHttpStatusCode$1["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
|
534
|
-
EHttpStatusCode$1[EHttpStatusCode$1["InternalServerError"] = 500] = "InternalServerError";
|
|
535
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NotImplemented"] = 501] = "NotImplemented";
|
|
536
|
-
EHttpStatusCode$1[EHttpStatusCode$1["BadGateway"] = 502] = "BadGateway";
|
|
537
|
-
EHttpStatusCode$1[EHttpStatusCode$1["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
|
538
|
-
EHttpStatusCode$1[EHttpStatusCode$1["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
539
|
-
EHttpStatusCode$1[EHttpStatusCode$1["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
|
|
540
|
-
EHttpStatusCode$1[EHttpStatusCode$1["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
|
541
|
-
EHttpStatusCode$1[EHttpStatusCode$1["InsufficientStorage"] = 507] = "InsufficientStorage";
|
|
542
|
-
EHttpStatusCode$1[EHttpStatusCode$1["LoopDetected"] = 508] = "LoopDetected";
|
|
543
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NotExtended"] = 510] = "NotExtended";
|
|
544
|
-
EHttpStatusCode$1[EHttpStatusCode$1["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
|
545
|
-
return EHttpStatusCode$1;
|
|
546
|
-
}({});
|
|
547
|
-
|
|
548
|
-
//#endregion
|
|
549
|
-
//#region packages/event-http/src/errors/error-renderer.ts
|
|
550
|
-
const preStyles = "font-family: monospace;width: 100%;max-width: 900px;padding: 10px;margin: 20px auto;border-radius: 8px;background-color: #494949;box-shadow: 0px 0px 3px 2px rgb(255 255 255 / 20%);";
|
|
551
|
-
var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
|
|
552
|
-
renderHtml(response) {
|
|
553
|
-
const data = response.body || {};
|
|
554
|
-
response.setContentType("text/html");
|
|
555
|
-
const keys = Object.keys(data).filter((key) => ![
|
|
556
|
-
"statusCode",
|
|
557
|
-
"error",
|
|
558
|
-
"message"
|
|
559
|
-
].includes(key));
|
|
560
|
-
return "<html style=\"background-color: #333; color: #bbb;\">" + `<head><title>${data.statusCode} ${httpStatusCodes[data.statusCode]}</title></head>` + `<body><center><h1>${data.statusCode} ${httpStatusCodes[data.statusCode]}</h1></center>` + `<center><h4>${data.message}</h1></center><hr color="#666">` + `<center style="color: #666;"> Wooks v${"0.5.24"} </center>` + `${keys.length > 0 ? `<pre style="${preStyles}">${JSON.stringify({
|
|
561
|
-
...data,
|
|
562
|
-
statusCode: undefined,
|
|
563
|
-
message: undefined,
|
|
564
|
-
error: undefined
|
|
565
|
-
}, null, " ")}</pre>` : ""}` + "</body></html>";
|
|
566
|
-
}
|
|
567
|
-
renderText(response) {
|
|
568
|
-
const data = response.body || {};
|
|
569
|
-
response.setContentType("text/plain");
|
|
570
|
-
const keys = Object.keys(data).filter((key) => ![
|
|
571
|
-
"statusCode",
|
|
572
|
-
"error",
|
|
573
|
-
"message"
|
|
574
|
-
].includes(key));
|
|
575
|
-
return `${data.statusCode} ${httpStatusCodes[data.statusCode]}\n${data.message}` + `\n\n${keys.length > 0 ? `${JSON.stringify({
|
|
576
|
-
...data,
|
|
577
|
-
statusCode: undefined,
|
|
578
|
-
message: undefined,
|
|
579
|
-
error: undefined
|
|
580
|
-
}, null, " ")}` : ""}`;
|
|
581
|
-
}
|
|
582
|
-
renderJson(response) {
|
|
583
|
-
const data = response.body || {};
|
|
584
|
-
response.setContentType("application/json");
|
|
585
|
-
const keys = Object.keys(data).filter((key) => ![
|
|
586
|
-
"statusCode",
|
|
587
|
-
"error",
|
|
588
|
-
"message"
|
|
589
|
-
].includes(key));
|
|
590
|
-
return `{"statusCode":${escapeQuotes(data.statusCode)},` + `"error":"${escapeQuotes(data.error)}",` + `"message":"${escapeQuotes(data.message)}"` + `${keys.length > 0 ? `,${keys.map((k) => `"${escapeQuotes(k)}":${JSON.stringify(data[k])}`).join(",")}` : ""}}`;
|
|
591
|
-
}
|
|
592
|
-
render(response) {
|
|
593
|
-
const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
|
|
594
|
-
response.status = response.body?.statusCode || 500;
|
|
595
|
-
if (acceptsJson()) return this.renderJson(response);
|
|
596
|
-
else if (acceptsHtml()) return this.renderHtml(response);
|
|
597
|
-
else if (acceptsText()) return this.renderText(response);
|
|
598
|
-
else return this.renderJson(response);
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
function escapeQuotes(s) {
|
|
602
|
-
return (typeof s === "number" ? s : s || "").toString().replace(/"/gu, "\\\"");
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
//#endregion
|
|
606
|
-
//#region packages/event-http/src/errors/http-error.ts
|
|
607
|
-
var HttpError = class extends Error {
|
|
608
|
-
name = "HttpError";
|
|
609
|
-
constructor(code = 500, _body = "") {
|
|
610
|
-
super(typeof _body === "string" ? _body : _body.message);
|
|
611
|
-
this.code = code;
|
|
612
|
-
this._body = _body;
|
|
613
|
-
}
|
|
614
|
-
get body() {
|
|
615
|
-
return typeof this._body === "string" ? {
|
|
616
|
-
statusCode: this.code,
|
|
617
|
-
message: this.message,
|
|
618
|
-
error: httpStatusCodes[this.code]
|
|
619
|
-
} : {
|
|
620
|
-
...this._body,
|
|
621
|
-
statusCode: this.code,
|
|
622
|
-
message: this.message,
|
|
623
|
-
error: httpStatusCodes[this.code]
|
|
624
|
-
};
|
|
625
|
-
}
|
|
626
|
-
renderer;
|
|
627
|
-
attachRenderer(renderer) {
|
|
628
|
-
this.renderer = renderer;
|
|
629
|
-
}
|
|
630
|
-
getRenderer() {
|
|
631
|
-
return this.renderer;
|
|
632
|
-
}
|
|
633
|
-
};
|
|
634
|
-
|
|
635
805
|
//#endregion
|
|
636
806
|
//#region packages/event-http/src/response/core.ts
|
|
637
807
|
const defaultStatus = {
|
|
@@ -738,11 +908,11 @@ var BaseHttpResponse = class {
|
|
|
738
908
|
async respond() {
|
|
739
909
|
const { rawResponse, hasResponded } = useResponse();
|
|
740
910
|
const { method, rawRequest } = useRequest();
|
|
741
|
-
const logger = useEventLogger("http-response") || console;
|
|
911
|
+
const logger = useEventLogger$1("http-response") || console;
|
|
742
912
|
if (hasResponded()) this.panic("The response was already sent.", logger);
|
|
743
913
|
this.mergeHeaders();
|
|
744
914
|
const res = rawResponse();
|
|
745
|
-
if (this.body instanceof Readable) {
|
|
915
|
+
if (this.body instanceof Readable$1) {
|
|
746
916
|
const stream = this.body;
|
|
747
917
|
this.mergeStatus("ok");
|
|
748
918
|
res.writeHead(this.status, { ...this._headers });
|
|
@@ -760,14 +930,14 @@ var BaseHttpResponse = class {
|
|
|
760
930
|
});
|
|
761
931
|
stream.on("close", () => {
|
|
762
932
|
stream.destroy();
|
|
763
|
-
resolve(
|
|
933
|
+
resolve(void 0);
|
|
764
934
|
});
|
|
765
935
|
stream.pipe(res);
|
|
766
936
|
});
|
|
767
937
|
} else if (globalThis.Response && this.body instanceof Response) {
|
|
768
938
|
this.mergeFetchStatus(this.body.status);
|
|
769
939
|
if (method === "HEAD") res.end();
|
|
770
|
-
else {
|
|
940
|
+
else {
|
|
771
941
|
const additionalHeaders = {};
|
|
772
942
|
if (this.body.headers.get("content-length")) additionalHeaders["content-length"] = this.body.headers.get("content-length");
|
|
773
943
|
if (this.body.headers.get("content-type")) additionalHeaders["content-type"] = this.body.headers.get("content-type");
|
|
@@ -804,11 +974,11 @@ function createWooksResponder(renderer = new BaseHttpResponseRenderer(), errorRe
|
|
|
804
974
|
const r = new BaseHttpResponse(errorRenderer);
|
|
805
975
|
let httpError;
|
|
806
976
|
if (data instanceof HttpError) httpError = data;
|
|
807
|
-
else httpError = new HttpError(500, data.message);
|
|
977
|
+
else httpError = new HttpError(500, data.message);
|
|
808
978
|
r.setBody(httpError.body);
|
|
809
979
|
return r;
|
|
810
980
|
} else if (data instanceof BaseHttpResponse) return data;
|
|
811
|
-
else return new BaseHttpResponse(renderer).setBody(data);
|
|
981
|
+
else return new BaseHttpResponse(renderer).setBody(data);
|
|
812
982
|
}
|
|
813
983
|
return {
|
|
814
984
|
createResponse,
|
|
@@ -823,7 +993,7 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
823
993
|
constructor(opts, wooks) {
|
|
824
994
|
super(wooks, opts?.logger, opts?.router);
|
|
825
995
|
this.opts = opts;
|
|
826
|
-
this.logger = opts?.logger || this.getLogger(
|
|
996
|
+
this.logger = opts?.logger || this.getLogger(`[96m[wooks-http]`);
|
|
827
997
|
}
|
|
828
998
|
all(path, handler) {
|
|
829
999
|
return this.on("*", path, handler);
|
|
@@ -861,7 +1031,7 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
861
1031
|
backlog,
|
|
862
1032
|
listeningListener
|
|
863
1033
|
];
|
|
864
|
-
const ui = args.indexOf(
|
|
1034
|
+
const ui = args.indexOf(void 0);
|
|
865
1035
|
if (ui >= 0) args = args.slice(0, ui);
|
|
866
1036
|
server.listen(...args);
|
|
867
1037
|
});
|
|
@@ -903,7 +1073,7 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
903
1073
|
}
|
|
904
1074
|
responder = createWooksResponder();
|
|
905
1075
|
respond(data) {
|
|
906
|
-
|
|
1076
|
+
this.responder.respond(data)?.catch((e) => {
|
|
907
1077
|
this.logger.error("Uncaught response exception", e);
|
|
908
1078
|
});
|
|
909
1079
|
}
|
|
@@ -934,7 +1104,7 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
934
1104
|
this.respond(error);
|
|
935
1105
|
return error;
|
|
936
1106
|
}
|
|
937
|
-
else {
|
|
1107
|
+
else {
|
|
938
1108
|
this.logger.debug(`404 Not found (${req.method})${req.url}`);
|
|
939
1109
|
const error = new HttpError(404);
|
|
940
1110
|
this.respond(error);
|
|
@@ -962,9 +1132,15 @@ else {
|
|
|
962
1132
|
}
|
|
963
1133
|
}
|
|
964
1134
|
};
|
|
1135
|
+
/**
|
|
1136
|
+
* Factory for WooksHttp App
|
|
1137
|
+
* @param opts TWooksHttpOptions
|
|
1138
|
+
* @param wooks Wooks | WooksAdapterBase
|
|
1139
|
+
* @returns WooksHttp
|
|
1140
|
+
*/
|
|
965
1141
|
function createHttpApp(opts, wooks) {
|
|
966
1142
|
return new WooksHttp(opts, wooks);
|
|
967
1143
|
}
|
|
968
1144
|
|
|
969
1145
|
//#endregion
|
|
970
|
-
export { BaseHttpResponse, BaseHttpResponseRenderer, EHttpStatusCode, HttpError, HttpErrorRenderer, WooksHttp, WooksURLSearchParams, createHttpApp, createHttpContext, createWooksResponder, httpStatusCodes, renderCacheControl, useAccept, useAuthorization, useCookies, useEventLogger, useHeaders, useHttpContext, useRequest, useResponse, useRouteParams, useSearchParams, useSetCacheControl, useSetCookie, useSetCookies, useSetHeader, useSetHeaders, useStatus };
|
|
1146
|
+
export { BaseHttpResponse, BaseHttpResponseRenderer, DEFAULT_LIMITS, EHttpStatusCode, HttpError, HttpErrorRenderer, WooksHttp, WooksURLSearchParams, createHttpApp, createHttpContext, createWooksResponder, httpStatusCodes, renderCacheControl, useAccept, useAuthorization, useCookies, useEventLogger, useHeaders, useHttpContext, useRequest, useResponse, useRouteParams, useSearchParams, useSetCacheControl, useSetCookie, useSetCookies, useSetHeader, useSetHeaders, useStatus };
|