Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: align Headers to spec #10199

Merged
merged 1 commit into from
Apr 18, 2021
Merged

Conversation

lucacasonato
Copy link
Member

@lucacasonato lucacasonato commented Apr 15, 2021

This commit aligns Headers to spec. It also removes the now unused
03_dom_iterable.js file. We now pass all relevant Headers WPT. We do
not implement any sort of header filtering, as we are a server side
runtime.

This is likely not the most efficient implementation of Headers yet. It is
however spec compliant. Once all the APIs in the HTTP hot loop are
correct we can start optimizing them. It is likely that this reduces bench
throughput temporarily.

Comment on lines +11 to +78
const ASCII_DIGIT = ["\u0030-\u0039"];
const ASCII_UPPER_ALPHA = ["\u0041-\u005A"];
const ASCII_LOWER_ALPHA = ["\u0061-\u007A"];
const ASCII_ALPHA = [...ASCII_UPPER_ALPHA, ...ASCII_LOWER_ALPHA];
const ASCII_ALPHANUMERIC = [...ASCII_DIGIT, ...ASCII_ALPHA];

const HTTP_TAB_OR_SPACE = ["\u0009", "\u0020"];
const HTTP_WHITESPACE = ["\u000A", "\u000D", ...HTTP_TAB_OR_SPACE];

const HTTP_TOKEN_CODE_POINT = [
"\u0021",
"\u0023",
"\u0024",
"\u0025",
"\u0026",
"\u0027",
"\u002A",
"\u002B",
"\u002D",
"\u002E",
"\u005E",
"\u005F",
"\u0060",
"\u007C",
"\u007E",
...ASCII_ALPHANUMERIC,
];
const HTTP_TOKEN_CODE_POINT_RE = new RegExp(
`^[${regexMatcher(HTTP_TOKEN_CODE_POINT)}]+$`,
);
const HTTP_QUOTED_STRING_TOKEN_POINT = [
"\u0009",
"\u0020-\u007E",
"\u0080-\u00FF",
];
const HTTP_QUOTED_STRING_TOKEN_POINT_RE = new RegExp(
`^[${regexMatcher(HTTP_QUOTED_STRING_TOKEN_POINT)}]+$`,
);
const HTTP_WHITESPACE_MATCHER = regexMatcher(HTTP_WHITESPACE);
const HTTP_WHITESPACE_PREFIX_RE = new RegExp(
`^[${HTTP_WHITESPACE_MATCHER}]+`,
"g",
);
const HTTP_WHITESPACE_SUFFIX_RE = new RegExp(
`[${HTTP_WHITESPACE_MATCHER}]+$`,
"g",
);

/**
* Turn a string of chars into a regex safe matcher.
* @param {string[]} chars
* @returns {string}
*/
function regexMatcher(chars) {
const matchers = chars.map((char) => {
if (char.length === 1) {
return `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`;
} else if (char.length === 3 && char[1] === "-") {
return `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}-\\u${
char.charCodeAt(2).toString(16).padStart(4, "0")
}`;
} else {
throw TypeError("unreachable");
}
});
return matchers.join("");
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all just moved from //op_crates/web/01_mimesniff.js

Comment on lines +689 to +695
"headers-basic.any.js": true,
"headers-casing.any.js": true,
"headers-combine.any.js": true,
"headers-errors.any.js": true,
"headers-normalize.any.js": true,
"headers-record.any.js": true,
"headers-structure.any.js": true
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All relevant tests pass.

@lucacasonato lucacasonato requested a review from ry April 15, 2021 16:47
@lucacasonato
Copy link
Member Author

The unit_test/fetch.ts changes are harmless and not technically wrong, but not great. I can not easily resolve this without conflicting with my follow-up PR that rewrites Body, and Request, so I would vote to keep it as is for now and revert the test changes in the follow up PR.

Comment on lines -380 to -389
unitTest(function headersSetDuplicateCookieKey(): void {
const headers = new Headers([["Set-Cookie", "foo=bar"]]);
headers.set("set-Cookie", "foo=baz");
headers.set("set-cookie", "bar=qat");
const actual = [...headers];
assertEquals(actual, [
["set-cookie", "foo=baz"],
["set-cookie", "bar=qat"],
]);
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is plain wrong. headers.set is not the same as append. It removes existing headers of that name before insertion. See https://fetch.spec.whatwg.org/#concept-header-list-set

Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

This commit aligns `Headers` to spec. It also removes the now unused
03_dom_iterable.js file. We now pass all relevant `Headers` WPT. We do
not implement any sort of header filtering, as we are a server side
runtime.

This is likely not the most efficient implementation of `Headers` yet.
It is however spec compliant. Once all the APIs in the `HTTP` hot loop
are correct we can start optimizing them. It is likely that this commit
reduces bench throughput temporarily.
@lucacasonato lucacasonato merged commit 0552eaf into denoland:main Apr 18, 2021
@lucacasonato lucacasonato deleted the align_headers branch April 18, 2021 23:00
@ry
Copy link
Member

ry commented May 6, 2021

This PR caused a fairly severe performance degradation in the performance of std/http/server.ts

Screen Shot 2021-05-06 at 7 57 20 AM

@lucacasonato
Copy link
Member Author

lucacasonato commented May 6, 2021

This is most likely caused by the O(n^2) complexity of https://github.com/denoland/deno/blob/main/extensions/fetch/20_headers.js#L178-L207

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants