Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

http.request(method: HEAD) + server keep-alive = uncatchable "Parse error" #2206

Closed
avz opened this issue Nov 27, 2011 · 5 comments
Closed
Labels

Comments

@avz
Copy link

avz commented Nov 27, 2011

In the HEAD-request if the server responded Connection: keep-alive then http.request() throws a Parse error, but a handler for error is not called.

server.js

var net = require('net')

var server = net.createServer(function (socket) {
    var headers = [
        'HTTP/1.1 200 OK',
        'Connection: keep-alive',
        'Content-Length: 1' // required
    ]

    socket.write(headers.join('\r\n') + '\r\n\r\n1')
    socket.end()
})

server.listen(8888, '127.0.0.1')

client.js

var http = require('http')

var options = {
    host: 'localhost',
    port: 8888,
    path: '/',
    method: 'HEAD' // GET-requests work properly
};

var req = http.request(options, function(res) {
    console.log('STATUS: ' + res.statusCode);
    console.log('HEADERS: ' + JSON.stringify(res.headers));

    res.on('data', function (chunk) {
        console.log('BODY: ' + chunk);
    });
});

req.on('error', function(e) {
  console.log('HANDLED: ' + e.message);
});

req.end();

process.on('uncaughtException', function(err) {
    console.log('UNHANDLED: ' + err.stack)
})

result:

# node client.js
STATUS: 200
HEADERS: {"connection":"keep-alive","content-length":"1"}
UNHANDLED: Error: Parse Error
    at Socket.ondata (http.js:1125:24)
    at TCP.onread (net.js:334:27)

System info

# uname -srm
FreeBSD 8.2-STABLE amd64
# node -v
v0.6.3
@koichik
Copy link

koichik commented Nov 28, 2011

socket.write(headers.join('\r\n') + '\r\n\r\n1')

Because the response of HEAD method does NOT have a body, the last character ('1') is NOT a part of the response.
Is it intentional?

With Connection: keep-alive, the response is completed without an error after all headers are received, and socket is detached.
Then the illegal data ('1') is detected.
So... who should emit the error? Agent?

@avz
Copy link
Author

avz commented Nov 28, 2011

I know that is illegal response, but I want to catch this error in req.on('error') handler, not process.on('uncaughtException')

@koichik
Copy link

koichik commented Nov 28, 2011

Because the response is completed successfully, the req should not emit 'error' event.

If the second request exists, it emits 'error'.
example:

    res.on('data', function (chunk) {
        console.log('BODY: ' + chunk);
    });

    // append below
    res.on('end', function() {
        http.globalAgent.maxSockets = 1;
        var req2 = http.request(options, function(res2) {
        });
        req2.on('error', function(e) {
            console.log('HANDLED by REQ2: ' + e.message);
        });
        req.end();
    });

result:

STATUS: 200
HEADERS: {"connection":"keep-alive","content-length":"1"}
HANDLED by REQ2: Parse Error

Because illegal data ('1') is the first character of the second response (it should be 'H' of HTTP/1.1 200 ok).
But, in your case, the second request does not exist, no request can emit 'error'.

You can catch the error on the socket.
example:

req.on('error', function(e) {
    console.log('HANDLED by SOCKET: ' + e.message);
});

// append below
req.on('socket', function(socket) {
  socket.on('error', function(e) {
    console.log('SOCKET HANDLED: ' + e.message);
  });
});

result:

STATUS: 200
HEADERS: {"connection":"keep-alive","content-length":"1"}
HANDLED by SOCKET: Parse Error

@luk-
Copy link

luk- commented Jul 1, 2013

resolved?

@bnoordhuis
Copy link
Member

Yep, resolved as of 827b2a9.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants