@wooksjs/event-http 0.5.25 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -24,6 +24,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  //#endregion
25
25
  const __wooksjs_event_core = __toESM(require("@wooksjs/event-core"));
26
26
  const buffer = __toESM(require("buffer"));
27
+ const node_stream = __toESM(require("node:stream"));
28
+ const node_util = __toESM(require("node:util"));
29
+ const node_zlib = __toESM(require("node:zlib"));
27
30
  const url = __toESM(require("url"));
28
31
  const http = __toESM(require("http"));
29
32
  const wooks = __toESM(require("wooks"));
@@ -104,26 +107,417 @@ const cookieAttrFunc = {
104
107
  sameSite: (v) => v ? `SameSite=${typeof v === "string" ? v : "Strict"}` : ""
105
108
  };
106
109
 
110
+ //#endregion
111
+ //#region packages/event-http/src/compressor/body-compressor.ts
112
+ const compressors = { identity: {
113
+ compress: (v) => v,
114
+ uncompress: (v) => v,
115
+ stream: {
116
+ compress: (data) => data,
117
+ uncompress: (data) => data
118
+ }
119
+ } };
120
+ function encodingSupportsStream(encodings) {
121
+ return encodings.every((enc) => compressors[enc]?.stream);
122
+ }
123
+ async function uncompressBody(encodings, compressed) {
124
+ let buf = compressed;
125
+ for (const enc of encodings.slice().reverse()) {
126
+ const c = compressors[enc];
127
+ if (!c) throw new Error(`Unsupported compression type "${enc}".`);
128
+ buf = await c.uncompress(buf);
129
+ }
130
+ return buf;
131
+ }
132
+ async function uncompressBodyStream(encodings, src) {
133
+ if (!encodingSupportsStream(encodings)) throw new Error("Some encodings lack a streaming decompressor");
134
+ let out = src;
135
+ for (const enc of Array.from(encodings).reverse()) out = await compressors[enc].stream.uncompress(out);
136
+ return out;
137
+ }
138
+
139
+ //#endregion
140
+ //#region packages/event-http/src/compressor/zlib-compressors.ts
141
+ const pipeline = node_stream.pipeline;
142
+ function iterableToReadable(src) {
143
+ return node_stream.Readable.from(src, { objectMode: false });
144
+ }
145
+ function pump(src, transform) {
146
+ pipeline(iterableToReadable(src), transform, (err) => {
147
+ if (err) transform.destroy(err);
148
+ });
149
+ return transform;
150
+ }
151
+ function addStreamCodec(name, createDeflater, createInflater) {
152
+ const c = compressors[name] ?? (compressors[name] = {
153
+ compress: (v) => v,
154
+ uncompress: (v) => v
155
+ });
156
+ c.stream = {
157
+ compress: async (src) => pump(src, createDeflater()),
158
+ uncompress: async (src) => pump(src, createInflater())
159
+ };
160
+ }
161
+ addStreamCodec("gzip", node_zlib.createGzip, node_zlib.createGunzip);
162
+ addStreamCodec("deflate", node_zlib.createDeflate, node_zlib.createInflate);
163
+ addStreamCodec("br", node_zlib.createBrotliCompress, node_zlib.createBrotliDecompress);
164
+ let zp;
165
+ async function zlib() {
166
+ if (!zp) {
167
+ const { gzip, gunzip, deflate, inflate, brotliCompress, brotliDecompress } = await import("node:zlib");
168
+ zp = {
169
+ gzip: (0, node_util.promisify)(gzip),
170
+ gunzip: (0, node_util.promisify)(gunzip),
171
+ deflate: (0, node_util.promisify)(deflate),
172
+ inflate: (0, node_util.promisify)(inflate),
173
+ brotliCompress: (0, node_util.promisify)(brotliCompress),
174
+ brotliDecompress: (0, node_util.promisify)(brotliDecompress)
175
+ };
176
+ }
177
+ return zp;
178
+ }
179
+ compressors.gzip.compress = async (b) => (await zlib()).gzip(b);
180
+ compressors.gzip.uncompress = async (b) => (await zlib()).gunzip(b);
181
+ compressors.deflate.compress = async (b) => (await zlib()).deflate(b);
182
+ compressors.deflate.uncompress = async (b) => (await zlib()).inflate(b);
183
+ compressors.br.compress = async (b) => (await zlib()).brotliCompress(b);
184
+ compressors.br.uncompress = async (b) => (await zlib()).brotliDecompress(b);
185
+
186
+ //#endregion
187
+ //#region packages/event-http/src/response/renderer.ts
188
+ var BaseHttpResponseRenderer = class {
189
+ render(response) {
190
+ if (typeof response.body === "string" || typeof response.body === "boolean" || typeof response.body === "number") {
191
+ if (!response.getContentType()) response.setContentType("text/plain");
192
+ return response.body.toString();
193
+ }
194
+ if (response.body === undefined) return "";
195
+ if (response.body instanceof Uint8Array) return response.body;
196
+ if (typeof response.body === "object") {
197
+ if (!response.getContentType()) response.setContentType("application/json");
198
+ return JSON.stringify(response.body);
199
+ }
200
+ throw new Error(`Unsupported body format "${typeof response.body}"`);
201
+ }
202
+ };
203
+
204
+ //#endregion
205
+ //#region packages/event-http/src/utils/status-codes.ts
206
+ const httpStatusCodes = {
207
+ 100: "Continue",
208
+ 101: "Switching protocols",
209
+ 102: "Processing",
210
+ 103: "Early Hints",
211
+ 200: "OK",
212
+ 201: "Created",
213
+ 202: "Accepted",
214
+ 203: "Non-Authoritative Information",
215
+ 204: "No Content",
216
+ 205: "Reset Content",
217
+ 206: "Partial Content",
218
+ 207: "Multi-Status",
219
+ 208: "Already Reported",
220
+ 226: "IM Used",
221
+ 300: "Multiple Choices",
222
+ 301: "Moved Permanently",
223
+ 302: "Found (Previously \"Moved Temporarily\")",
224
+ 303: "See Other",
225
+ 304: "Not Modified",
226
+ 305: "Use Proxy",
227
+ 306: "Switch Proxy",
228
+ 307: "Temporary Redirect",
229
+ 308: "Permanent Redirect",
230
+ 400: "Bad Request",
231
+ 401: "Unauthorized",
232
+ 402: "Payment Required",
233
+ 403: "Forbidden",
234
+ 404: "Not Found",
235
+ 405: "Method Not Allowed",
236
+ 406: "Not Acceptable",
237
+ 407: "Proxy Authentication Required",
238
+ 408: "Request Timeout",
239
+ 409: "Conflict",
240
+ 410: "Gone",
241
+ 411: "Length Required",
242
+ 412: "Precondition Failed",
243
+ 413: "Payload Too Large",
244
+ 414: "URI Too Long",
245
+ 415: "Unsupported Media Type",
246
+ 416: "Range Not Satisfiable",
247
+ 417: "Expectation Failed",
248
+ 418: "I'm a Teapot",
249
+ 421: "Misdirected Request",
250
+ 422: "Unprocessable Entity",
251
+ 423: "Locked",
252
+ 424: "Failed Dependency",
253
+ 425: "Too Early",
254
+ 426: "Upgrade Required",
255
+ 428: "Precondition Required",
256
+ 429: "Too Many Requests",
257
+ 431: "Request Header Fields Too Large",
258
+ 451: "Unavailable For Legal Reasons",
259
+ 500: "Internal Server Error",
260
+ 501: "Not Implemented",
261
+ 502: "Bad Gateway",
262
+ 503: "Service Unavailable",
263
+ 504: "Gateway Timeout",
264
+ 505: "HTTP Version Not Supported",
265
+ 506: "Variant Also Negotiates",
266
+ 507: "Insufficient Storage",
267
+ 508: "Loop Detected",
268
+ 510: "Not Extended",
269
+ 511: "Network Authentication Required"
270
+ };
271
+ let EHttpStatusCode = function(EHttpStatusCode$1) {
272
+ EHttpStatusCode$1[EHttpStatusCode$1["Continue"] = 100] = "Continue";
273
+ EHttpStatusCode$1[EHttpStatusCode$1["SwitchingProtocols"] = 101] = "SwitchingProtocols";
274
+ EHttpStatusCode$1[EHttpStatusCode$1["Processing"] = 102] = "Processing";
275
+ EHttpStatusCode$1[EHttpStatusCode$1["EarlyHints"] = 103] = "EarlyHints";
276
+ EHttpStatusCode$1[EHttpStatusCode$1["OK"] = 200] = "OK";
277
+ EHttpStatusCode$1[EHttpStatusCode$1["Created"] = 201] = "Created";
278
+ EHttpStatusCode$1[EHttpStatusCode$1["Accepted"] = 202] = "Accepted";
279
+ EHttpStatusCode$1[EHttpStatusCode$1["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
280
+ EHttpStatusCode$1[EHttpStatusCode$1["NoContent"] = 204] = "NoContent";
281
+ EHttpStatusCode$1[EHttpStatusCode$1["ResetContent"] = 205] = "ResetContent";
282
+ EHttpStatusCode$1[EHttpStatusCode$1["PartialContent"] = 206] = "PartialContent";
283
+ EHttpStatusCode$1[EHttpStatusCode$1["MultiStatus"] = 207] = "MultiStatus";
284
+ EHttpStatusCode$1[EHttpStatusCode$1["AlreadyReported"] = 208] = "AlreadyReported";
285
+ EHttpStatusCode$1[EHttpStatusCode$1["IMUsed"] = 226] = "IMUsed";
286
+ EHttpStatusCode$1[EHttpStatusCode$1["MultipleChoices"] = 300] = "MultipleChoices";
287
+ EHttpStatusCode$1[EHttpStatusCode$1["MovedPermanently"] = 301] = "MovedPermanently";
288
+ EHttpStatusCode$1[EHttpStatusCode$1["Found"] = 302] = "Found";
289
+ EHttpStatusCode$1[EHttpStatusCode$1["SeeOther"] = 303] = "SeeOther";
290
+ EHttpStatusCode$1[EHttpStatusCode$1["NotModified"] = 304] = "NotModified";
291
+ EHttpStatusCode$1[EHttpStatusCode$1["UseProxy"] = 305] = "UseProxy";
292
+ EHttpStatusCode$1[EHttpStatusCode$1["SwitchProxy"] = 306] = "SwitchProxy";
293
+ EHttpStatusCode$1[EHttpStatusCode$1["TemporaryRedirect"] = 307] = "TemporaryRedirect";
294
+ EHttpStatusCode$1[EHttpStatusCode$1["PermanentRedirect"] = 308] = "PermanentRedirect";
295
+ EHttpStatusCode$1[EHttpStatusCode$1["BadRequest"] = 400] = "BadRequest";
296
+ EHttpStatusCode$1[EHttpStatusCode$1["Unauthorized"] = 401] = "Unauthorized";
297
+ EHttpStatusCode$1[EHttpStatusCode$1["PaymentRequired"] = 402] = "PaymentRequired";
298
+ EHttpStatusCode$1[EHttpStatusCode$1["Forbidden"] = 403] = "Forbidden";
299
+ EHttpStatusCode$1[EHttpStatusCode$1["NotFound"] = 404] = "NotFound";
300
+ EHttpStatusCode$1[EHttpStatusCode$1["MethodNotAllowed"] = 405] = "MethodNotAllowed";
301
+ EHttpStatusCode$1[EHttpStatusCode$1["NotAcceptable"] = 406] = "NotAcceptable";
302
+ EHttpStatusCode$1[EHttpStatusCode$1["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
303
+ EHttpStatusCode$1[EHttpStatusCode$1["RequestTimeout"] = 408] = "RequestTimeout";
304
+ EHttpStatusCode$1[EHttpStatusCode$1["Conflict"] = 409] = "Conflict";
305
+ EHttpStatusCode$1[EHttpStatusCode$1["Gone"] = 410] = "Gone";
306
+ EHttpStatusCode$1[EHttpStatusCode$1["LengthRequired"] = 411] = "LengthRequired";
307
+ EHttpStatusCode$1[EHttpStatusCode$1["PreconditionFailed"] = 412] = "PreconditionFailed";
308
+ EHttpStatusCode$1[EHttpStatusCode$1["PayloadTooLarge"] = 413] = "PayloadTooLarge";
309
+ EHttpStatusCode$1[EHttpStatusCode$1["URITooLong"] = 414] = "URITooLong";
310
+ EHttpStatusCode$1[EHttpStatusCode$1["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
311
+ EHttpStatusCode$1[EHttpStatusCode$1["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
312
+ EHttpStatusCode$1[EHttpStatusCode$1["ExpectationFailed"] = 417] = "ExpectationFailed";
313
+ EHttpStatusCode$1[EHttpStatusCode$1["ImATeapot"] = 418] = "ImATeapot";
314
+ EHttpStatusCode$1[EHttpStatusCode$1["MisdirectedRequest"] = 421] = "MisdirectedRequest";
315
+ EHttpStatusCode$1[EHttpStatusCode$1["UnprocessableEntity"] = 422] = "UnprocessableEntity";
316
+ EHttpStatusCode$1[EHttpStatusCode$1["Locked"] = 423] = "Locked";
317
+ EHttpStatusCode$1[EHttpStatusCode$1["FailedDependency"] = 424] = "FailedDependency";
318
+ EHttpStatusCode$1[EHttpStatusCode$1["TooEarly"] = 425] = "TooEarly";
319
+ EHttpStatusCode$1[EHttpStatusCode$1["UpgradeRequired"] = 426] = "UpgradeRequired";
320
+ EHttpStatusCode$1[EHttpStatusCode$1["PreconditionRequired"] = 428] = "PreconditionRequired";
321
+ EHttpStatusCode$1[EHttpStatusCode$1["TooManyRequests"] = 429] = "TooManyRequests";
322
+ EHttpStatusCode$1[EHttpStatusCode$1["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
323
+ EHttpStatusCode$1[EHttpStatusCode$1["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
324
+ EHttpStatusCode$1[EHttpStatusCode$1["InternalServerError"] = 500] = "InternalServerError";
325
+ EHttpStatusCode$1[EHttpStatusCode$1["NotImplemented"] = 501] = "NotImplemented";
326
+ EHttpStatusCode$1[EHttpStatusCode$1["BadGateway"] = 502] = "BadGateway";
327
+ EHttpStatusCode$1[EHttpStatusCode$1["ServiceUnavailable"] = 503] = "ServiceUnavailable";
328
+ EHttpStatusCode$1[EHttpStatusCode$1["GatewayTimeout"] = 504] = "GatewayTimeout";
329
+ EHttpStatusCode$1[EHttpStatusCode$1["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
330
+ EHttpStatusCode$1[EHttpStatusCode$1["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
331
+ EHttpStatusCode$1[EHttpStatusCode$1["InsufficientStorage"] = 507] = "InsufficientStorage";
332
+ EHttpStatusCode$1[EHttpStatusCode$1["LoopDetected"] = 508] = "LoopDetected";
333
+ EHttpStatusCode$1[EHttpStatusCode$1["NotExtended"] = 510] = "NotExtended";
334
+ EHttpStatusCode$1[EHttpStatusCode$1["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
335
+ return EHttpStatusCode$1;
336
+ }({});
337
+
338
+ //#endregion
339
+ //#region packages/event-http/src/errors/error-renderer.ts
340
+ 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%);";
341
+ var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
342
+ renderHtml(response) {
343
+ const data = response.body || {};
344
+ response.setContentType("text/html");
345
+ const keys = Object.keys(data).filter((key) => ![
346
+ "statusCode",
347
+ "error",
348
+ "message"
349
+ ].includes(key));
350
+ 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.25"} </center>` + `${keys.length > 0 ? `<pre style="${preStyles}">${JSON.stringify({
351
+ ...data,
352
+ statusCode: undefined,
353
+ message: undefined,
354
+ error: undefined
355
+ }, null, " ")}</pre>` : ""}` + "</body></html>";
356
+ }
357
+ renderText(response) {
358
+ const data = response.body || {};
359
+ response.setContentType("text/plain");
360
+ const keys = Object.keys(data).filter((key) => ![
361
+ "statusCode",
362
+ "error",
363
+ "message"
364
+ ].includes(key));
365
+ return `${data.statusCode} ${httpStatusCodes[data.statusCode]}\n${data.message}` + `\n\n${keys.length > 0 ? `${JSON.stringify({
366
+ ...data,
367
+ statusCode: undefined,
368
+ message: undefined,
369
+ error: undefined
370
+ }, null, " ")}` : ""}`;
371
+ }
372
+ renderJson(response) {
373
+ const data = response.body || {};
374
+ response.setContentType("application/json");
375
+ const keys = Object.keys(data).filter((key) => ![
376
+ "statusCode",
377
+ "error",
378
+ "message"
379
+ ].includes(key));
380
+ 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(",")}` : ""}}`;
381
+ }
382
+ render(response) {
383
+ const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
384
+ response.status = response.body?.statusCode || 500;
385
+ if (acceptsJson()) return this.renderJson(response);
386
+ else if (acceptsHtml()) return this.renderHtml(response);
387
+ else if (acceptsText()) return this.renderText(response);
388
+ else return this.renderJson(response);
389
+ }
390
+ };
391
+ function escapeQuotes(s) {
392
+ return (typeof s === "number" ? s : s || "").toString().replace(/"/gu, "\\\"");
393
+ }
394
+
395
+ //#endregion
396
+ //#region packages/event-http/src/errors/http-error.ts
397
+ var HttpError = class extends Error {
398
+ name = "HttpError";
399
+ constructor(code = 500, _body = "") {
400
+ super(typeof _body === "string" ? _body : _body.message);
401
+ this.code = code;
402
+ this._body = _body;
403
+ }
404
+ get body() {
405
+ return typeof this._body === "string" ? {
406
+ statusCode: this.code,
407
+ message: this.message,
408
+ error: httpStatusCodes[this.code]
409
+ } : {
410
+ ...this._body,
411
+ statusCode: this.code,
412
+ message: this.message,
413
+ error: httpStatusCodes[this.code]
414
+ };
415
+ }
416
+ renderer;
417
+ attachRenderer(renderer) {
418
+ this.renderer = renderer;
419
+ }
420
+ getRenderer() {
421
+ return this.renderer;
422
+ }
423
+ };
424
+
107
425
  //#endregion
108
426
  //#region packages/event-http/src/composables/request.ts
109
427
  const xForwardedFor = "x-forwarded-for";
428
+ const DEFAULT_LIMITS = {
429
+ maxCompressed: 1048576,
430
+ maxInflated: 10485760,
431
+ maxRatio: 100,
432
+ readTimeoutMs: 1e4
433
+ };
110
434
  function useRequest() {
111
435
  const { store } = useHttpContext();
112
- const { init } = store("request");
436
+ const { init, get, set } = store("request");
113
437
  const event = store("event");
114
438
  const req = event.get("req");
115
- const rawBody = () => init("rawBody", () => new Promise((resolve, reject) => {
116
- let body = buffer.Buffer.from("");
117
- req.on("data", (chunk) => {
118
- body = buffer.Buffer.concat([body, chunk]);
119
- });
120
- req.on("error", (err) => {
121
- reject(err);
122
- });
123
- req.on("end", () => {
124
- resolve(body);
125
- });
126
- }));
439
+ const contentEncoding = req.headers["content-encoding"];
440
+ const contentEncodings = () => init("contentEncodings", () => (contentEncoding || "").split(",").map((p) => p.trim()).filter((p) => !!p));
441
+ const isCompressed = () => init("isCompressed", () => {
442
+ const parts = contentEncodings();
443
+ for (const p of parts) if ([
444
+ "deflate",
445
+ "gzip",
446
+ "br"
447
+ ].includes(p)) return true;
448
+ return false;
449
+ });
450
+ const getMaxCompressed = () => get("maxCompressed") ?? DEFAULT_LIMITS.maxCompressed;
451
+ const setMaxCompressed = (limit) => set("maxCompressed", limit);
452
+ const getReadTimeoutMs = () => get("readTimeoutMs") ?? DEFAULT_LIMITS.readTimeoutMs;
453
+ const setReadTimeoutMs = (limit) => set("readTimeoutMs", limit);
454
+ const getMaxInflated = () => get("maxInflated") ?? DEFAULT_LIMITS.maxInflated;
455
+ const setMaxInflated = (limit) => set("maxInflated", limit);
456
+ const rawBody = () => init("rawBody", async () => {
457
+ const encs = contentEncodings();
458
+ const isZip = isCompressed();
459
+ const streamable = isZip && encodingSupportsStream(encs);
460
+ const maxCompressed = getMaxCompressed();
461
+ const maxInflated = getMaxInflated();
462
+ const timeoutMs = getReadTimeoutMs();
463
+ const cl = Number(req.headers["content-length"] ?? 0);
464
+ const upfrontLimit = isZip ? maxCompressed : maxInflated;
465
+ if (cl && cl > upfrontLimit) throw new HttpError(413, "Payload Too Large");
466
+ for (const enc of encs) if (!compressors[enc]) throw new HttpError(415, `Unsupported Content-Encoding "${enc}"`);
467
+ let timer = null;
468
+ function resetTimer() {
469
+ if (timeoutMs === 0) return;
470
+ clearTimer();
471
+ timer = setTimeout(() => {
472
+ clearTimer();
473
+ req.destroy();
474
+ }, timeoutMs);
475
+ }
476
+ function clearTimer() {
477
+ if (timer) {
478
+ clearTimeout(timer);
479
+ timer = null;
480
+ }
481
+ }
482
+ let rawBytes = 0;
483
+ async function* limitedCompressed() {
484
+ resetTimer();
485
+ try {
486
+ for await (const chunk of req) {
487
+ rawBytes += chunk.length;
488
+ if (rawBytes > upfrontLimit) {
489
+ req.destroy();
490
+ throw new HttpError(413, "Payload Too Large");
491
+ }
492
+ resetTimer();
493
+ yield chunk;
494
+ }
495
+ } finally {
496
+ clearTimer();
497
+ }
498
+ }
499
+ let stream$1 = limitedCompressed();
500
+ if (streamable) stream$1 = await uncompressBodyStream(encs, stream$1);
501
+ const chunks = [];
502
+ let inflatedBytes = 0;
503
+ try {
504
+ for await (const chunk of stream$1) {
505
+ inflatedBytes += chunk.length;
506
+ if (inflatedBytes > maxInflated) throw new HttpError(413, "Inflated body too large");
507
+ chunks.push(chunk);
508
+ }
509
+ } catch (error) {
510
+ if (error instanceof HttpError) throw error;
511
+ throw new HttpError(408, "Request body timeout");
512
+ }
513
+ let body = buffer.Buffer.concat(chunks);
514
+ if (!streamable && isZip) {
515
+ body = await uncompressBody(encs, body);
516
+ inflatedBytes = body.byteLength;
517
+ if (inflatedBytes > maxInflated) throw new HttpError(413, "Inflated body too large");
518
+ }
519
+ return body;
520
+ });
127
521
  const reqId = (0, __wooksjs_event_core.useEventId)().getId;
128
522
  const forwardedIp = () => init("forwardedIp", () => {
129
523
  if (typeof req.headers[xForwardedFor] === "string" && req.headers[xForwardedFor]) return req.headers[xForwardedFor].split(",").shift()?.trim();
@@ -146,7 +540,14 @@ else return remoteIp();
146
540
  rawBody,
147
541
  reqId,
148
542
  getIp,
149
- getIpList
543
+ getIpList,
544
+ isCompressed,
545
+ getMaxCompressed,
546
+ setMaxCompressed,
547
+ getReadTimeoutMs,
548
+ setReadTimeoutMs,
549
+ getMaxInflated,
550
+ setMaxInflated
150
551
  };
151
552
  }
152
553
 
@@ -387,11 +788,15 @@ function useStatus() {
387
788
  //#region packages/event-http/src/utils/url-search-params.ts
388
789
  var WooksURLSearchParams = class extends url.URLSearchParams {
389
790
  toJson() {
390
- const json = {};
791
+ const json = Object.create(null);
391
792
  for (const [key, value] of this.entries()) if (isArrayParam(key)) {
392
793
  const a = json[key] = json[key] || [];
393
794
  a.push(value);
394
- } else json[key] = value;
795
+ } else {
796
+ if (key === "__proto__") throw new HttpError(400, `Illegal key name "${key}"`);
797
+ if (key in json) throw new HttpError(400, `Duplicate key "${key}"`);
798
+ json[key] = value;
799
+ }
395
800
  return json;
396
801
  }
397
802
  };
@@ -417,245 +822,6 @@ function useSearchParams() {
417
822
  };
418
823
  }
419
824
 
420
- //#endregion
421
- //#region packages/event-http/src/response/renderer.ts
422
- var BaseHttpResponseRenderer = class {
423
- render(response) {
424
- if (typeof response.body === "string" || typeof response.body === "boolean" || typeof response.body === "number") {
425
- if (!response.getContentType()) response.setContentType("text/plain");
426
- return response.body.toString();
427
- }
428
- if (response.body === undefined) return "";
429
- if (response.body instanceof Uint8Array) return response.body;
430
- if (typeof response.body === "object") {
431
- if (!response.getContentType()) response.setContentType("application/json");
432
- return JSON.stringify(response.body);
433
- }
434
- throw new Error(`Unsupported body format "${typeof response.body}"`);
435
- }
436
- };
437
-
438
- //#endregion
439
- //#region packages/event-http/src/utils/status-codes.ts
440
- const httpStatusCodes = {
441
- 100: "Continue",
442
- 101: "Switching protocols",
443
- 102: "Processing",
444
- 103: "Early Hints",
445
- 200: "OK",
446
- 201: "Created",
447
- 202: "Accepted",
448
- 203: "Non-Authoritative Information",
449
- 204: "No Content",
450
- 205: "Reset Content",
451
- 206: "Partial Content",
452
- 207: "Multi-Status",
453
- 208: "Already Reported",
454
- 226: "IM Used",
455
- 300: "Multiple Choices",
456
- 301: "Moved Permanently",
457
- 302: "Found (Previously \"Moved Temporarily\")",
458
- 303: "See Other",
459
- 304: "Not Modified",
460
- 305: "Use Proxy",
461
- 306: "Switch Proxy",
462
- 307: "Temporary Redirect",
463
- 308: "Permanent Redirect",
464
- 400: "Bad Request",
465
- 401: "Unauthorized",
466
- 402: "Payment Required",
467
- 403: "Forbidden",
468
- 404: "Not Found",
469
- 405: "Method Not Allowed",
470
- 406: "Not Acceptable",
471
- 407: "Proxy Authentication Required",
472
- 408: "Request Timeout",
473
- 409: "Conflict",
474
- 410: "Gone",
475
- 411: "Length Required",
476
- 412: "Precondition Failed",
477
- 413: "Payload Too Large",
478
- 414: "URI Too Long",
479
- 415: "Unsupported Media Type",
480
- 416: "Range Not Satisfiable",
481
- 417: "Expectation Failed",
482
- 418: "I'm a Teapot",
483
- 421: "Misdirected Request",
484
- 422: "Unprocessable Entity",
485
- 423: "Locked",
486
- 424: "Failed Dependency",
487
- 425: "Too Early",
488
- 426: "Upgrade Required",
489
- 428: "Precondition Required",
490
- 429: "Too Many Requests",
491
- 431: "Request Header Fields Too Large",
492
- 451: "Unavailable For Legal Reasons",
493
- 500: "Internal Server Error",
494
- 501: "Not Implemented",
495
- 502: "Bad Gateway",
496
- 503: "Service Unavailable",
497
- 504: "Gateway Timeout",
498
- 505: "HTTP Version Not Supported",
499
- 506: "Variant Also Negotiates",
500
- 507: "Insufficient Storage",
501
- 508: "Loop Detected",
502
- 510: "Not Extended",
503
- 511: "Network Authentication Required"
504
- };
505
- let EHttpStatusCode = function(EHttpStatusCode$1) {
506
- EHttpStatusCode$1[EHttpStatusCode$1["Continue"] = 100] = "Continue";
507
- EHttpStatusCode$1[EHttpStatusCode$1["SwitchingProtocols"] = 101] = "SwitchingProtocols";
508
- EHttpStatusCode$1[EHttpStatusCode$1["Processing"] = 102] = "Processing";
509
- EHttpStatusCode$1[EHttpStatusCode$1["EarlyHints"] = 103] = "EarlyHints";
510
- EHttpStatusCode$1[EHttpStatusCode$1["OK"] = 200] = "OK";
511
- EHttpStatusCode$1[EHttpStatusCode$1["Created"] = 201] = "Created";
512
- EHttpStatusCode$1[EHttpStatusCode$1["Accepted"] = 202] = "Accepted";
513
- EHttpStatusCode$1[EHttpStatusCode$1["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
514
- EHttpStatusCode$1[EHttpStatusCode$1["NoContent"] = 204] = "NoContent";
515
- EHttpStatusCode$1[EHttpStatusCode$1["ResetContent"] = 205] = "ResetContent";
516
- EHttpStatusCode$1[EHttpStatusCode$1["PartialContent"] = 206] = "PartialContent";
517
- EHttpStatusCode$1[EHttpStatusCode$1["MultiStatus"] = 207] = "MultiStatus";
518
- EHttpStatusCode$1[EHttpStatusCode$1["AlreadyReported"] = 208] = "AlreadyReported";
519
- EHttpStatusCode$1[EHttpStatusCode$1["IMUsed"] = 226] = "IMUsed";
520
- EHttpStatusCode$1[EHttpStatusCode$1["MultipleChoices"] = 300] = "MultipleChoices";
521
- EHttpStatusCode$1[EHttpStatusCode$1["MovedPermanently"] = 301] = "MovedPermanently";
522
- EHttpStatusCode$1[EHttpStatusCode$1["Found"] = 302] = "Found";
523
- EHttpStatusCode$1[EHttpStatusCode$1["SeeOther"] = 303] = "SeeOther";
524
- EHttpStatusCode$1[EHttpStatusCode$1["NotModified"] = 304] = "NotModified";
525
- EHttpStatusCode$1[EHttpStatusCode$1["UseProxy"] = 305] = "UseProxy";
526
- EHttpStatusCode$1[EHttpStatusCode$1["SwitchProxy"] = 306] = "SwitchProxy";
527
- EHttpStatusCode$1[EHttpStatusCode$1["TemporaryRedirect"] = 307] = "TemporaryRedirect";
528
- EHttpStatusCode$1[EHttpStatusCode$1["PermanentRedirect"] = 308] = "PermanentRedirect";
529
- EHttpStatusCode$1[EHttpStatusCode$1["BadRequest"] = 400] = "BadRequest";
530
- EHttpStatusCode$1[EHttpStatusCode$1["Unauthorized"] = 401] = "Unauthorized";
531
- EHttpStatusCode$1[EHttpStatusCode$1["PaymentRequired"] = 402] = "PaymentRequired";
532
- EHttpStatusCode$1[EHttpStatusCode$1["Forbidden"] = 403] = "Forbidden";
533
- EHttpStatusCode$1[EHttpStatusCode$1["NotFound"] = 404] = "NotFound";
534
- EHttpStatusCode$1[EHttpStatusCode$1["MethodNotAllowed"] = 405] = "MethodNotAllowed";
535
- EHttpStatusCode$1[EHttpStatusCode$1["NotAcceptable"] = 406] = "NotAcceptable";
536
- EHttpStatusCode$1[EHttpStatusCode$1["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
537
- EHttpStatusCode$1[EHttpStatusCode$1["RequestTimeout"] = 408] = "RequestTimeout";
538
- EHttpStatusCode$1[EHttpStatusCode$1["Conflict"] = 409] = "Conflict";
539
- EHttpStatusCode$1[EHttpStatusCode$1["Gone"] = 410] = "Gone";
540
- EHttpStatusCode$1[EHttpStatusCode$1["LengthRequired"] = 411] = "LengthRequired";
541
- EHttpStatusCode$1[EHttpStatusCode$1["PreconditionFailed"] = 412] = "PreconditionFailed";
542
- EHttpStatusCode$1[EHttpStatusCode$1["PayloadTooLarge"] = 413] = "PayloadTooLarge";
543
- EHttpStatusCode$1[EHttpStatusCode$1["URITooLong"] = 414] = "URITooLong";
544
- EHttpStatusCode$1[EHttpStatusCode$1["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
545
- EHttpStatusCode$1[EHttpStatusCode$1["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
546
- EHttpStatusCode$1[EHttpStatusCode$1["ExpectationFailed"] = 417] = "ExpectationFailed";
547
- EHttpStatusCode$1[EHttpStatusCode$1["ImATeapot"] = 418] = "ImATeapot";
548
- EHttpStatusCode$1[EHttpStatusCode$1["MisdirectedRequest"] = 421] = "MisdirectedRequest";
549
- EHttpStatusCode$1[EHttpStatusCode$1["UnprocessableEntity"] = 422] = "UnprocessableEntity";
550
- EHttpStatusCode$1[EHttpStatusCode$1["Locked"] = 423] = "Locked";
551
- EHttpStatusCode$1[EHttpStatusCode$1["FailedDependency"] = 424] = "FailedDependency";
552
- EHttpStatusCode$1[EHttpStatusCode$1["TooEarly"] = 425] = "TooEarly";
553
- EHttpStatusCode$1[EHttpStatusCode$1["UpgradeRequired"] = 426] = "UpgradeRequired";
554
- EHttpStatusCode$1[EHttpStatusCode$1["PreconditionRequired"] = 428] = "PreconditionRequired";
555
- EHttpStatusCode$1[EHttpStatusCode$1["TooManyRequests"] = 429] = "TooManyRequests";
556
- EHttpStatusCode$1[EHttpStatusCode$1["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
557
- EHttpStatusCode$1[EHttpStatusCode$1["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
558
- EHttpStatusCode$1[EHttpStatusCode$1["InternalServerError"] = 500] = "InternalServerError";
559
- EHttpStatusCode$1[EHttpStatusCode$1["NotImplemented"] = 501] = "NotImplemented";
560
- EHttpStatusCode$1[EHttpStatusCode$1["BadGateway"] = 502] = "BadGateway";
561
- EHttpStatusCode$1[EHttpStatusCode$1["ServiceUnavailable"] = 503] = "ServiceUnavailable";
562
- EHttpStatusCode$1[EHttpStatusCode$1["GatewayTimeout"] = 504] = "GatewayTimeout";
563
- EHttpStatusCode$1[EHttpStatusCode$1["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
564
- EHttpStatusCode$1[EHttpStatusCode$1["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
565
- EHttpStatusCode$1[EHttpStatusCode$1["InsufficientStorage"] = 507] = "InsufficientStorage";
566
- EHttpStatusCode$1[EHttpStatusCode$1["LoopDetected"] = 508] = "LoopDetected";
567
- EHttpStatusCode$1[EHttpStatusCode$1["NotExtended"] = 510] = "NotExtended";
568
- EHttpStatusCode$1[EHttpStatusCode$1["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
569
- return EHttpStatusCode$1;
570
- }({});
571
-
572
- //#endregion
573
- //#region packages/event-http/src/errors/error-renderer.ts
574
- 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%);";
575
- var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
576
- renderHtml(response) {
577
- const data = response.body || {};
578
- response.setContentType("text/html");
579
- const keys = Object.keys(data).filter((key) => ![
580
- "statusCode",
581
- "error",
582
- "message"
583
- ].includes(key));
584
- 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({
585
- ...data,
586
- statusCode: undefined,
587
- message: undefined,
588
- error: undefined
589
- }, null, " ")}</pre>` : ""}` + "</body></html>";
590
- }
591
- renderText(response) {
592
- const data = response.body || {};
593
- response.setContentType("text/plain");
594
- const keys = Object.keys(data).filter((key) => ![
595
- "statusCode",
596
- "error",
597
- "message"
598
- ].includes(key));
599
- return `${data.statusCode} ${httpStatusCodes[data.statusCode]}\n${data.message}` + `\n\n${keys.length > 0 ? `${JSON.stringify({
600
- ...data,
601
- statusCode: undefined,
602
- message: undefined,
603
- error: undefined
604
- }, null, " ")}` : ""}`;
605
- }
606
- renderJson(response) {
607
- const data = response.body || {};
608
- response.setContentType("application/json");
609
- const keys = Object.keys(data).filter((key) => ![
610
- "statusCode",
611
- "error",
612
- "message"
613
- ].includes(key));
614
- 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(",")}` : ""}}`;
615
- }
616
- render(response) {
617
- const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
618
- response.status = response.body?.statusCode || 500;
619
- if (acceptsJson()) return this.renderJson(response);
620
- else if (acceptsHtml()) return this.renderHtml(response);
621
- else if (acceptsText()) return this.renderText(response);
622
- else return this.renderJson(response);
623
- }
624
- };
625
- function escapeQuotes(s) {
626
- return (typeof s === "number" ? s : s || "").toString().replace(/"/gu, "\\\"");
627
- }
628
-
629
- //#endregion
630
- //#region packages/event-http/src/errors/http-error.ts
631
- var HttpError = class extends Error {
632
- name = "HttpError";
633
- constructor(code = 500, _body = "") {
634
- super(typeof _body === "string" ? _body : _body.message);
635
- this.code = code;
636
- this._body = _body;
637
- }
638
- get body() {
639
- return typeof this._body === "string" ? {
640
- statusCode: this.code,
641
- message: this.message,
642
- error: httpStatusCodes[this.code]
643
- } : {
644
- ...this._body,
645
- statusCode: this.code,
646
- message: this.message,
647
- error: httpStatusCodes[this.code]
648
- };
649
- }
650
- renderer;
651
- attachRenderer(renderer) {
652
- this.renderer = renderer;
653
- }
654
- getRenderer() {
655
- return this.renderer;
656
- }
657
- };
658
-
659
825
  //#endregion
660
826
  //#region packages/event-http/src/response/core.ts
661
827
  const defaultStatus = {
@@ -993,6 +1159,7 @@ function createHttpApp(opts, wooks$1) {
993
1159
  //#endregion
994
1160
  exports.BaseHttpResponse = BaseHttpResponse
995
1161
  exports.BaseHttpResponseRenderer = BaseHttpResponseRenderer
1162
+ exports.DEFAULT_LIMITS = DEFAULT_LIMITS
996
1163
  exports.EHttpStatusCode = EHttpStatusCode
997
1164
  exports.HttpError = HttpError
998
1165
  exports.HttpErrorRenderer = HttpErrorRenderer