fulmine.js 5.19.6 → 5.19.7

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/utils.js +20 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fulmine.js",
3
- "version": "5.19.6",
3
+ "version": "5.19.7",
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": {
package/src/utils.js CHANGED
@@ -416,6 +416,10 @@ function patternToRegex(pattern, isPrefix = false, caseSensitive = true, strict
416
416
  }
417
417
  groupContent += pattern[i++];
418
418
  }
419
+ // a group nobody closed, which express refuses rather than reading to the end
420
+ if (braceDepth > 0) {
421
+ throw new Error(`Unexpected end at index ${len}, expected }: ${pattern}`);
422
+ }
419
423
  i++;
420
424
 
421
425
  // When a :parameter precedes this group, that parameter is the one that gives ground
@@ -512,12 +516,12 @@ function patternToRegex(pattern, isPrefix = false, caseSensitive = true, strict
512
516
 
513
517
  // these have no meaning in a path, and the route is refused rather than matching them
514
518
  // literally: a path that quietly stops matching is worse than one that fails at startup.
515
- // Escape them to use them as literals.
516
- if ("?+()[]!".includes(ch)) {
519
+ // Escape them to use them as literals. A } here closes a group nobody opened.
520
+ if ("?+()[]!}".includes(ch)) {
517
521
  throw new Error(`Unexpected ${ch} at index ${i}: ${pattern}`);
518
522
  }
519
523
 
520
- if (".^$|}".includes(ch)) {
524
+ if (".^$|".includes(ch)) {
521
525
  regexPattern += "\\" + ch;
522
526
  } else {
523
527
  regexPattern += ch;
@@ -556,9 +560,20 @@ function escapePathLiteral(literal) {
556
560
  return literal.replace(/[:*{}?+()[\]!.^$|\\]/g, "\\$&");
557
561
  }
558
562
 
563
+ // Everything path-to-regexp gives a meaning to: a parameter, a wildcard, a group, a character it
564
+ // reserves, and the backslash that makes one of them literal. A dot or a dash is not in here, so
565
+ // the ordinary path stays a string compare.
566
+ const PATH_SYNTAX = /[:*{}?+()[\]!\\]/;
567
+
559
568
  /**
560
569
  * Whether a path has anything in it that a string comparison cannot answer, which is a parameter,
561
- * a wildcard or an optional group. A regular expression is already compiled, so it needs nothing.
570
+ * a wildcard, an optional group, or a reserved character. A regular expression is already
571
+ * compiled, so it needs nothing.
572
+ *
573
+ * The escapes are what the short list of three used to miss: "/\\(a\\)" is the way to ask for a
574
+ * literal parenthesis, and comparing it as text looked for the backslashes on the wire and
575
+ * answered 404. A reserved character written bare, "/(a)", has to reach the compiler too, which
576
+ * is what refuses it the way express does.
562
577
  *
563
578
  * @param {string|RegExp} pattern
564
579
  * @returns {boolean}
@@ -568,7 +583,7 @@ function needsConversionToRegex(pattern) {
568
583
  return false;
569
584
  }
570
585
 
571
- return pattern.includes("*") || pattern.includes(":") || pattern.includes("{");
586
+ return PATH_SYNTAX.test(pattern);
572
587
  }
573
588
 
574
589
  /**