Skip to content
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

http.ClientRequest ignores incomplete chunked http response #25081

Closed
bjarketrux opened this issue Dec 17, 2018 · 7 comments
Closed

http.ClientRequest ignores incomplete chunked http response #25081

bjarketrux opened this issue Dec 17, 2018 · 7 comments
Labels
http Issues or PRs related to the http subsystem.

Comments

@bjarketrux
Copy link

When fetching a file via http with header Transfer-Encoding: chunked a prematurely disrupted connection (socket) is not handled properly.

According to the MDN a chunked response is terminated by a 0-length chunk at the end.

Example code

var http = require("http");

const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write("chunk-1");

    setTimeout(() => res.write("chunk-2"), 2000);
    setTimeout(() => res.socket.destroy(), 4000);
    // Normally the response would look like this
    // setTimeout(() => res.write("chunk-3"), 4000);
    // setTimeout(() => res.end(), 6000);
});

server.listen(8000);

var req = http.get("http://localhost:8000", res => {
    console.log("Status code:", res.statusCode);

    res.on("data", data => {
        console.log("Received chunk:", data.toString());
    });

    res.on("end", () => console.log("Ended"));
});

req.on("error", error => {
    console.log("Request error:", error);
});

Observed behavior

Executing the example code will output:

Status code: 200
Received chunk: chunk-1
Received chunk: chunk-2
Ended

Expected behavior

I would expect the following output:

Status code: 200
Received chunk: chunk-1
Received chunk: chunk-2
Request error: ERR_INCOMPLETE_CHUNKED_ENCODING

Note: The code ERR_INCOMPLETE_CHUNKED_ENCODING is what Chrome will write when navigating to http://localhost:8000, but I imagine node.js will have another code.

Note 2: Data is not called with the 0-size termination message.

Alternative behavior:
The end event is called with an error or message saying that the underlying socket was closed but the chunked message was not terminated.

If the observed behavior is expected, what can I do to detect an incomplete message? Note that I want to pipe the response into a file so I will not implement the on('data') handler.

  • Version: v8.12.0
  • Platform: MacOS Mojave 10.14.2
@akshayarise
Copy link

@bjarketrux

According to MDN

At the beginning of each chunk you need to explicitly add the length of the current chunk in hexadecimal format, followed by '\r\n' and then the chunk itself, followed by another '\r\n'. The terminating chunk is a regular chunk, with the exception that its length is zero. It is followed by the trailer, which consists of a (possibly empty) sequence of entity header fields.

@bjarketrux
Copy link
Author

@akshayarise
The message send from the server already has this format. The problem is detecting (from the client) if all chunks has been received or if the underlying socket was closed prematurely.

@bnoordhuis bnoordhuis added the http Issues or PRs related to the http subsystem. label Dec 28, 2018
@bjarketrux
Copy link
Author

Any update?

@lpinca
Copy link
Member

lpinca commented Mar 16, 2019

@bjarketrux you can use https://nodejs.org/api/http.html#http_message_complete

res.on('end', function() {
  console.log(this.complete);
})

@bjarketrux
Copy link
Author

@lpinca If you look at the observed and expected behavior sections in the original post you can see that I already use the 'end' event but this is not the issue.

This issue is that I cannot distinguish between a normal stream and an abrupted connection which is exactly what I want.

@lpinca
Copy link
Member

lpinca commented Mar 17, 2019

I can't see where message.complete is used in your example code. When the 'end' event is emitted you can check the complete attribute. This allows you to know if the response is complete (whether or not all chunks have been received).

@bjarketrux
Copy link
Author

Whoops, I should have read the answer instead of complaining about you not reading the question :-D

Works absolutely! 🥇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http Issues or PRs related to the http subsystem.
Projects
None yet
Development

No branches or pull requests

4 participants