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

Commit

Permalink
http: close connection on 204 and chunked encoding
Browse files Browse the repository at this point in the history
This is similar to commit 2cbf458 but this time for 204 No Content
instead of 304 Not Modified responses.

When the user sends a 204 response with a Transfer-Encoding: chunked
header, suppress sending the zero chunk and force the connection to
close.
  • Loading branch information
bnoordhuis committed Jan 24, 2013
1 parent 0774798 commit 4a7a98f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 28 deletions.
18 changes: 11 additions & 7 deletions lib/http.js
Expand Up @@ -564,18 +564,22 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
state.messageHeader += 'Date: ' + utcDate() + CRLF;
}

// Force the connection to close when the response is a 304 Not Modified
// and the user has set a "Transfer-Encoding: chunked" header.
// Force the connection to close when the response is a 204 No Content or
// a 304 Not Modified and the user has set a "Transfer-Encoding: chunked"
// header.
//
// RFC 2616 mandates that 304 responses MUST NOT have a body but node.js
// used to send out a zero chunk anyway to accommodate clients that don't
// have special handling for 304 responses.
// RFC 2616 mandates that 204 and 304 responses MUST NOT have a body but
// node.js used to send out a zero chunk anyway to accommodate clients
// that don't have special handling for those responses.
//
// It was pointed out that this might confuse reverse proxies to the point
// of creating security liabilities, so suppress the zero chunk and force
// the connection to close.
if (this.statusCode === 304 && this.chunkedEncoding === true) {
debug('304 response should not use chunked encoding, closing connection.');
var statusCode = this.statusCode;
if ((statusCode == 204 || statusCode === 304) &&
this.chunkedEncoding === true) {
debug(statusCode + ' response should not use chunked encoding,' +
' closing connection.');
this.chunkedEncoding = false;
this.shouldKeepAlive = false;
}
Expand Down
50 changes: 29 additions & 21 deletions test/simple/test-http-chunked-304.js
Expand Up @@ -24,32 +24,40 @@ var assert = require('assert');
var http = require('http');
var net = require('net');

// RFC 2616, section 10.3.5:
// RFC 2616, section 10.2.5:
//
// The 304 response MUST NOT contain a message-body, and thus is always
// The 204 response MUST NOT contain a message-body, and thus is always
// terminated by the first empty line after the header fields.
//
// Verify that no empty chunk is sent when the user explicitly sets
// a Transfer-Encoding header.
var server = http.createServer(function(req, res) {
res.writeHead(304, { 'Transfer-Encoding': 'chunked' });
res.end();
server.close();
// Likewise for 304 responses. Verify that no empty chunk is sent when
// the user explicitly sets a Transfer-Encoding header.

test(204, function() {
test(304);
});

server.listen(common.PORT, function() {
var conn = net.createConnection(common.PORT, function() {
conn.write('GET / HTTP/1.1\r\n\r\n');
function test(statusCode, next) {
var server = http.createServer(function(req, res) {
res.writeHead(statusCode, { 'Transfer-Encoding': 'chunked' });
res.end();
server.close();
});

var resp = '';
conn.setEncoding('utf8');
conn.on('data', function(data) {
resp += data;
});
server.listen(common.PORT, function() {
var conn = net.createConnection(common.PORT, function() {
conn.write('GET / HTTP/1.1\r\n\r\n');

conn.on('end', common.mustCall(function() {
assert.equal(/^Connection: close\r\n$/m.test(resp), true);
assert.equal(/^0\r\n$/m.test(resp), false);
}));
var resp = '';
conn.setEncoding('utf8');
conn.on('data', function(data) {
resp += data;
});

conn.on('end', common.mustCall(function() {
assert.equal(/^Connection: close\r\n$/m.test(resp), true);
assert.equal(/^0\r\n$/m.test(resp), false);
if (next) process.nextTick(next);
}));
});
});
});
}

0 comments on commit 4a7a98f

Please sign in to comment.