My node.js application is using http.request
to the REST API http://army.gov/launch-nukes
and I need to distinguish between three possible cases:
Success
-- The server replies in the affirmative. I know my enemies are destroyed.Failure
-- Either I have received error from the server, or was unable to connect to server. I still have enemies. Unknown
-- After establishing a connection to the server, I have sent the request -- but not sure what happened. This could mean the request never made it to the server, or the server response to me never made it. I may or may not have just started a world war.As you can see, it's very important for me to distinguish the Failure
and Unknown
case, as they have very different consequences and different actions I need to take.
I would also very much like to use http Keep-Alive -- as what can I say, I'm a bit of a war-monger and plan on making lots of requests in bursts (and then nothing for long periods of time)
--
The core of the question is how to separate a connection-error/time-out (which is a Failure
) from an error/timeout that occurs after the request is put on the wire (which is an Unknown
).
In psuedo-code logic I want this:
var tcp = openConnectionTo('army.gov') // start a new connection, or get an kept-alive one tcp.on('error', FAILURE_CASE); tcp.on('connectionEstablished', function (connection) { var req = connection.httpGetRequest('launch-nukes'); req.on('timeout', UNKNOWN_CASE); req.on('response', /* read server response and decide FAILURE OR SUCCESS */); } )
Your code is non-blocking because it uses non-blocking I/O with the request() function. This means that node. js is free to service other requests while your series of http requests is being fetched.
In general, Node. js errors are divided into two distinct categories: operational errors and programmer errors.
Here is an example:
var http = require('http'); var options = { hostname: 'localhost', port: 7777, path: '/', method: 'GET' }; var req = http.request(options, function (res) { // check the returned response code if (('' + res.statusCode).match(/^2\d\d$/)) { // Request handled, happy } else if (('' + res.statusCode).match(/^5\d\d$/)) // Server error, I have no idea what happend in the backend // but server at least returned correctly (in a HTTP protocol // sense) formatted response } }); req.on('error', function (e) { // General error, i.e. // - ECONNRESET - server closed the socket unexpectedly // - ECONNREFUSED - server did not listen // - HPE_INVALID_VERSION // - HPE_INVALID_STATUS // - ... (other HPE_* codes) - server returned garbage console.log(e); }); req.on('timeout', function () { // Timeout happend. Server received request, but not handled it // (i.e. doesn't send any response or it took to long). // You don't know what happend. // It will emit 'error' message as well (with ECONNRESET code). console.log('timeout'); req.abort(); }); req.setTimeout(5000); req.end();
I recommend you play with it using netcat, ie.:
$ nc -l 7777 // Just listens and does not send any response (i.e. timeout) $ echo -e "HTTP/1.1 200 OK\n\n" | nc -l 7777 // HTTP 200 OK $ echo -e "HTTP/1.1 500 Internal\n\n" | nc -l 7777 // HTTP 500
(and so on...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With