@momsfriendlydevco/cowboy 1.0.9 → 1.0.11
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 +1 -0
- package/lib/cowboy.js +1 -11
- package/lib/request.js +75 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Features:
|
|
|
9
9
|
* Express-like `req` + `res` object for routes
|
|
10
10
|
* Built in middleware + request validation via [Joi](https://joi.dev)
|
|
11
11
|
* Built-in debug support for testkits + Wrangler
|
|
12
|
+
* Built-in JSON / Multipart (or FormData) / Plain text decoding and population of `req.body`
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
Examples
|
package/lib/cowboy.js
CHANGED
|
@@ -123,17 +123,7 @@ export class Cowboy {
|
|
|
123
123
|
pathTidy: this.settings.pathTidy,
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
if (cfReq.body) {
|
|
128
|
-
try {
|
|
129
|
-
req.body = await cfReq.json();
|
|
130
|
-
} catch (e) {
|
|
131
|
-
if (debug.enabled) {
|
|
132
|
-
debug('Failed to decode request body as JSON: [[[' + cfReq.body.toString() + ']]]');
|
|
133
|
-
}
|
|
134
|
-
throw new Error('Invalid JSON body');
|
|
135
|
-
}
|
|
136
|
-
}
|
|
126
|
+
await req.parseBody();
|
|
137
127
|
|
|
138
128
|
let res = new CowboyResponse();
|
|
139
129
|
debug('Incoming request:', req.toString());
|
package/lib/request.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import debug from '#lib/debug';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Tiny wrapper around Wrangler to wrap its default Request object in an Express-like structure
|
|
3
5
|
* @extends CloudflareRequest
|
|
@@ -16,6 +18,21 @@ export default class CowboyRequest {
|
|
|
16
18
|
hostname;
|
|
17
19
|
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Extracted URL query parameters
|
|
23
|
+
* @type {Object}
|
|
24
|
+
*/
|
|
25
|
+
query = {};
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Raw body payload provided by cfReq
|
|
30
|
+
* This gets translated into a usable object after a call to `parseBody()`
|
|
31
|
+
* @type {*}
|
|
32
|
+
*/
|
|
33
|
+
body = null;
|
|
34
|
+
|
|
35
|
+
|
|
19
36
|
constructor(cfReq, props) {
|
|
20
37
|
// Copy all cfReq keys locally as a shallow copy
|
|
21
38
|
Object.assign(
|
|
@@ -35,6 +52,64 @@ export default class CowboyRequest {
|
|
|
35
52
|
let url = new URL(cfReq.url);
|
|
36
53
|
this.path = this.pathTidy(url.pathname);
|
|
37
54
|
this.hostname = url.hostname;
|
|
55
|
+
this.query = Object.fromEntries(url.searchParams);
|
|
56
|
+
|
|
57
|
+
// Slurp the headers
|
|
58
|
+
this.headers = Object.fromEntries(cfReq.headers.entries());
|
|
59
|
+
|
|
60
|
+
// Hold the body element - this wont be decoded until parseBody() is called
|
|
61
|
+
this.body = {
|
|
62
|
+
json: cfReq.json.bind(cfReq),
|
|
63
|
+
formData: cfReq.formData.bind(cfReq),
|
|
64
|
+
text: cfReq.text.bind(cfReq),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Parse the body of an incoming request
|
|
71
|
+
*
|
|
72
|
+
* @param {String} [forceType] Whether to force a specific mime-type instead of using the header supplied format
|
|
73
|
+
* @returns {Promise} A promise which will resolve when the body has been parsed
|
|
74
|
+
*/
|
|
75
|
+
async parseBody(forceType) {
|
|
76
|
+
let type = (forceType || this.headers['content-type'])
|
|
77
|
+
.replace(/^([a-z\-\/]+).*$/, '$1'); // Scrap everything after the mime
|
|
78
|
+
|
|
79
|
+
switch (type) {
|
|
80
|
+
case 'json':
|
|
81
|
+
case 'application/json':
|
|
82
|
+
try {
|
|
83
|
+
this.body = await this.body.json();
|
|
84
|
+
break;
|
|
85
|
+
} catch (e) {
|
|
86
|
+
if (debug.enabled) debug('Failed to decode request body as JSON:', e.toString());
|
|
87
|
+
throw new Error('Invalid JSON body');
|
|
88
|
+
}
|
|
89
|
+
case 'formData':
|
|
90
|
+
case 'multipart/form-data': // Decode as multi-part
|
|
91
|
+
case 'application/x-www-form-urlencoded': // Decode as multi-part
|
|
92
|
+
try {
|
|
93
|
+
let formData = await this.body.formData();
|
|
94
|
+
this.body = Object.fromEntries(formData.entries());
|
|
95
|
+
break;
|
|
96
|
+
} catch (e) {
|
|
97
|
+
if (debug.enabled) debug('Failed to decode multi-part body:', e.toString());
|
|
98
|
+
throw new Error('Invalid multi-part encoded body');
|
|
99
|
+
}
|
|
100
|
+
case 'text':
|
|
101
|
+
case 'text/plain': // Decode as plain text
|
|
102
|
+
try {
|
|
103
|
+
this.body = await this.body.text();
|
|
104
|
+
break;
|
|
105
|
+
} catch (e) {
|
|
106
|
+
if (debug.enabled) debug('Failed to decode plain-text body:', e.toString());
|
|
107
|
+
throw new Error('Invalid text body');
|
|
108
|
+
}
|
|
109
|
+
default:
|
|
110
|
+
debug('EMPTY BODY PAYLOAD');
|
|
111
|
+
this.body = {};
|
|
112
|
+
}
|
|
38
113
|
}
|
|
39
114
|
|
|
40
115
|
|