fulmine.js 5.19.7 → 5.19.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fulmine.js",
3
- "version": "5.19.7",
3
+ "version": "5.19.8",
4
4
  "description": "Drop-in Express 5 replacement on uWebSockets.js. Your existing middleware keeps working.",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -18,7 +18,7 @@ limitations under the License.
18
18
  */
19
19
 
20
20
  const acorn = require("acorn");
21
- const { stringify, contentTypeSet, withUtf8Charset, contentTypeFor } = require("./utils.js");
21
+ const { stringify, contentTypeSet, withUtf8Charset, contentTypeFor, headerIsWritable } = require("./utils.js");
22
22
  // H3App, DeclarativeResponse and _cfg exist at runtime but are missing from the .d.ts the
23
23
  // package ships, so the module is read through a loose alias
24
24
  const uWS = require("uWebSockets.js");
@@ -261,6 +261,11 @@ function readStatusAndHeaders(callExprs, headers) {
261
261
  }
262
262
  value = resolved;
263
263
  }
264
+ // a name or a value setHeader refuses is an error page in express, not a header:
265
+ // left to the ordinary path, which throws it
266
+ if (!headerIsWritable(String(header), value)) {
267
+ return null;
268
+ }
264
269
  const index = headers.findIndex((entry) => String(entry[0]).toLowerCase() === name);
265
270
  if (index === -1) {
266
271
  headers.push([header, value]);
@@ -280,6 +285,9 @@ function readStatusAndHeaders(callExprs, headers) {
280
285
  if (call.arguments[0].type !== "Literal" || call.arguments[1].type !== "Literal") {
281
286
  return null;
282
287
  }
288
+ if (!headerIsWritable(String(call.arguments[0].value), String(call.arguments[1].value))) {
289
+ return null;
290
+ }
283
291
  headers.push([call.arguments[0].value, String(call.arguments[1].value)]);
284
292
  } else if (call.obj.propertyName === "sendStatus") {
285
293
  if (call.arguments[0].type !== "Literal") {
package/src/node-shim.js CHANGED
@@ -417,7 +417,10 @@ function serveNodeRequest(router, nodeReq, nodeRes, next) {
417
417
  router._armAbort(shimRes, response);
418
418
 
419
419
  return router._routeRequest(request, response).then((matched) => {
420
- if (matched || response.headersSent || response.aborted) {
420
+ // a 404 after the head is out is left as it is, an error after it is not: it goes on to
421
+ // the final handler, which closes the connection as express's does. Same rule as the
422
+ // native path, see nativeDone in router-utils.js
423
+ if (matched || response.aborted || (response.headersSent && !request._error)) {
421
424
  return;
422
425
  }
423
426
  if (next) {
package/src/route.js CHANGED
@@ -120,20 +120,19 @@ class Route {
120
120
  if (handle.length !== 4) {
121
121
  return next(err);
122
122
  }
123
- try {
124
- handle(err, req, res, next);
125
- } catch (thrown) {
126
- next(thrown);
127
- }
128
- } else {
129
- if (handle.length === 4) {
130
- return next();
131
- }
132
- try {
133
- handle(req, res, next);
134
- } catch (thrown) {
135
- next(thrown);
123
+ } else if (handle.length === 4) {
124
+ return next();
125
+ }
126
+ try {
127
+ const out = err ? handle(err, req, res, next) : handle(req, res, next);
128
+ // a rejected promise goes to next() as the error it carries, as express's Layer
129
+ // does it. A bare rejection carries none and gets the one express invents. Thenable
130
+ // too, which express deprecates but still waits for
131
+ if (out && typeof out.then === "function") {
132
+ out.then(null, (thrown) => next(thrown || new Error("Rejected promise")));
136
133
  }
134
+ } catch (thrown) {
135
+ next(thrown);
137
136
  }
138
137
  sync = 0;
139
138
  };