@momsfriendlydevco/cowboy 1.0.4 → 1.0.5
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/lib/cowboy.js +59 -14
- package/lib/request.js +9 -0
- package/lib/response.js +1 -1
- package/lib/testkit.js +3 -0
- package/package.json +1 -1
package/lib/cowboy.js
CHANGED
|
@@ -27,6 +27,7 @@ export class Cowboy {
|
|
|
27
27
|
* @property {Function} pathTidy Additional tidyup for server request paths, useful if the API does not live at the server root. Defaults to removing a "/api/:worker/" prefix
|
|
28
28
|
*/
|
|
29
29
|
settings = {
|
|
30
|
+
patchAxios: true,
|
|
30
31
|
pathTidy(path) {
|
|
31
32
|
return path.replace(/^\/api\/\w+/, '/');
|
|
32
33
|
},
|
|
@@ -47,6 +48,13 @@ export class Cowboy {
|
|
|
47
48
|
routes = [];
|
|
48
49
|
|
|
49
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Has completed one init() cycle
|
|
53
|
+
* @type {Boolean}
|
|
54
|
+
*/
|
|
55
|
+
doneInit = false;
|
|
56
|
+
|
|
57
|
+
|
|
50
58
|
/**
|
|
51
59
|
* Queue up a middleware path
|
|
52
60
|
* All given middleware is called in sequence, if middleware
|
|
@@ -70,6 +78,7 @@ export class Cowboy {
|
|
|
70
78
|
/**
|
|
71
79
|
* Prepend middleware which will be used for all routes
|
|
72
80
|
* @param {CowboyMiddleware} middleware Middleware to use
|
|
81
|
+
* @returns {Cowboy} This chainable Cowboy router instance
|
|
73
82
|
*/
|
|
74
83
|
use(...middleware) {
|
|
75
84
|
this.earlyMiddleware.push(middleware);
|
|
@@ -101,27 +110,32 @@ export class Cowboy {
|
|
|
101
110
|
* @returns {Promise<CowboyResponse>} A promise which will eventually resolve when all middleware completes
|
|
102
111
|
*/
|
|
103
112
|
async fetch(cfReq, env) {
|
|
104
|
-
|
|
113
|
+
this.init();
|
|
114
|
+
|
|
115
|
+
if (env.COWBOY_DEBUG)
|
|
105
116
|
debug.enabled = true;
|
|
106
|
-
debug('Cowboy Worker debugging is enabled');
|
|
107
|
-
}
|
|
108
117
|
|
|
109
118
|
// Create basic [req]uest / [res]ponse objects
|
|
110
119
|
let req = new CowboyRequest(cfReq, {
|
|
111
120
|
router: this,
|
|
112
121
|
pathTidy: this.settings.pathTidy,
|
|
113
122
|
});
|
|
123
|
+
if (cfReq.body) req.body = await cfReq.json();
|
|
124
|
+
|
|
114
125
|
let res = new CowboyResponse();
|
|
126
|
+
debug('Incoming request:', req.toString());
|
|
115
127
|
|
|
116
128
|
// Exec all earlyMiddleware - every time
|
|
117
|
-
|
|
118
|
-
|
|
129
|
+
await this.execMiddleware({
|
|
130
|
+
req, res,
|
|
131
|
+
middleware: this.earlyMiddleware,
|
|
132
|
+
});
|
|
119
133
|
|
|
120
134
|
// Find matching route
|
|
121
135
|
let route = this.resolve(req);
|
|
122
136
|
if (!route) {
|
|
123
137
|
if (debug.enabled) {
|
|
124
|
-
debug(`No matching route for "${req.
|
|
138
|
+
debug(`No matching route for "${req.toString()}"`);
|
|
125
139
|
this.routes.forEach((r, i) =>
|
|
126
140
|
debug(
|
|
127
141
|
`Route #${i}`,
|
|
@@ -134,7 +148,10 @@ export class Cowboy {
|
|
|
134
148
|
}
|
|
135
149
|
|
|
136
150
|
// Exec route middleware
|
|
137
|
-
let response = await this.execMiddleware({
|
|
151
|
+
let response = await this.execMiddleware({
|
|
152
|
+
req, res,
|
|
153
|
+
middleware: route.middleware,
|
|
154
|
+
});
|
|
138
155
|
|
|
139
156
|
if (!response) throw new Error('Middleware chain ended without returning a response!');
|
|
140
157
|
if (!response.toCloudflareResponse) throw new Error('Eventual middleware chain output should have a .toCloudflareResponse() method');
|
|
@@ -143,12 +160,12 @@ export class Cowboy {
|
|
|
143
160
|
|
|
144
161
|
|
|
145
162
|
async execMiddleware({middleware, req, res}) {
|
|
146
|
-
let middlewareStack =
|
|
163
|
+
let middlewareStack = middleware
|
|
147
164
|
.map(m => {
|
|
148
165
|
let mFunc =
|
|
149
166
|
typeof m == 'function' ? m // Already a function
|
|
150
|
-
: typeof m == 'string' ? CowboyMiddleware[m]() // Lookup from middleware with defaults
|
|
151
|
-
: Array.isArray(m) ? CowboyMiddleware[m[0]](
|
|
167
|
+
: typeof m == 'string' ? CowboyMiddleware[m].apply(this) // Lookup from middleware with defaults
|
|
168
|
+
: Array.isArray(m) ? CowboyMiddleware[m[0]].apply(this, m.slice(1)) // Lookup from middleware with options
|
|
152
169
|
: (()=> { throw new Error(`Unknown middleware type "${typeof m}"`) })()
|
|
153
170
|
|
|
154
171
|
if (!mFunc) throw new Error('Cowboy Middleware must be a function, string or Record(name, options)');
|
|
@@ -156,7 +173,6 @@ export class Cowboy {
|
|
|
156
173
|
});
|
|
157
174
|
|
|
158
175
|
let response; // Response to eventually send
|
|
159
|
-
debug('Run middleware stack', middlewareStack);
|
|
160
176
|
while (middlewareStack.length > 0) {
|
|
161
177
|
let middleware = middlewareStack.shift();
|
|
162
178
|
try {
|
|
@@ -168,9 +184,19 @@ export class Cowboy {
|
|
|
168
184
|
response = res.end(response);
|
|
169
185
|
}
|
|
170
186
|
} catch (e) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
187
|
+
let errorText = typeof e == 'string' ? e : e.toString();
|
|
188
|
+
|
|
189
|
+
debug('Error thrown', errorText);
|
|
190
|
+
|
|
191
|
+
// Form: '404: Not found'
|
|
192
|
+
if (/^(\d{3}):/.test(errorText)) {
|
|
193
|
+
let errorBits = /^(?<status>\d{3}):?(?<text>.*)$/.exec(errorText).groups;
|
|
194
|
+
res.status(errorBits.status).send(errorBits.text);
|
|
195
|
+
} else { // Generic error - assume 400
|
|
196
|
+
res.status(400).send(e.toString());
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
response = res;
|
|
174
200
|
break;
|
|
175
201
|
}
|
|
176
202
|
}
|
|
@@ -185,6 +211,23 @@ export class Cowboy {
|
|
|
185
211
|
post(path, ...middleware) { return this.route('POST', path, ...middleware) }
|
|
186
212
|
put(path, ...middleware) { return this.route('PUT', path, ...middleware) }
|
|
187
213
|
options(path, ...middleware) { return this.route('OPTIONS', path, ...middleware) }
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Generial Init() sequence
|
|
218
|
+
* This will be run automatically on setup or the first fetch()
|
|
219
|
+
* @returns {Cowboy} This chainable Cowboy router instance
|
|
220
|
+
*/
|
|
221
|
+
init() {
|
|
222
|
+
debug('INIT!');
|
|
223
|
+
if (this.doneInit) return this; // Already completed init
|
|
224
|
+
|
|
225
|
+
if (this.settings.patchAxios) {
|
|
226
|
+
// TODO: Patch Axios somehow
|
|
227
|
+
// axios.defaults.adapter = axiosFetchAdapter;
|
|
228
|
+
}
|
|
229
|
+
return this;
|
|
230
|
+
}
|
|
188
231
|
}
|
|
189
232
|
|
|
190
233
|
|
|
@@ -200,5 +243,7 @@ export default function cowboy(options) {
|
|
|
200
243
|
fetch: cowboyInstance.fetch.bind(cowboyInstance),
|
|
201
244
|
});
|
|
202
245
|
|
|
246
|
+
cowboyInstance.init();
|
|
247
|
+
|
|
203
248
|
return cowboyInstance;
|
|
204
249
|
}
|
package/lib/request.js
CHANGED
|
@@ -36,4 +36,13 @@ export default class CowboyRequest {
|
|
|
36
36
|
this.path = this.pathTidy(url.pathname);
|
|
37
37
|
this.hostname = url.hostname;
|
|
38
38
|
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Utility function to simplify an incoming request
|
|
43
|
+
* @returns {String} Human readable string
|
|
44
|
+
*/
|
|
45
|
+
toString() {
|
|
46
|
+
return `${this.method} ${this.path}`;
|
|
47
|
+
}
|
|
39
48
|
}
|
package/lib/response.js
CHANGED
|
@@ -99,7 +99,7 @@ export default class CowboyResponse {
|
|
|
99
99
|
status: this.code,
|
|
100
100
|
headers: this.headers,
|
|
101
101
|
};
|
|
102
|
-
console.log('Build response', JSON.stringify(cfOptions));
|
|
102
|
+
console.log('Build response', JSON.stringify({...cfOptions, body: this.body}, null, '\t'));
|
|
103
103
|
return new this.CloudflareResponse(this.body, cfOptions);
|
|
104
104
|
}
|
|
105
105
|
}
|
package/lib/testkit.js
CHANGED
|
@@ -17,6 +17,7 @@ export let worker;
|
|
|
17
17
|
*
|
|
18
18
|
* @param {Object} [options] Additional options to mutate behaviour
|
|
19
19
|
* @param {Axios} [options.axios] Axios instance to mutate with the base URL, if specified
|
|
20
|
+
* @param {Boolean} [options.server=true] Initialize a local server - disable this if you're running your own
|
|
20
21
|
* @param {Function} [options.logOutput] Function to wrap STDOUT output. Called as `(line:String)`
|
|
21
22
|
* @param {Function} [options.logOutputErr] Function to wrap STDERR output. Called as `(line:String)`
|
|
22
23
|
* @param {String} [options.host='127.0.0.1'] Host to run Wrangler on
|
|
@@ -28,6 +29,7 @@ export let worker;
|
|
|
28
29
|
export function start(options) {
|
|
29
30
|
let settings = {
|
|
30
31
|
axios: null,
|
|
32
|
+
server: true,
|
|
31
33
|
logOutput: output => console.log('WRANGLER>', output),
|
|
32
34
|
logOutputErr: output => console.log('WRANGLER!', output),
|
|
33
35
|
host: '127.0.0.1',
|
|
@@ -51,6 +53,7 @@ export function start(options) {
|
|
|
51
53
|
// }}}
|
|
52
54
|
// Launch worker {{{
|
|
53
55
|
.then(()=> {
|
|
56
|
+
if (!settings.server) return;
|
|
54
57
|
debug('Running Wrangler against script', wranglerConfig.main);
|
|
55
58
|
|
|
56
59
|
let isRunning = false;
|