@bepalo/router 1.2.13 → 1.5.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -22
- package/dist/cjs/helpers.d.ts +83 -63
- package/dist/cjs/helpers.d.ts.map +1 -1
- package/dist/cjs/helpers.js +94 -91
- package/dist/cjs/helpers.js.map +1 -1
- package/dist/cjs/middlewares.d.ts +122 -3
- package/dist/cjs/middlewares.d.ts.map +1 -1
- package/dist/cjs/middlewares.js +188 -1
- package/dist/cjs/middlewares.js.map +1 -1
- package/dist/cjs/router.d.ts +1 -2
- package/dist/cjs/router.d.ts.map +1 -1
- package/dist/cjs/router.js.map +1 -1
- package/dist/cjs/types.d.ts +29 -7
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/upload-stream.d.ts +3 -3
- package/dist/cjs/upload-stream.d.ts.map +1 -1
- package/dist/cjs/upload-stream.js +1 -2
- package/dist/cjs/upload-stream.js.map +1 -1
- package/dist/helpers.d.ts +83 -63
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +94 -91
- package/dist/helpers.js.map +1 -1
- package/dist/middlewares.d.ts +122 -3
- package/dist/middlewares.d.ts.map +1 -1
- package/dist/middlewares.js +188 -1
- package/dist/middlewares.js.map +1 -1
- package/dist/router.d.ts +1 -2
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js.map +1 -1
- package/dist/types.d.ts +29 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/upload-stream.d.ts +3 -3
- package/dist/upload-stream.d.ts.map +1 -1
- package/dist/upload-stream.js +1 -2
- package/dist/upload-stream.js.map +1 -1
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -49,16 +49,16 @@
|
|
|
49
49
|
## ✨ Features
|
|
50
50
|
|
|
51
51
|
- ⚡ **High Performance** - Built on a radix tree for O(k) route matching (where k is path length)
|
|
52
|
-
- 🎯 **Flexible Routing** - Support for path parameters, wildcards (`*`, `.*`, `**`, `.**`), and all HTTP methods
|
|
53
|
-
- 🎭 **Multiple Handler Types** - Filters, hooks, handlers, fallbacks, and catchers
|
|
52
|
+
- 🎯 **Flexible Routing Engine** - Support for path parameters, wildcards (`*`, `.*`, `**`, `.**`), and all HTTP methods
|
|
53
|
+
- 🎭 **Multiple Handler Types** - Filters, hooks, afters, handlers, fallbacks, and catchers
|
|
54
54
|
- 🔌 **Middleware Pipeline** - Chain multiple handlers with early exit capability
|
|
55
55
|
- 🛡️ **Error Handling** - Built-in error catching with contextual error handlers
|
|
56
56
|
- 🔄 **Method-Based Routing** - Separate routing trees for each HTTP method
|
|
57
|
-
- 📦 **Local Dependencies** - Only @bepalo
|
|
57
|
+
- 📦 **Local Dependencies** - Minimal Dependencies — Only internal @bepalo packages
|
|
58
58
|
- 🌐 **Runtime Agnostic** - Works with Bun, Deno, Node.js, and other runtimes
|
|
59
59
|
- 🔧 **TypeScript Ready** - Full type definitions included
|
|
60
|
-
- 🧩 **Router
|
|
61
|
-
- 🛠️ **Helper
|
|
60
|
+
- 🧩 **Composable Router Architecture** - Append one router to another with a path prefix.
|
|
61
|
+
- 🛠️ **Built-in Helper Utilities** - Built-in response helpers (json, html, parseBody, upload, etc.)
|
|
62
62
|
- 🔐 **Middleware Integration** - CORS, rate limiting, authentication helpers
|
|
63
63
|
|
|
64
64
|
## 🚀 Get Started
|
|
@@ -226,7 +226,7 @@ router.filter(
|
|
|
226
226
|
|
|
227
227
|
// Main route
|
|
228
228
|
router.handle("GET /", () =>
|
|
229
|
-
html("<h1>Welcome! Enjoy using @
|
|
229
|
+
html("<h1>Welcome! Enjoy using @bepalo/router</h1>"),
|
|
230
230
|
);
|
|
231
231
|
router.handle("GET /status", () => status(200));
|
|
232
232
|
|
|
@@ -351,7 +351,7 @@ Deno.serve(
|
|
|
351
351
|
#### Nodejs
|
|
352
352
|
|
|
353
353
|
```js
|
|
354
|
-
//
|
|
354
|
+
// Node.js compatibility example (uses Fetch bridge; not optimized)
|
|
355
355
|
http
|
|
356
356
|
.createServer(async (req, res) => {
|
|
357
357
|
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
@@ -541,6 +541,7 @@ router.respond(
|
|
|
541
541
|
|
|
542
542
|
```ts
|
|
543
543
|
import {
|
|
544
|
+
Status, // Status enum
|
|
544
545
|
status, // HTTP status response
|
|
545
546
|
redirect, // Redirect response with location header set
|
|
546
547
|
forward, // forward to other path within the router.
|
|
@@ -568,10 +569,45 @@ const router = new Router();
|
|
|
568
569
|
router.handle("GET /text", () => text("Hello World"));
|
|
569
570
|
router.handle("GET /html", () => html("<h1>Title</h1>"));
|
|
570
571
|
router.handle("GET /json", () => json({ data: "value" }));
|
|
571
|
-
router.handle("GET /status", () => status(
|
|
572
|
+
router.handle("GET /status", () => status(Status._204_NoContent, null)); // No Content
|
|
572
573
|
router.handle("GET /intro.mp4", () => blob(Bun.file("./intro.mp4")));
|
|
573
574
|
router.handle("GET /download", () => octetStream(Bun.file("./intro.mp4")));
|
|
574
575
|
|
|
576
|
+
router.handle("GET /new-location", () => html("GET new-location"));
|
|
577
|
+
// router.handle("POST /new-location", () => html("POST new-location"));
|
|
578
|
+
router.handle<CTXBody>("POST /new-location", [
|
|
579
|
+
parseBody({ once: true, clone: true }),
|
|
580
|
+
(req, { body }) => console.log(body),
|
|
581
|
+
forward("/new-location2"),
|
|
582
|
+
]);
|
|
583
|
+
router.handle<CTXBody>("POST /new-location2", [
|
|
584
|
+
parseBody({ once: true, clone: false }),
|
|
585
|
+
(req, { body }) => console.log(body),
|
|
586
|
+
() => html("POST new-location2"),
|
|
587
|
+
]);
|
|
588
|
+
router.handle("GET /redirected", () => redirect("/new-location"));
|
|
589
|
+
router.handle("GET /forwarded", forward("/new-location"));
|
|
590
|
+
// this would set the headers:
|
|
591
|
+
// "x-forwarded-path": "/forwarded"
|
|
592
|
+
// "x-original-path": "/forwarded"
|
|
593
|
+
router.handle<CTXBody>("PUT /forwarded-with-new-method", [
|
|
594
|
+
parseBody({ once: true, clone: true }),
|
|
595
|
+
(req, { body }) => console.log(body),
|
|
596
|
+
forward("/new-location", { method: "POST" }),
|
|
597
|
+
]);
|
|
598
|
+
// this would set the headers:
|
|
599
|
+
// "x-forwarded-method": "PUT"
|
|
600
|
+
// "x-forwarded-path": "/new-location"
|
|
601
|
+
// "x-original-path": "/forwarded-with-new-method"
|
|
602
|
+
router.handle("GET /forwarded-conditional", function (this: Router, req, ctx) {
|
|
603
|
+
if (req.headers.get("authorization"))
|
|
604
|
+
return forward("/new-location").bind(this)(req, ctx);
|
|
605
|
+
// or return forward("/new-location").apply(this, [req, ctx]);
|
|
606
|
+
// NOTE: be careful when binding instance `router` instead of `this`
|
|
607
|
+
// as it might be called from a different router due to append.
|
|
608
|
+
return status(Status._401_Unauthorized);
|
|
609
|
+
});
|
|
610
|
+
|
|
575
611
|
router.handle<CTXCookie>("GET /cookie", [
|
|
576
612
|
parseCookie(),
|
|
577
613
|
(req, { cookie }) => json({ cookie }),
|
|
@@ -580,7 +616,8 @@ router.handle<CTXCookie>("GET /cookie", [
|
|
|
580
616
|
router.handle<CTXBody>("POST /cookie", [
|
|
581
617
|
parseBody(),
|
|
582
618
|
(req, { body }) => {
|
|
583
|
-
return status(
|
|
619
|
+
return status(Status._200_OK, "OK", {
|
|
620
|
+
// or `, undefined, {` and the status text will be set
|
|
584
621
|
headers: [
|
|
585
622
|
...Object.entries(body).map(([name, value]) =>
|
|
586
623
|
setCookie(name, String(value), {
|
|
@@ -595,24 +632,55 @@ router.handle<CTXBody>("POST /cookie", [
|
|
|
595
632
|
|
|
596
633
|
router.handle("DELETE /cookie/:name", [
|
|
597
634
|
(req, ctx) =>
|
|
598
|
-
status(
|
|
635
|
+
status(Status._200_OK, undefined, {
|
|
599
636
|
headers: [clearCookie(ctx.params.name, { path: "/" })],
|
|
600
637
|
}),
|
|
601
638
|
]);
|
|
602
639
|
|
|
640
|
+
// be sure to create ./upload folder for this example
|
|
603
641
|
router.handle<CTXUpload>("POST /upload", [
|
|
604
642
|
(req, ctx) => {
|
|
605
643
|
let file: Bun.BunFile;
|
|
606
644
|
let fileWriter: Bun.FileSink;
|
|
607
645
|
return parseUploadStreaming({
|
|
608
646
|
allowedTypes: ["image/jpeg"],
|
|
609
|
-
|
|
610
|
-
|
|
647
|
+
maxFileSize: 5 * 1024 * 1024,
|
|
648
|
+
maxTotalSize: 5 * 1024 * 1024 + 1024,
|
|
649
|
+
maxFields: 1,
|
|
650
|
+
maxFiles: 1,
|
|
651
|
+
// uploadIdGenerator: () =>
|
|
652
|
+
// `upload_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
653
|
+
async onUploadStart(uploadId, totalSize) {
|
|
654
|
+
console.log("onUploadStart", { uploadId, totalSize });
|
|
655
|
+
},
|
|
656
|
+
async onError(uploadId, error) {
|
|
657
|
+
console.error("onError", uploadId, error);
|
|
658
|
+
},
|
|
659
|
+
async onFileError(uploadId, fieldName, fileName, error) {
|
|
660
|
+
console.error("onFileError", uploadId, error);
|
|
661
|
+
},
|
|
662
|
+
async onField(uploadId, fieldName, value) {
|
|
663
|
+
console.log("onField", { uploadId, fieldName, value });
|
|
664
|
+
},
|
|
665
|
+
async onFileStart(uploadId, fieldName, fileName, contentType) {
|
|
666
|
+
console.log("onFileStart", {
|
|
667
|
+
uploadId,
|
|
668
|
+
fieldName,
|
|
669
|
+
fileName,
|
|
670
|
+
contentType,
|
|
671
|
+
});
|
|
611
672
|
const ext = fileName.substring(fileName.lastIndexOf("."));
|
|
612
|
-
|
|
673
|
+
const customFilename = uploadId + ext;
|
|
674
|
+
file = Bun.file("./uploads/" + customFilename);
|
|
613
675
|
fileWriter = file.writer();
|
|
676
|
+
return {
|
|
677
|
+
customFilename,
|
|
678
|
+
// metadata
|
|
679
|
+
};
|
|
614
680
|
},
|
|
615
681
|
async onFileChunk(uploadId, fieldName, fileName, chunk, offset, isLast) {
|
|
682
|
+
const chunkSize = chunk.byteLength;
|
|
683
|
+
console.log("onFileChunk", { uploadId, chunkSize, offset, isLast });
|
|
616
684
|
fileWriter.write(chunk);
|
|
617
685
|
},
|
|
618
686
|
async onFileComplete(
|
|
@@ -623,17 +691,26 @@ router.handle<CTXUpload>("POST /upload", [
|
|
|
623
691
|
customFilename,
|
|
624
692
|
metadata,
|
|
625
693
|
) {
|
|
626
|
-
console.log(
|
|
694
|
+
console.log("onFileComplete", {
|
|
695
|
+
uploadId,
|
|
696
|
+
fieldName,
|
|
697
|
+
fileName,
|
|
698
|
+
fileSize,
|
|
699
|
+
customFilename,
|
|
700
|
+
metadata,
|
|
701
|
+
});
|
|
702
|
+
if (fileWriter) {
|
|
703
|
+
fileWriter.end();
|
|
704
|
+
}
|
|
627
705
|
},
|
|
628
706
|
async onUploadComplete(uploadId, success) {
|
|
629
|
-
console.log({ uploadId, success });
|
|
707
|
+
console.log("onUploadComplete", { uploadId, success });
|
|
630
708
|
},
|
|
631
709
|
})(req, ctx);
|
|
632
710
|
},
|
|
633
711
|
(req, { uploadId, fields, files }) => {
|
|
634
712
|
console.log({ uploadId, fields, files });
|
|
635
|
-
|
|
636
|
-
return status(200);
|
|
713
|
+
return status(Status._200_OK);
|
|
637
714
|
},
|
|
638
715
|
]);
|
|
639
716
|
```
|
|
@@ -642,12 +719,21 @@ router.handle<CTXUpload>("POST /upload", [
|
|
|
642
719
|
|
|
643
720
|
```ts
|
|
644
721
|
import {
|
|
722
|
+
type CTXCookie,
|
|
723
|
+
type CTXBody,
|
|
724
|
+
type CTXAuth,
|
|
725
|
+
type CTXUpload,
|
|
726
|
+
parseCookie, // Cookie parser
|
|
727
|
+
parseBody, // Body parser
|
|
728
|
+
parseUploadStreaming, // multi-part-form-data and file upload stream parser
|
|
645
729
|
cors, // CORS middleware
|
|
646
730
|
limitRate, // Rate limiting
|
|
731
|
+
authenticate, // Generic authentication middleware
|
|
732
|
+
authorize, // Generic authorization middleware
|
|
647
733
|
authBasic, // Basic authentication
|
|
648
734
|
authAPIKey, // API key authentication
|
|
649
735
|
authJWT, // JWT authentication
|
|
650
|
-
} from "@bepalo/router
|
|
736
|
+
} from "@bepalo/router";
|
|
651
737
|
```
|
|
652
738
|
|
|
653
739
|
### 🔧 Advanced Usage
|
|
@@ -768,13 +854,14 @@ The router uses a radix tree (trie) data structure for route matching, providing
|
|
|
768
854
|
| Feature | @bepalo/router | Express | Hono | Fastify |
|
|
769
855
|
| ------------------------------- | -------------- | ------- | ---- | ------- |
|
|
770
856
|
| Radix Tree Routing | ✅ | ❌ | ✅ | ✅ |
|
|
771
|
-
| Few Dependencies | ✅ | ❌ |
|
|
857
|
+
| Few Dependencies | ✅ | ❌ | ⚠️ | ⚠️ |
|
|
772
858
|
| TypeScript Native | ✅ | ❌ | ✅ | ✅ |
|
|
773
|
-
| Extended Handler Phases | ✅ |
|
|
774
|
-
| Built-in Middleware | ✅ |
|
|
775
|
-
| Runtime Agnostic | ✅ | ❌ | ✅ |
|
|
859
|
+
| Extended Handler Phases | ✅ | ❌ | ❌ | ⚠️ |
|
|
860
|
+
| Built-in Middleware | ✅ | ⚠️ | ✅ | ✅ |
|
|
861
|
+
| Runtime Agnostic | ✅ | ❌ | ✅ | ⚠️ |
|
|
776
862
|
| Router Composition | ✅ | ✅ | ✅ | ✅ |
|
|
777
863
|
| Structured Multi-Phase Pipeline | ✅ | ❌ | ❌ | ❌ |
|
|
864
|
+
| Server | ❌ | ✅ | ⚠️ | ✅ |
|
|
778
865
|
|
|
779
866
|
## 📄 License
|
|
780
867
|
|
package/dist/cjs/helpers.d.ts
CHANGED
|
@@ -1,17 +1,80 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Handler } from "./types";
|
|
1
|
+
import type { BoundHandler, HttpMethod } from "./types";
|
|
3
2
|
export * from "./upload-stream";
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export declare enum Status {
|
|
4
|
+
_100_Continue = 100,
|
|
5
|
+
_101_SwitchingProtocols = 101,
|
|
6
|
+
_102_Processing = 102,
|
|
7
|
+
_103_EarlyHints = 103,
|
|
8
|
+
_200_OK = 200,
|
|
9
|
+
_201_Created = 201,
|
|
10
|
+
_202_Accepted = 202,
|
|
11
|
+
_203_NonAuthoritativeInformation = 203,
|
|
12
|
+
_204_NoContent = 204,
|
|
13
|
+
_205_ResetContent = 205,
|
|
14
|
+
_206_PartialContent = 206,
|
|
15
|
+
_207_MultiStatus = 207,
|
|
16
|
+
_208_AlreadyReported = 208,
|
|
17
|
+
_226_IMUsed = 226,
|
|
18
|
+
_300_MultipleChoices = 300,
|
|
19
|
+
_301_MovedPermanently = 301,
|
|
20
|
+
_302_Found = 302,
|
|
21
|
+
_303_SeeOther = 303,
|
|
22
|
+
_304_NotModified = 304,
|
|
23
|
+
_305_UseProxy = 305,
|
|
24
|
+
_307_TemporaryRedirect = 307,
|
|
25
|
+
_308_PermanentRedirect = 308,
|
|
26
|
+
_400_BadRequest = 400,
|
|
27
|
+
_401_Unauthorized = 401,
|
|
28
|
+
_402_PaymentRequired = 402,
|
|
29
|
+
_403_Forbidden = 403,
|
|
30
|
+
_404_NotFound = 404,
|
|
31
|
+
_405_MethodNotAllowed = 405,
|
|
32
|
+
_406_NotAcceptable = 406,
|
|
33
|
+
_407_ProxyAuthenticationRequired = 407,
|
|
34
|
+
_408_RequestTimeout = 408,
|
|
35
|
+
_409_Conflict = 409,
|
|
36
|
+
_410_Gone = 410,
|
|
37
|
+
_411_LengthRequired = 411,
|
|
38
|
+
_412_PreconditionFailed = 412,
|
|
39
|
+
_413_PayloadTooLarge = 413,
|
|
40
|
+
_414_URITooLong = 414,
|
|
41
|
+
_415_UnsupportedMediaType = 415,
|
|
42
|
+
_416_RangeNotSatisfiable = 416,
|
|
43
|
+
_417_ExpectationFailed = 417,
|
|
44
|
+
_418_IMATeapot = 418,
|
|
45
|
+
_421_MisdirectedRequest = 421,
|
|
46
|
+
_422_UnprocessableEntity = 422,
|
|
47
|
+
_423_Locked = 423,
|
|
48
|
+
_424_FailedDependency = 424,
|
|
49
|
+
_425_TooEarly = 425,
|
|
50
|
+
_426_UpgradeRequired = 426,
|
|
51
|
+
_428_PreconditionRequired = 428,
|
|
52
|
+
_429_TooManyRequests = 429,
|
|
53
|
+
_431_RequestHeaderFieldsTooLarge = 431,
|
|
54
|
+
_451_UnavailableForLegalReasons = 451,
|
|
55
|
+
_500_InternalServerError = 500,
|
|
56
|
+
_501_NotImplemented = 501,
|
|
57
|
+
_502_BadGateway = 502,
|
|
58
|
+
_503_ServiceUnavailable = 503,
|
|
59
|
+
_504_GatewayTimeout = 504,
|
|
60
|
+
_505_HTTPVersionNotSupported = 505,
|
|
61
|
+
_506_VariantAlsoNegotiates = 506,
|
|
62
|
+
_507_InsufficientStorage = 507,
|
|
63
|
+
_508_LoopDetected = 508,
|
|
64
|
+
_510_NotExtended = 510,
|
|
65
|
+
_511_NetworkAuthenticationRequired = 511,
|
|
66
|
+
_419_PageExpired = 419,
|
|
67
|
+
_420_EnhanceYourCalm = 420,
|
|
68
|
+
_450_BlockedbyWindowsParentalControls = 450,
|
|
69
|
+
_498_InvalidToken = 498,
|
|
70
|
+
_499_TokenRequired = 499,
|
|
71
|
+
_509_BandwidthLimitExceeded = 509,
|
|
72
|
+
_526_InvalidSSLCertificate = 526,
|
|
73
|
+
_529_Siteisoverloaded = 529,
|
|
74
|
+
_530_Siteisfrozen = 530,
|
|
75
|
+
_598_NetworkReadTimeoutError = 598,
|
|
76
|
+
_599_NetworkConnectTimeoutError = 599
|
|
8
77
|
}
|
|
9
|
-
export type CTXError = {
|
|
10
|
-
error: Error;
|
|
11
|
-
};
|
|
12
|
-
export type CTXAddress = {
|
|
13
|
-
address: SocketAddress;
|
|
14
|
-
};
|
|
15
78
|
export declare function getHttpStatusText(code: number): string;
|
|
16
79
|
/**
|
|
17
80
|
* Creates a Response with the specified status code.
|
|
@@ -36,14 +99,18 @@ export declare const status: (status: number, content?: string | null, init?: Re
|
|
|
36
99
|
*/
|
|
37
100
|
export declare const redirect: (location: string, init?: ResponseInit) => Response;
|
|
38
101
|
/**
|
|
39
|
-
* Forwards the request to another
|
|
40
|
-
* Does not
|
|
102
|
+
* Forwards the request to another route internally.
|
|
103
|
+
* Does not send a redirect to the client but changes the path and method,
|
|
104
|
+
* adds X-Forwarded-[Method|Path] and X-Original-Path headers and calls
|
|
105
|
+
* `(this as Router).respond(newReq, ctx)`.
|
|
106
|
+
* NOTE: parse body only once at the first handler using `parseBody({once: true})`
|
|
107
|
+
* as the body will be consumed at the first parseBody call.
|
|
41
108
|
* @param {string} path - The new path to forward to
|
|
42
109
|
* @returns {Response} A Response object with the forwarded request's response
|
|
43
110
|
*/
|
|
44
111
|
export declare const forward: <XContext = {}>(path: string, options?: {
|
|
45
|
-
method
|
|
46
|
-
}) =>
|
|
112
|
+
method?: HttpMethod;
|
|
113
|
+
}) => BoundHandler<XContext>;
|
|
47
114
|
/**
|
|
48
115
|
* Creates a text/plain Response.
|
|
49
116
|
* Defaults to status 200 and text/plain content-type if not specified.
|
|
@@ -194,53 +261,6 @@ export declare const clearCookie: (name: string, options?: CookieOptions) => Coo
|
|
|
194
261
|
* // Returns: { session: "abc123", theme: "dark" }
|
|
195
262
|
*/
|
|
196
263
|
export declare const parseCookieFromRequest: <Expected extends Record<string, string>>(req: Request) => Expected | undefined;
|
|
197
|
-
/**
|
|
198
|
-
* Context object containing parsed cookies.
|
|
199
|
-
* @typedef {Object} CTXCookie
|
|
200
|
-
* @property {Record<string, string>} cookie - Parsed cookies from the request
|
|
201
|
-
*/
|
|
202
|
-
export type CTXCookie = {
|
|
203
|
-
cookie: Record<string, string>;
|
|
204
|
-
};
|
|
205
|
-
/**
|
|
206
|
-
* Creates middleware that parses cookies from the request and adds them to the context.
|
|
207
|
-
* @returns {Function} A middleware function that adds parsed cookies to context.cookie
|
|
208
|
-
* @example
|
|
209
|
-
* const cookieParser = parseCookie();
|
|
210
|
-
* // Use in respondWith: respondWith({}, cookieParser(), ...otherHandlers)
|
|
211
|
-
*/
|
|
212
|
-
export declare const parseCookie: <Context extends CTXCookie>() => Handler<Context>;
|
|
213
|
-
/**
|
|
214
|
-
* Context object containing parsed request body.
|
|
215
|
-
* @typedef {Object} CTXBody
|
|
216
|
-
* @property {Record<string, unknown>} body - Parsed request body data
|
|
217
|
-
*/
|
|
218
|
-
export type CTXBody = {
|
|
219
|
-
body: Record<string, unknown>;
|
|
220
|
-
};
|
|
221
|
-
/**
|
|
222
|
-
* Supported media types for request body parsing.
|
|
223
|
-
* @typedef {"application/x-www-form-urlencoded"|"application/json"|"text/plain"} SupportedBodyMediaTypes
|
|
224
|
-
*/
|
|
225
|
-
export type SupportedBodyMediaTypes = "application/x-www-form-urlencoded" | "application/json" | "text/plain";
|
|
226
|
-
/**
|
|
227
|
-
* Creates middleware that parses the request body based on Content-Type.
|
|
228
|
-
* Supports url-encoded forms, JSON, and plain text.
|
|
229
|
-
* @param {Object} [options] - Configuration options for body parsing
|
|
230
|
-
* @param {SupportedBodyMediaTypes|SupportedBodyMediaTypes[]} [options.accept] - Media types to accept (defaults to all supported)
|
|
231
|
-
* @param {number} [options.maxSize] - Maximum body size in bytes (defaults to 1MB)
|
|
232
|
-
* @returns {Function} A middleware function that adds parsed body to context.body
|
|
233
|
-
* @throws {Response} Returns a 415 response if content-type is not accepted
|
|
234
|
-
* @throws {Response} Returns a 413 response if body exceeds maxSize
|
|
235
|
-
* @throws {Response} Returns a 400 response if body is malformed
|
|
236
|
-
* @example
|
|
237
|
-
* const bodyParser = parseBody({ maxSize: 5000 });
|
|
238
|
-
* // Use in respondWith: respondWith({}, bodyParser(), ...otherHandlers)
|
|
239
|
-
*/
|
|
240
|
-
export declare const parseBody: <Context extends CTXBody>(options?: {
|
|
241
|
-
accept?: SupportedBodyMediaTypes | SupportedBodyMediaTypes[];
|
|
242
|
-
maxSize?: number;
|
|
243
|
-
}) => Handler<Context>;
|
|
244
264
|
/**
|
|
245
265
|
* Request handler function type.
|
|
246
266
|
* @callback RequestHandler
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAExD,cAAc,iBAAiB,CAAC;AAEhC,oBAAY,MAAM;IAChB,aAAa,MAAM;IACnB,uBAAuB,MAAM;IAC7B,eAAe,MAAM;IACrB,eAAe,MAAM;IACrB,OAAO,MAAM;IACb,YAAY,MAAM;IAClB,aAAa,MAAM;IACnB,gCAAgC,MAAM;IACtC,cAAc,MAAM;IACpB,iBAAiB,MAAM;IACvB,mBAAmB,MAAM;IACzB,gBAAgB,MAAM;IACtB,oBAAoB,MAAM;IAC1B,WAAW,MAAM;IACjB,oBAAoB,MAAM;IAC1B,qBAAqB,MAAM;IAC3B,UAAU,MAAM;IAChB,aAAa,MAAM;IACnB,gBAAgB,MAAM;IACtB,aAAa,MAAM;IACnB,sBAAsB,MAAM;IAC5B,sBAAsB,MAAM;IAC5B,eAAe,MAAM;IACrB,iBAAiB,MAAM;IACvB,oBAAoB,MAAM;IAC1B,cAAc,MAAM;IACpB,aAAa,MAAM;IACnB,qBAAqB,MAAM;IAC3B,kBAAkB,MAAM;IACxB,gCAAgC,MAAM;IACtC,mBAAmB,MAAM;IACzB,aAAa,MAAM;IACnB,SAAS,MAAM;IACf,mBAAmB,MAAM;IACzB,uBAAuB,MAAM;IAC7B,oBAAoB,MAAM;IAC1B,eAAe,MAAM;IACrB,yBAAyB,MAAM;IAC/B,wBAAwB,MAAM;IAC9B,sBAAsB,MAAM;IAC5B,cAAc,MAAM;IACpB,uBAAuB,MAAM;IAC7B,wBAAwB,MAAM;IAC9B,WAAW,MAAM;IACjB,qBAAqB,MAAM;IAC3B,aAAa,MAAM;IACnB,oBAAoB,MAAM;IAC1B,yBAAyB,MAAM;IAC/B,oBAAoB,MAAM;IAC1B,gCAAgC,MAAM;IACtC,+BAA+B,MAAM;IACrC,wBAAwB,MAAM;IAC9B,mBAAmB,MAAM;IACzB,eAAe,MAAM;IACrB,uBAAuB,MAAM;IAC7B,mBAAmB,MAAM;IACzB,4BAA4B,MAAM;IAClC,0BAA0B,MAAM;IAChC,wBAAwB,MAAM;IAC9B,iBAAiB,MAAM;IACvB,gBAAgB,MAAM;IACtB,kCAAkC,MAAM;IACxC,gBAAgB,MAAM;IACtB,oBAAoB,MAAM;IAC1B,qCAAqC,MAAM;IAC3C,iBAAiB,MAAM;IACvB,kBAAkB,MAAM;IACxB,2BAA2B,MAAM;IACjC,0BAA0B,MAAM;IAChC,qBAAqB,MAAM;IAC3B,iBAAiB,MAAM;IACvB,4BAA4B,MAAM;IAClC,+BAA+B,MAAM;CACtC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA2KtD;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,MAAM,GACjB,QAAQ,MAAM,EACd,UAAU,MAAM,GAAG,IAAI,EACvB,OAAO,YAAY,KAClB,QAYF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,EAAE,OAAO,YAAY,KAAG,QAWhE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ,GAAG,EAAE,EACnC,MAAM,MAAM,EACZ,UAAU;IACR,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,KACA,YAAY,CAAC,QAAQ,CAgBvB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,OAAO,YAAY,KAAG,QAa3D,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,OAAO,YAAY,KAAG,QAa3D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,GAAG,EAAE,OAAO,YAAY,KAAG,QAarD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,IAAI,EAAE,OAAO,YAAY,KAAG,QActD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,IAAI,GAAG,WAAW,GAAG,cAAc,EAC1C,OAAO,YAAY,KAClB,QAmBF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,GACnB,WAAW,QAAQ,EACnB,OAAO,YAAY,KAClB,QAQF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,GAAG,GAAI,MAAM,eAAe,EAAE,OAAO,YAAY,KAAG,QAahE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,QAAQ,EAAE,OAAO,YAAY,KAAG,QAiC3D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CACtC;AAED;;;GAGG;AACH,KAAK,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpC;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,GACpB,MAAM,MAAM,EACZ,OAAO,MAAM,EACb,UAAU,aAAa,KACtB,WAcF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GACtB,MAAM,MAAM,EACZ,UAAU,aAAa,KACtB,WAgBF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,GAAI,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5E,KAAK,OAAO,KACX,QAAQ,GAAG,SAqBb,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,GAAG,GAAG;IAC3C,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;CAC1E;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB,CAAC,OAAO,GAAG,GAAG;IAChD,CACE,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,OAAO,GACX,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;CAC/C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,GAAG,GAAG,EACb,QAAQ,SAAS,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,CACrD,cAAc,CAAC,OAAO,CAAC,CACxB,EAED,SAAS,OAAO,EAChB,GAAG,UAAU,CAAC,GAAG,QAAQ,CAAC,KACzB;IAAE,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAUrC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,GAAG,GAAG,EACb,OAAO,SAAS,mBAAmB,CAAC,OAAO,CAAC,GAAG,mBAAmB,CAAC,OAAO,CAAC,EAC3E,QAAQ,SAAS,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,CACrD,cAAc,CAAC,OAAO,CAAC,CACxB,EAED,SAAS,OAAO,EAChB,SAAS,OAAO,EAChB,GAAG,UAAU,CAAC,GAAG,QAAQ,CAAC,KACzB;IAAE,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAoBrC,CAAC"}
|
package/dist/cjs/helpers.js
CHANGED
|
@@ -23,9 +23,85 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
23
23
|
});
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.respondWithCatcher = exports.respondWith = exports.
|
|
26
|
+
exports.respondWithCatcher = exports.respondWith = exports.parseCookieFromRequest = exports.clearCookie = exports.setCookie = exports.send = exports.usp = exports.formData = exports.octetStream = exports.blob = exports.json = exports.html = exports.text = exports.forward = exports.redirect = exports.status = exports.Status = void 0;
|
|
27
27
|
exports.getHttpStatusText = getHttpStatusText;
|
|
28
28
|
__exportStar(require("./upload-stream"), exports);
|
|
29
|
+
var Status;
|
|
30
|
+
(function (Status) {
|
|
31
|
+
Status[Status["_100_Continue"] = 100] = "_100_Continue";
|
|
32
|
+
Status[Status["_101_SwitchingProtocols"] = 101] = "_101_SwitchingProtocols";
|
|
33
|
+
Status[Status["_102_Processing"] = 102] = "_102_Processing";
|
|
34
|
+
Status[Status["_103_EarlyHints"] = 103] = "_103_EarlyHints";
|
|
35
|
+
Status[Status["_200_OK"] = 200] = "_200_OK";
|
|
36
|
+
Status[Status["_201_Created"] = 201] = "_201_Created";
|
|
37
|
+
Status[Status["_202_Accepted"] = 202] = "_202_Accepted";
|
|
38
|
+
Status[Status["_203_NonAuthoritativeInformation"] = 203] = "_203_NonAuthoritativeInformation";
|
|
39
|
+
Status[Status["_204_NoContent"] = 204] = "_204_NoContent";
|
|
40
|
+
Status[Status["_205_ResetContent"] = 205] = "_205_ResetContent";
|
|
41
|
+
Status[Status["_206_PartialContent"] = 206] = "_206_PartialContent";
|
|
42
|
+
Status[Status["_207_MultiStatus"] = 207] = "_207_MultiStatus";
|
|
43
|
+
Status[Status["_208_AlreadyReported"] = 208] = "_208_AlreadyReported";
|
|
44
|
+
Status[Status["_226_IMUsed"] = 226] = "_226_IMUsed";
|
|
45
|
+
Status[Status["_300_MultipleChoices"] = 300] = "_300_MultipleChoices";
|
|
46
|
+
Status[Status["_301_MovedPermanently"] = 301] = "_301_MovedPermanently";
|
|
47
|
+
Status[Status["_302_Found"] = 302] = "_302_Found";
|
|
48
|
+
Status[Status["_303_SeeOther"] = 303] = "_303_SeeOther";
|
|
49
|
+
Status[Status["_304_NotModified"] = 304] = "_304_NotModified";
|
|
50
|
+
Status[Status["_305_UseProxy"] = 305] = "_305_UseProxy";
|
|
51
|
+
Status[Status["_307_TemporaryRedirect"] = 307] = "_307_TemporaryRedirect";
|
|
52
|
+
Status[Status["_308_PermanentRedirect"] = 308] = "_308_PermanentRedirect";
|
|
53
|
+
Status[Status["_400_BadRequest"] = 400] = "_400_BadRequest";
|
|
54
|
+
Status[Status["_401_Unauthorized"] = 401] = "_401_Unauthorized";
|
|
55
|
+
Status[Status["_402_PaymentRequired"] = 402] = "_402_PaymentRequired";
|
|
56
|
+
Status[Status["_403_Forbidden"] = 403] = "_403_Forbidden";
|
|
57
|
+
Status[Status["_404_NotFound"] = 404] = "_404_NotFound";
|
|
58
|
+
Status[Status["_405_MethodNotAllowed"] = 405] = "_405_MethodNotAllowed";
|
|
59
|
+
Status[Status["_406_NotAcceptable"] = 406] = "_406_NotAcceptable";
|
|
60
|
+
Status[Status["_407_ProxyAuthenticationRequired"] = 407] = "_407_ProxyAuthenticationRequired";
|
|
61
|
+
Status[Status["_408_RequestTimeout"] = 408] = "_408_RequestTimeout";
|
|
62
|
+
Status[Status["_409_Conflict"] = 409] = "_409_Conflict";
|
|
63
|
+
Status[Status["_410_Gone"] = 410] = "_410_Gone";
|
|
64
|
+
Status[Status["_411_LengthRequired"] = 411] = "_411_LengthRequired";
|
|
65
|
+
Status[Status["_412_PreconditionFailed"] = 412] = "_412_PreconditionFailed";
|
|
66
|
+
Status[Status["_413_PayloadTooLarge"] = 413] = "_413_PayloadTooLarge";
|
|
67
|
+
Status[Status["_414_URITooLong"] = 414] = "_414_URITooLong";
|
|
68
|
+
Status[Status["_415_UnsupportedMediaType"] = 415] = "_415_UnsupportedMediaType";
|
|
69
|
+
Status[Status["_416_RangeNotSatisfiable"] = 416] = "_416_RangeNotSatisfiable";
|
|
70
|
+
Status[Status["_417_ExpectationFailed"] = 417] = "_417_ExpectationFailed";
|
|
71
|
+
Status[Status["_418_IMATeapot"] = 418] = "_418_IMATeapot";
|
|
72
|
+
Status[Status["_421_MisdirectedRequest"] = 421] = "_421_MisdirectedRequest";
|
|
73
|
+
Status[Status["_422_UnprocessableEntity"] = 422] = "_422_UnprocessableEntity";
|
|
74
|
+
Status[Status["_423_Locked"] = 423] = "_423_Locked";
|
|
75
|
+
Status[Status["_424_FailedDependency"] = 424] = "_424_FailedDependency";
|
|
76
|
+
Status[Status["_425_TooEarly"] = 425] = "_425_TooEarly";
|
|
77
|
+
Status[Status["_426_UpgradeRequired"] = 426] = "_426_UpgradeRequired";
|
|
78
|
+
Status[Status["_428_PreconditionRequired"] = 428] = "_428_PreconditionRequired";
|
|
79
|
+
Status[Status["_429_TooManyRequests"] = 429] = "_429_TooManyRequests";
|
|
80
|
+
Status[Status["_431_RequestHeaderFieldsTooLarge"] = 431] = "_431_RequestHeaderFieldsTooLarge";
|
|
81
|
+
Status[Status["_451_UnavailableForLegalReasons"] = 451] = "_451_UnavailableForLegalReasons";
|
|
82
|
+
Status[Status["_500_InternalServerError"] = 500] = "_500_InternalServerError";
|
|
83
|
+
Status[Status["_501_NotImplemented"] = 501] = "_501_NotImplemented";
|
|
84
|
+
Status[Status["_502_BadGateway"] = 502] = "_502_BadGateway";
|
|
85
|
+
Status[Status["_503_ServiceUnavailable"] = 503] = "_503_ServiceUnavailable";
|
|
86
|
+
Status[Status["_504_GatewayTimeout"] = 504] = "_504_GatewayTimeout";
|
|
87
|
+
Status[Status["_505_HTTPVersionNotSupported"] = 505] = "_505_HTTPVersionNotSupported";
|
|
88
|
+
Status[Status["_506_VariantAlsoNegotiates"] = 506] = "_506_VariantAlsoNegotiates";
|
|
89
|
+
Status[Status["_507_InsufficientStorage"] = 507] = "_507_InsufficientStorage";
|
|
90
|
+
Status[Status["_508_LoopDetected"] = 508] = "_508_LoopDetected";
|
|
91
|
+
Status[Status["_510_NotExtended"] = 510] = "_510_NotExtended";
|
|
92
|
+
Status[Status["_511_NetworkAuthenticationRequired"] = 511] = "_511_NetworkAuthenticationRequired";
|
|
93
|
+
Status[Status["_419_PageExpired"] = 419] = "_419_PageExpired";
|
|
94
|
+
Status[Status["_420_EnhanceYourCalm"] = 420] = "_420_EnhanceYourCalm";
|
|
95
|
+
Status[Status["_450_BlockedbyWindowsParentalControls"] = 450] = "_450_BlockedbyWindowsParentalControls";
|
|
96
|
+
Status[Status["_498_InvalidToken"] = 498] = "_498_InvalidToken";
|
|
97
|
+
Status[Status["_499_TokenRequired"] = 499] = "_499_TokenRequired";
|
|
98
|
+
Status[Status["_509_BandwidthLimitExceeded"] = 509] = "_509_BandwidthLimitExceeded";
|
|
99
|
+
Status[Status["_526_InvalidSSLCertificate"] = 526] = "_526_InvalidSSLCertificate";
|
|
100
|
+
Status[Status["_529_Siteisoverloaded"] = 529] = "_529_Siteisoverloaded";
|
|
101
|
+
Status[Status["_530_Siteisfrozen"] = 530] = "_530_Siteisfrozen";
|
|
102
|
+
Status[Status["_598_NetworkReadTimeoutError"] = 598] = "_598_NetworkReadTimeoutError";
|
|
103
|
+
Status[Status["_599_NetworkConnectTimeoutError"] = 599] = "_599_NetworkConnectTimeoutError";
|
|
104
|
+
})(Status || (exports.Status = Status = {}));
|
|
29
105
|
function getHttpStatusText(code) {
|
|
30
106
|
switch (code) {
|
|
31
107
|
// 1xx Informational
|
|
@@ -239,8 +315,12 @@ const redirect = (location, init) => {
|
|
|
239
315
|
};
|
|
240
316
|
exports.redirect = redirect;
|
|
241
317
|
/**
|
|
242
|
-
* Forwards the request to another
|
|
243
|
-
* Does not
|
|
318
|
+
* Forwards the request to another route internally.
|
|
319
|
+
* Does not send a redirect to the client but changes the path and method,
|
|
320
|
+
* adds X-Forwarded-[Method|Path] and X-Original-Path headers and calls
|
|
321
|
+
* `(this as Router).respond(newReq, ctx)`.
|
|
322
|
+
* NOTE: parse body only once at the first handler using `parseBody({once: true})`
|
|
323
|
+
* as the body will be consumed at the first parseBody call.
|
|
244
324
|
* @param {string} path - The new path to forward to
|
|
245
325
|
* @returns {Response} A Response object with the forwarded request's response
|
|
246
326
|
*/
|
|
@@ -248,13 +328,19 @@ const forward = (path, options) => {
|
|
|
248
328
|
return function (req, ctx) {
|
|
249
329
|
return __awaiter(this, void 0, void 0, function* () {
|
|
250
330
|
var _a;
|
|
331
|
+
const method = (_a = options === null || options === void 0 ? void 0 : options.method) !== null && _a !== void 0 ? _a : req.method;
|
|
332
|
+
const headers = new Headers(req.headers);
|
|
333
|
+
const body = req.body ? yield req.clone().arrayBuffer() : undefined;
|
|
251
334
|
const url = new URL(req.url);
|
|
335
|
+
const originalPathname = url.pathname;
|
|
252
336
|
url.pathname = path;
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
337
|
+
if (method != req.method)
|
|
338
|
+
headers.set("X-Forwarded-Method", req.method);
|
|
339
|
+
headers.set("X-Forwarded-Path", originalPathname);
|
|
340
|
+
if (!req.headers.has("X-Original-Path")) {
|
|
341
|
+
headers.set("X-Original-Path", originalPathname);
|
|
342
|
+
}
|
|
343
|
+
const newReq = new Request(url.toString(), { method, headers, body });
|
|
258
344
|
return this.respond(newReq, ctx);
|
|
259
345
|
});
|
|
260
346
|
};
|
|
@@ -559,89 +645,6 @@ const parseCookieFromRequest = (req) => {
|
|
|
559
645
|
return undefined;
|
|
560
646
|
};
|
|
561
647
|
exports.parseCookieFromRequest = parseCookieFromRequest;
|
|
562
|
-
/**
|
|
563
|
-
* Creates middleware that parses cookies from the request and adds them to the context.
|
|
564
|
-
* @returns {Function} A middleware function that adds parsed cookies to context.cookie
|
|
565
|
-
* @example
|
|
566
|
-
* const cookieParser = parseCookie();
|
|
567
|
-
* // Use in respondWith: respondWith({}, cookieParser(), ...otherHandlers)
|
|
568
|
-
*/
|
|
569
|
-
const parseCookie = () => {
|
|
570
|
-
return (req, ctx) => {
|
|
571
|
-
var _a;
|
|
572
|
-
const cookie = (_a = (0, exports.parseCookieFromRequest)(req)) !== null && _a !== void 0 ? _a : {};
|
|
573
|
-
ctx.cookie = cookie;
|
|
574
|
-
};
|
|
575
|
-
};
|
|
576
|
-
exports.parseCookie = parseCookie;
|
|
577
|
-
/**
|
|
578
|
-
* Creates middleware that parses the request body based on Content-Type.
|
|
579
|
-
* Supports url-encoded forms, JSON, and plain text.
|
|
580
|
-
* @param {Object} [options] - Configuration options for body parsing
|
|
581
|
-
* @param {SupportedBodyMediaTypes|SupportedBodyMediaTypes[]} [options.accept] - Media types to accept (defaults to all supported)
|
|
582
|
-
* @param {number} [options.maxSize] - Maximum body size in bytes (defaults to 1MB)
|
|
583
|
-
* @returns {Function} A middleware function that adds parsed body to context.body
|
|
584
|
-
* @throws {Response} Returns a 415 response if content-type is not accepted
|
|
585
|
-
* @throws {Response} Returns a 413 response if body exceeds maxSize
|
|
586
|
-
* @throws {Response} Returns a 400 response if body is malformed
|
|
587
|
-
* @example
|
|
588
|
-
* const bodyParser = parseBody({ maxSize: 5000 });
|
|
589
|
-
* // Use in respondWith: respondWith({}, bodyParser(), ...otherHandlers)
|
|
590
|
-
*/
|
|
591
|
-
const parseBody = (options) => {
|
|
592
|
-
var _a;
|
|
593
|
-
const accept = (options === null || options === void 0 ? void 0 : options.accept)
|
|
594
|
-
? Array.isArray(options.accept)
|
|
595
|
-
? options.accept
|
|
596
|
-
: [options.accept]
|
|
597
|
-
: [
|
|
598
|
-
"application/x-www-form-urlencoded",
|
|
599
|
-
"application/json",
|
|
600
|
-
"text/plain",
|
|
601
|
-
];
|
|
602
|
-
const maxSize = (_a = options === null || options === void 0 ? void 0 : options.maxSize) !== null && _a !== void 0 ? _a : 1024 * 1024; // Default 1MB
|
|
603
|
-
return (req, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
604
|
-
var _a, _b, _c, _d;
|
|
605
|
-
const contentType = (_a = req.headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.split(";", 2)[0];
|
|
606
|
-
if (!(contentType && accept.includes(contentType))) {
|
|
607
|
-
yield ((_b = req.body) === null || _b === void 0 ? void 0 : _b.cancel().catch(() => { }));
|
|
608
|
-
return (0, exports.status)(415);
|
|
609
|
-
}
|
|
610
|
-
try {
|
|
611
|
-
const contentLengthHeader = req.headers.get("content-length");
|
|
612
|
-
if (!contentLengthHeader || parseInt(contentLengthHeader) > maxSize) {
|
|
613
|
-
yield ((_c = req.body) === null || _c === void 0 ? void 0 : _c.cancel().catch(() => { }));
|
|
614
|
-
return (0, exports.status)(413);
|
|
615
|
-
}
|
|
616
|
-
switch (contentType) {
|
|
617
|
-
case "application/x-www-form-urlencoded": {
|
|
618
|
-
const body = yield req.formData();
|
|
619
|
-
ctx.body = Object.fromEntries(body.entries());
|
|
620
|
-
break;
|
|
621
|
-
}
|
|
622
|
-
case "application/json": {
|
|
623
|
-
const body = yield req.json();
|
|
624
|
-
ctx.body =
|
|
625
|
-
typeof body === "object" ? body : {};
|
|
626
|
-
break;
|
|
627
|
-
}
|
|
628
|
-
case "text/plain": {
|
|
629
|
-
const text = yield req.text();
|
|
630
|
-
ctx.body = { text };
|
|
631
|
-
break;
|
|
632
|
-
}
|
|
633
|
-
default:
|
|
634
|
-
ctx.body = {};
|
|
635
|
-
break;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
catch (_e) {
|
|
639
|
-
yield ((_d = req.body) === null || _d === void 0 ? void 0 : _d.cancel().catch(() => { }));
|
|
640
|
-
return (0, exports.status)(400, "Malformed Payload");
|
|
641
|
-
}
|
|
642
|
-
});
|
|
643
|
-
};
|
|
644
|
-
exports.parseBody = parseBody;
|
|
645
648
|
/**
|
|
646
649
|
* Creates a request handler that processes requests through a series of middleware/handlers.
|
|
647
650
|
* Handlers are executed in order. If a handler returns a Response, that response is returned immediately.
|