nodejs / nodejs/node

Stream finished does not always work with http incoming message

Open
#38,657 22 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

stream
Dominant language
JavaScript
Stars
122k
Forks
37.3k
Avg merge
4d 2h
Merged PRs (30d)
283

Description

  • Version: v15.12.0
  • Platform: Darwin Kernel Version 20.3.0
  • Subsystem: http
What steps will reproduce the bug?

The stream.finished never resolves or rejects when applied onto a destroyed incoming message like in example below. It finishes for example when applied on a destroyed file stream. Also it finishes when the line with await new Promise(r => setTimeout(r, 1000)); is commented. This looks really inconsistent.

let http = require("http");
let { finished } = require("stream/promises");

let server = http.createServer(async function(req, res)
{
	for await (let chunk of req) break;
	await new Promise(r => setTimeout(r, 1000));
	console.log("waiting");
	await finished(req);
	console.log("sending");
	res.end();
});

(async function()
{
	await new Promise(resolve => server.listen(resolve));
	let req = http.request({ port: server.address().port, method: "post" }).end("abc");
	try
	{
		let res = await new Promise((resolve, reject) => req.on("response", resolve).on("error", reject));
		await finished(res.resume());
	}
	catch(e)
	{
		console.log(e);
	}
}());
How often does it reproduce? Is there a required condition?

Always.

What is the expected behavior?
Error: socket hang up
waiting
sending
What do you see instead?
Error: socket hang up
waiting
Additional information

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided http.createServer reproduction on Node v15.12.0 and tracing the interaction between the incoming request, the stream/promises finished function, and the delayed await. Compare the destroyed request behavior with the file-stream behavior shown in the report. Done means the reproduction reaches "sending" and produces the expected socket hang-up output.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.