Consider the following HTTP client, following official example of the http module`:
var http = require('http');
http.get('http://127.0.0.1:12345/', function(response) {
console.log('got response ', response.statusCode);
var body = [];
response.on('data', function(data) {
console.log('got data: ', data);
});
response.on('end', function() {
body = Buffer.concat(body).toString();
console.log('end body = ', body, ' complete = ', response.complete);
console.log('success!');
});
}).on('error', function(err) {
console.log('ClientRequest error: ' + err);
console.log('error!');
});
Here I make an HTTP request, and report on three occasions: whenever I start receiving an HTTP response, whenever I get some HTTP body data, whenever the response is complete, and on all errors.
I expect this code to always complete (unless the connection hangs) with exactly one of success! or error! in logs. However, if the connect resets after the server has already sent some headers, I get both. Here is an example output:
got response 200
got data: <Buffer 48 65 6c 6c 6f 0a>
ClientRequest error: Error: read ECONNRESET
error!
end body = Hello
complete = true
success!
How to reproduce:
nc -l -p 12345to start a debug server.- Run the client with
node a.js. I usenode v18.14.2on Windows, but I saw the same behavior on Ubuntu 22.04 withnode v12.22.9as well. - Type the following response, but do not abort
ncjust yet:HTTP/1.1 200 OK Hello - Terminate the
ncprocess with task manager (Windows) or kill the TCP connection withsudo tcpkill -i lo port 12345and writing something else tonc(Linux).
It seems like Node both detects the error (hence the error callback is fired) and considers the HTTP request a success (hence to end callback is fired). In my original code that resulted in two instances of my application continuing instead of one which was very confusing.
How do I make sure exactly one of those is fired, and only on successful HTTP responses?
I suggest taking a look at the once() function which removes itself after being called, here is a link to it's reference - https://nodejs.org/api/events.html#emitteronceeventname-listener
Also, your code seems to be a get-event handler on a server but is behaving as though it is reading data from a server, and so I am not sure if you have confused the two here or if I am mistaken, however I would also recommend taking a look at using something like 'Node Fetch' that simplifies your program execution flow - https://www.npmjs.com/package/node-fetch
And looks something like this instead of the traditional event handlers: