Skip to content

Commit

Permalink
http: do not send 0\r\n\r\n in TE HEAD responses
Browse files Browse the repository at this point in the history
When replying to a HEAD request, do not attempt to send the trailers and
EOF sequence (`0\r\n\r\n`). The HEAD request MUST not have body.

Quote from RFC:

The presence of a message body in a response depends on both the
request method to which it is responding and the response status code
(Section 3.1.2).  Responses to the HEAD request method (Section 4.3.2
of [RFC7231]) never include a message body because the associated
response header fields (e.g., Transfer-Encoding, Content-Length,
etc.), if present, indicate only what their values would have been if
the request method had been GET (Section 4.3.1 of [RFC7231]).

fix nodejs#8361

Reviewed-By: Timothy J Fontaine <tjfontaine@gmail.com>
  • Loading branch information
indutny authored and tjfontaine committed Sep 16, 2014
1 parent 6e689ec commit 1fddc1f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 24 deletions.
6 changes: 5 additions & 1 deletion lib/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,10 @@ OutgoingMessage.prototype.end = function(data, encoding) {
if (encoding === 'hex' || encoding === 'base64')
hot = false;

// Transfer-encoding: chunked responses to HEAD requests
if (this._hasBody && this.chunkedEncoding)
hot = false;

if (hot) {
// Hot path. They're doing
// res.writeHead();
Expand Down Expand Up @@ -982,7 +986,7 @@ OutgoingMessage.prototype.end = function(data, encoding) {
}

if (!hot) {
if (this.chunkedEncoding) {
if (this._hasBody && this.chunkedEncoding) {
ret = this._send('0\r\n' + this._trailer + '\r\n', 'ascii');
} else {
// Force a flush, HACK.
Expand Down
58 changes: 35 additions & 23 deletions test/simple/test-http-head-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,44 @@ var util = require('util');


var body = 'hello world\n';
var id = 0;

var server = http.createServer(function(req, res) {
common.error('req: ' + req.method);
res.writeHead(200, {'Content-Length': body.length});
res.end();
server.close();
});
function test(headers) {
var port = common.PORT + id++;

var server = http.createServer(function(req, res) {
console.error('req: %s headers: %j', req.method, headers);
res.writeHead(200, headers);
res.end();
server.close();
});

var gotEnd = false;

var gotEnd = false;

server.listen(common.PORT, function() {
var request = http.request({
port: common.PORT,
method: 'HEAD',
path: '/'
}, function(response) {
common.error('response start');
response.on('end', function() {
common.error('response end');
gotEnd = true;
server.listen(port, function() {
var request = http.request({
port: port,
method: 'HEAD',
path: '/'
}, function(response) {
console.error('response start');
response.on('end', function() {
console.error('response end');
gotEnd = true;
});
response.resume();
});
response.resume();
request.end();
});
request.end();
});

process.on('exit', function() {
assert.ok(gotEnd);
process.on('exit', function() {
assert.ok(gotEnd);
});
}

test({
'Transfer-Encoding': 'chunked'
});
test({
'Content-Length': body.length
});

0 comments on commit 1fddc1f

Please sign in to comment.