-
Notifications
You must be signed in to change notification settings - Fork 48
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
feat: support http2 #126
feat: support http2 #126
Conversation
src/request.ts
Outdated
const rawHeaders = incoming.rawHeaders | ||
for (let i = 0; i < rawHeaders.length; i += 2) { | ||
const {[i]: key, [i + 1]: value} = rawHeaders | ||
if (key.charCodeAt(0) !== /*:*/ 0x3a) { | ||
headerRecord.push([key, value]) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Undici had a bug that allowed ':', which was not allowed in the header name, but now that it is fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these lines really necessary? These affect performance, so I would like to remove them if it is not a practical problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What version of undici are you using?
The whatwg fetch spec does not allow h2 pseudo-headers containing :
and throws an error. This check is necessary.
> $ node
Welcome to Node.js v21.6.1.
Type ".help" for more information.
> new Headers({ ":authority": "localhost" });
Uncaught TypeError: Headers.append: ":authority" is an invalid header name.
at webidl.errors.exception (node:internal/deps/undici/undici:1636:14)
at webidl.errors.invalidArgument (node:internal/deps/undici/undici:1647:28)
at appendHeader (node:internal/deps/undici/undici:2053:29)
at fill (node:internal/deps/undici/undici:2039:11)
at new Headers (node:internal/deps/undici/undici:2167:11)
> $ node
Welcome to Node.js v20.11.0.
Type ".help" for more information.
> new Headers({ ":authority": "localhost" }); // allowed
HeadersList {
cookies: null,
[Symbol(headers map)]: Map(1) { ':authority' => { name: ':authority', value: 'localhost' } },
[Symbol(headers map sorted)]: null
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see!
@usualoma Can you see this? I think we have to go with this code, but any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @yusukebe |
Hi @tsctx Sorry for the delay. I've commented. |
As for const url = `http://${req instanceof Http2ServerRequest ? req.authority : req.headers.host}${req.url}` https://nodejs.org/api/http2.html#requestauthority
|
Sorry, I was looking in the wrong place, so I modified my comment a bit. |
Thanks for sharing this with me. It should always be so.
Fixed fae3065
IMO we should always do // server.mjs
import * as http from 'node:http'
// without `new URL()`
http.createServer((req, res) => res.end(req.url)).listen(3000, '0.0.0.0')
// with `new URL()`
http.createServer((req, res) => res.end(new URL(`http://${req.headers.host}${req.url}`).pathname)).listen(3001, '0.0.0.0') Result: > $ curl "http://localhost:3000/path\\"
/path\\
> $ curl "http://localhost:3001/path\\"
/path// |
794bbfc
to
e213fc6
Compare
@tsctx Thank you. I understand. diff --git a/src/request.ts b/src/request.ts
index 9c7ec49..74565af 100644
--- a/src/request.ts
+++ b/src/request.ts
@@ -7,12 +7,13 @@ import { Readable } from 'node:stream'
const newRequestFromIncoming = (
method: string,
+ url: string,
incoming: IncomingMessage | Http2ServerRequest
): Request => {
const headerRecord: [string, string][] = []
const rawHeaders = incoming.rawHeaders
for (let i = 0; i < rawHeaders.length; i += 2) {
- const {[i]: key, [i + 1]: value} = rawHeaders
+ const { [i]: key, [i + 1]: value } = rawHeaders
if (key.charCodeAt(0) !== /*:*/ 0x3a) {
headerRecord.push([key, value])
}
@@ -30,12 +31,13 @@ const newRequestFromIncoming = (
;(init as any).duplex = 'half'
}
- return new Request(`http://${incoming instanceof Http2ServerRequest ? incoming.authority : incoming.headers.host}${incoming.url}`, init)
+ return new Request(url, init)
}
const getRequestCache = Symbol('getRequestCache')
const requestCache = Symbol('requestCache')
const incomingKey = Symbol('incomingKey')
+const urlKey = Symbol('urlKey')
const requestPrototype: Record<string | symbol, any> = {
get method() {
@@ -43,13 +45,15 @@ const requestPrototype: Record<string | symbol, any> = {
},
get url() {
- if (this[requestCache]) return this[requestCache].url
- const req = this[incomingKey]
- return new URL(`http://${req instanceof Http2ServerRequest ? req.authority : req.headers.host}${req.url}`).href
+ return this[urlKey]
},
[getRequestCache]() {
- return (this[requestCache] ||= newRequestFromIncoming(this.method, this[incomingKey]))
+ return (this[requestCache] ||= newRequestFromIncoming(
+ this.method,
+ this[urlKey],
+ this[incomingKey]
+ ))
},
}
;[
@@ -84,5 +88,10 @@ Object.setPrototypeOf(requestPrototype, global.Request.prototype)
export const newRequest = (incoming: IncomingMessage | Http2ServerRequest) => {
const req = Object.create(requestPrototype)
req[incomingKey] = incoming
+ req[urlKey] = new URL(
+ `http://${incoming instanceof Http2ServerRequest ? incoming.authority : incoming.headers.host}${
+ incoming.url
+ }`
+ ).href
return req
} |
@yusukebe ptal |
@usualoma Thanks! |
@tsctx Thank you! |
No description provided.