-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
http2: minor cleanup of compat, tests #15254
Conversation
4a28942
to
3765d47
Compare
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.
Good work, thanks so much for helping out. I've left some comments around.
Regarding headers, I think we might want to validate them in core.js
, but I'll leave the final decision to @jasnell.
While you are cleaning things up, I think the doc for Http2ServerRequest
is not completed (my bad), would you mind to fill it up? https://nodejs.org/api/http2.html#http2_class_http2_http2serverrequest
lib/internal/http2/compat.js
Outdated
case HTTP2_HEADER_METHOD: | ||
case HTTP2_HEADER_PATH: | ||
case HTTP2_HEADER_AUTHORITY: | ||
case HTTP2_HEADER_SCHEME: |
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.
these read worse than the string IMHO. I'm ok in doing thia, just add a small comment nearby with their meaning.
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.
Yeah, I just wanted to have this similar to core where everything is a constant. I'll add the comments for sure.
@@ -155,23 +167,17 @@ class Http2ServerRequest extends Readable { | |||
} | |||
|
|||
get closed() { | |||
const state = this[kState]; | |||
return Boolean(state.closed); | |||
return this[kState].closed; |
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 think kState
can be nulled, shouldn't we protect this?
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 don't think there's ever a situation where that can happen (I reviewed all of the code in compat) and since it's accessed via a Symbol, users would have to really go out of their way to null it. (And we only ever set this to true within kFinish, no other manipulation.)
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.
Ok, good catch!
lib/internal/http2/compat.js
Outdated
@@ -201,7 +207,7 @@ class Http2ServerRequest extends Readable { | |||
} | |||
|
|||
get socket() { | |||
return this.stream.session.socket; | |||
return this[kStream].session.socket; |
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.
this[kStream]
can be nulled, shouldn't we protect this?
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.
Yeah, I agree. It wasn't protected before so I wasn't sure if there was a reason for it or not.
On that note, hapi uses this (the socket) to set their internal processing flag and since our stream reference isn't accessible after 'finish', it throws. Should we maybe store a reference to the session directly and not null it on finish? It could lead to some garbage collection issues but on the flipside it's the only issue I found with hapi compatibility.
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.
@apapirovski I don't think what HAPI is actually doing in HTTP1 could be ported 1-1 to HTTP2. I've added this to be compatibile but for all intent and purposes this should not be used: the socket is controlled by the C++/C layers.
@jasnell what do you think?
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.
Yeah, it's a bit weird because they don't actually seem to use the socket based on my quick review of the code — maybe they did in the past. Now they just store a flag on it. When I built a version that retained the socket reference then my test site worked fine with h2 on hapi. But I agree with you re: not using it.
I guess it's all about how much we're willing to compromise for compatibility.
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.
Just a thought but if we do something like process.nextTick(() => (this[kStream] = undefined));
then we get the best of both worlds. It passes all our tests, makes hapi work and gets rid of the stream reference after the user finishes processing the 'finish' event. That's probably the most h1 compatible solution.
@@ -23,7 +23,6 @@ server.listen(0, common.mustCall(function() { | |||
|
|||
assert.strictEqual(request.method, expected[':method']); | |||
assert.strictEqual(request.scheme, expected[':scheme']); | |||
assert.strictEqual(request.path, expected[':path']); |
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 think we should add an assertion that request.path
is undefined
for express compatibility.
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.
Good thinking, will update.
Ok, new commit added. Mostly just addressed feedback and added a couple of extra protections that were missing. The one debatable change is, as I mentioned above, setting kStream to undefined on nextTick instead of immediately. Definitely open to feedback on that. Also still need to sort out the header validation situation. I might just move that out of this PR since it's not so obvious where we want to validate (people using compatibility API would expect it to validate right away — to match h1 — but we also want to validate in the core which happens later on). |
94afd5c
to
a4702dc
Compare
Moved the header validation out for now. Can revisit in a separate PR. |
c497173
to
04e2da9
Compare
This does not land cleanly on master, would you mind rebasing and squashing? |
Remove unnecessary variable assignments, remove unreachable code pathways, remove path getter and setter, and other very minor cleanup. Only remove reference to stream on nextTick so that users and libraries can access it in the finish event. Fixes: nodejs#15313 Refs: expressjs/express#3390
04e2da9
to
57ab2dc
Compare
Rebased and squashed, also updated the commit message to be more descriptive + added links. Should be good to go. |
Landed as c981483 |
Remove unnecessary variable assignments, remove unreachable code pathways, remove path getter and setter, and other very minor cleanup. Only remove reference to stream on nextTick so that users and libraries can access it in the finish event. Fixes: #15313 Refs: expressjs/express#3390 PR-URL: #15254 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Remove unnecessary variable assignments, remove unreachable code pathways, remove path getter and setter, and other very minor cleanup. Only remove reference to stream on nextTick so that users and libraries can access it in the finish event. Fixes: nodejs#15313 Refs: expressjs/express#3390 PR-URL: nodejs#15254 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Remove unnecessary variable assignments, remove unreachable code pathways, remove path getter and setter, and other very minor cleanup. Only remove reference to stream on nextTick so that users and libraries can access it in the finish event. Fixes: #15313 Refs: expressjs/express#3390 PR-URL: #15254 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This is a bit of a hodgepodge of stuff that's too small for its own PRs. Here's the full list:
Remove path getter and setter, related to Initial support proposal for http2 expressjs/express#3390.
Add validation for header names and values, as per the spec. @mcollina I would like your input on this as doing this in compat means that users can still set invalid headers through the API in core. It doesn't feel like we want this in two places but if we only validate inmapToHeaders
then methods likesetHeader
won't throw when they probably should. I'm also not sure if I should be importing code from http or making a copy in http2 utils — not sure how node would usually handle this.A few of the validations within if statements were moved up, such as checking for
stream.destroyed
inkBeginSend
to avoid executing unnecessary code.Remove unused properties in kState.
Remove all the extra code for creating kHeaders & kTrailers and instead just create them in the constructor. I ran a benchmark and this had no performance impact but it keeps the code a lot cleaner since we don't have to keep constantly checking for it.
Cleanup unnecessary variable assignments throughout to match the majority of the code in h2 and node in general.
Let me know if there's anything I can adjust! Thanks.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
http2, test