-
-
Notifications
You must be signed in to change notification settings - Fork 50
Added HTTP/2 support for onFinished and isFinished functions #100
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
base: v3
Are you sure you want to change the base?
Conversation
bjohansebas
left a comment
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.
Okay, I haven’t fully reviewed your PR yet, although I’ve also been working on this (see #87). I’m implementing tests using compatibility mode, while yours uses native HTTP/2
Hi @bjohansebas , thanks for the note and for working on this as well. I want to better understand your approach. When you mention compatibility mode, is the main goal to cover how most users run HTTP two in Node, or are there specific lifecycle or edge cases that native Http2Stream based handling might miss. I am wondering if supporting both native HTTP two and compatibility mode would make sense here. |
|
I feel we could handle both cases. For Express HTTP/2 support, it will be done through the compatibility layer, which is why I’ve mainly focused on that in my other PR (the reason being that this is exactly why the compatibility mode exists; it’s also how Fastify handles it, and it saves us from having to re-implement many of our middlewares and Express itself). I think we could support both possible cases and merge our two PRs. That’s how I’m currently thinking about it, although I’m still testing things, since I’ve discovered some specific edge cases that affect both Node.js’s implementation and ours. Edit: I still haven’t found an edge case, or at least I think so. I was just doing some of the tests incorrectly in #87 . |
index.js
Outdated
| if (http2.Http2Stream && msg instanceof http2.Http2Stream) { | ||
| return Boolean(msg.destroyed || msg.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.
These added lines will never execute because both Http2ServerResponse and Http2Stream have the writeableEnded property, so we will return early in the first condition which checks for it on line 72
I don't think any functional changes are required to master to get http2 support, just tests.
Looks like the request abort scenario does need stream.closed check, but it need to come first or else we will return writeablEnded which is not sufficient for all cases in http2
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.
Hi @jonchurch , I did some changes on that with more correct handling, it's now not uses native http2 because not needing, just checks with executive.
Console Test Output
npm run test 01/12/26 18:50:11 PM
> on-finished@2.4.1 test
> mocha --reporter spec --check-leaks test/
HTTP/2
onFinished(res, listener)
with ServerResponse
http2
✔ should fire when response finishes
http2
✔ should include the stream object
http2
✔ should fire when response is destroyed
when called after finish
http2
http2
✔ should fire immediately
with async local storage
http2
http2
✔ should persist store in callback
with async local storage
http2
✔ should persist store in callback
with multiple streams
http2
http2
✔ should fire for each stream independently
when client closes connection
http2
✔ should fire the callback
when stream errors
http2
✔ should fire the callback
isFinished(res)
http2
✔ should return false for unfinished stream
http2
http2
✔ should return true for finished stream
http2
✔ should return true for destroyed stream
onFinished(res, listener)
✔ should invoke listener given an unknown object
✔ should throw TypeError if listener is not a function
when the response finishes
http1
✔ should fire the callback
http1
✔ should include the response object
when called after finish
http1
http1
✔ should fire when called after finish
when async local storage
http1
http1
✔ should presist store in callback
when async local storage
http1
✔ should presist store in callback
when using keep-alive
http1
http1
✔ should fire for each response
when requests pipelined
http1
http1
http1
http1
✔ should fire for each request
when response errors
http1
✔ should fire with error
http1
✔ should include the response object
when the response aborts
http1
✔ should execute the callback
when calling many times on same response
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
✔ should not print warnings
isFinished(res)
✔ should return undefined for unknown object
http1
✔ should be false before response finishes
http1
http1
✔ should be true after response finishes
when requests pipelined
http1
http1
http1
http1
✔ should have correct state when socket shared
http1
http1
✔ should handle aborted requests
when response errors
http1
http1
✔ should return true
when the response aborts
http1
http1
✔ should return true
onFinished(req, listener)
✔ should throw TypeError if listener is not a function
when the request finishes
http1
✔ should fire the callback
http1
✔ should include the request object
when called after finish
http1
http1
✔ should fire when called after finish
when async local storage
http1
http1
✔ should presist store in callback
when async local storage
http1
✔ should presist store in callback
when using keep-alive
http1
http1
✔ should fire for each request
when request errors
http1
✔ should fire with error
http1
✔ should include the request object
when requests pipelined
http1
http1
✔ should handle socket errors
when the request aborts
http1
✔ should execute the callback
when calling many times on same request
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
http1
✔ should not print warnings
when CONNECT method
http1
✔ should fire when request finishes
http1
http1
✔ should fire when called after finish
when Upgrade request
http1
✔ should fire when request finishes
http1
http1
✔ should fire when called after finish
isFinished(req)
✔ should return undefined for unknown object
http1
✔ should be false before request finishes
http1
http1
✔ should be true after request finishes
when request data buffered
http1
http1
✔ should be false before request finishes
when request errors
http1
http1
✔ should return true
when the request aborts
http1
http1
✔ should return true
when CONNECT method
http1
✔ should be true immediately
http1
http1
✔ should be true after request finishes
when Upgrade request
http1
✔ should be true immediately
http1
http1
✔ should be true after request finishes
58 passing (410ms)
Core Approach:
Related to #57, can you review @Phillip9587 ?