Skip to content

Commit 7408b73

Browse files
pref: fast path for parsing requests without \0
2 parents 84b0e28 + 40a4050 commit 7408b73

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

lib/util/identifier.js

+44-2
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,61 @@
77

88
const PATH_QUERY_FRAGMENT_REGEXP =
99
/^(#?(?:\0.|[^?#\0])*)(\?(?:\0.|[^#\0])*)?(#.*)?$/;
10+
const ZERO_ESCAPE_REGEXP = /\0(.)/g;
1011

1112
/**
1213
* @param {string} identifier identifier
1314
* @returns {[string, string, string]|null} parsed identifier
1415
*/
1516
function parseIdentifier(identifier) {
17+
if (!identifier) {
18+
return null;
19+
}
20+
21+
const firstEscape = identifier.indexOf("\0");
22+
if (firstEscape < 0) {
23+
// Fast path for inputs that don't use \0 escaping.
24+
const queryStart = identifier.indexOf("?");
25+
// Start at index 1 to ignore a possible leading hash.
26+
const fragmentStart = identifier.indexOf("#", 1);
27+
28+
if (fragmentStart < 0) {
29+
if (queryStart < 0) {
30+
// No fragment, no query
31+
return [identifier, "", ""];
32+
}
33+
// Query, no fragment
34+
return [
35+
identifier.slice(0, queryStart),
36+
identifier.slice(queryStart),
37+
""
38+
];
39+
}
40+
41+
if (queryStart < 0 || fragmentStart < queryStart) {
42+
// Fragment, no query
43+
return [
44+
identifier.slice(0, fragmentStart),
45+
"",
46+
identifier.slice(fragmentStart)
47+
];
48+
}
49+
50+
// Query and fragment
51+
return [
52+
identifier.slice(0, queryStart),
53+
identifier.slice(queryStart, fragmentStart),
54+
identifier.slice(fragmentStart)
55+
];
56+
}
57+
1658
const match = PATH_QUERY_FRAGMENT_REGEXP.exec(identifier);
1759

1860
if (!match) return null;
1961

2062
return [
21-
match[1].replace(/\0(.)/g, "$1"),
22-
match[2] ? match[2].replace(/\0(.)/g, "$1") : "",
63+
match[1].replace(ZERO_ESCAPE_REGEXP, "$1"),
64+
match[2] ? match[2].replace(ZERO_ESCAPE_REGEXP, "$1") : "",
2365
match[3] || ""
2466
];
2567
}

test/identifier.test.js

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ describe("parse identifier. edge cases", () => {
5353
{
5454
input: "path/#/not/a/hash?not-a-query",
5555
expected: ["path/", "", "#/not/a/hash?not-a-query"]
56+
},
57+
{
58+
input: "#\0?\0#ab\0\0c?\0#\0\0query#?#\0fragment",
59+
expected: ["#?#ab\0c", "?#\0query", "#?#\0fragment"]
5660
}
5761
];
5862

0 commit comments

Comments
 (0)