Fix handling of HTTP upgrades with bodies#60016
Merged
nodejs-github-bot merged 1 commit intonodejs:mainfrom Nov 3, 2025
Merged
Fix handling of HTTP upgrades with bodies#60016nodejs-github-bot merged 1 commit intonodejs:mainfrom
nodejs-github-bot merged 1 commit intonodejs:mainfrom
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #58394
Previously, when processing and accepting a Upgrade request, we ignored all indicators of a body in the request (content-length or transfer-encoding headers) and treated any information following the headers as part of the upgraded stream itself.
This was not correct. An HTTP request to upgrade can have a body, and it will always indicate this with standard headers to do so. If the request had a valid HTTP body, you shouldn't treat it as part of the new protocol stream you've upgraded to.
With this change, we now fully process the requests bodies separately instead, allowing us to automatically handle correct parsing of the body like any other HTTP request.
Fixing this is a matter of persuading llhttp to parse the body like normal. The llhttp return values for on_headers_complete (i.e. this
parserOnIncomingfunction) are (docs):The current Node code for this basically assumes that
2is required for to finish parsing an accepted upgrade or CONNECT, but as far as I can tell (based on this) that's not true. In this case, the upgrade flag is already set (that'sreq.upgradehere) and that's what controls whether the upgrade happens after the message is completed (here). Setting2would set the upgrade flag to true (but it's already true) and set SKIPBODY to true (which is what we're trying to fix here, and isn't required because this condition skips the body for CONNECT or no-body-headers-present for upgrades anyway).This is a breaking change if you are currently accepting HTTP Upgrade requests with request bodies successfully, or if you use socket-specific fields & methods on the upgraded stream argument.
In the former case, before now you will have received the request body and then the upgraded data on the same stream without any distinction or HTTP parsing applied. Now, you will need to separately read the request body from the request (the 1st argument) and the upgraded data from the upgrade stream (the 2nd argument). If you're not interested in request bodies, you can continue to just read from the upgrade stream directly.
In the latter case, if you want to access the raw socket, you should do so via request.socket, instead of expecting the 2nd argument to be a socket.
Separately, it's debatable whether we should also actually support bodies on CONNECT requests. Even with this change, we currently don't. That would require a small change to llhttp. The latest HTTP RFCs say:
but also
so to my mind it's somewhat unspecified (as opposed to Upgrade requests, where this isn't ambiguous at all imo). Opinions welcome on whether to modify llhttp to support that.