From e655a437b3fde33151eab3606f6d3a06d5b8e681 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sun, 27 Sep 2015 11:55:47 -0700 Subject: [PATCH] http: do not allow multiple instances of certain response headers Response headers such as ETag and Last-Modified do not permit multiple instances, and therefore the comma-separated syntax is not allowed. When multiple values for these headers are specified, use only the first instance. Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Ben Noordhuis PR-URL: https://github.com/nodejs/node/pull/3090 --- lib/_http_incoming.js | 6 +++ .../test-http-response-multiheaders.js | 54 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 test/parallel/test-http-response-multiheaders.js diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js index e16f198dba71bd..5377c84d5d3c7e 100644 --- a/lib/_http_incoming.js +++ b/lib/_http_incoming.js @@ -152,6 +152,12 @@ IncomingMessage.prototype._addHeaderLine = function(field, value, dest) { case 'from': case 'location': case 'max-forwards': + case 'retry-after': + case 'etag': + case 'last-modified': + case 'server': + case 'age': + case 'expires': // drop duplicates if (dest[field] === undefined) dest[field] = value; diff --git a/test/parallel/test-http-response-multiheaders.js b/test/parallel/test-http-response-multiheaders.js new file mode 100644 index 00000000000000..da6cd73a38ffaa --- /dev/null +++ b/test/parallel/test-http-response-multiheaders.js @@ -0,0 +1,54 @@ +'use strict'; + +const common = require('../common'); +const http = require('http'); +const assert = require('assert'); + +// Test that certain response header fields do not repeat +const norepeat = [ + 'retry-after', + 'etag', + 'last-modified', + 'server', + 'age', + 'expires' +]; + +const server = http.createServer(function(req, res) { + var num = req.headers['x-num']; + if (num == 1) { + for (let name of norepeat) { + res.setHeader(name, ['A', 'B']); + } + res.setHeader('X-A', ['A', 'B']); + } else if (num == 2) { + let headers = {}; + for (let name of norepeat) { + headers[name] = ['A', 'B']; + } + headers['X-A'] = ['A', 'B']; + res.writeHead(200, headers); + } + res.end('ok'); +}); + +server.listen(common.PORT, common.mustCall(function() { + for (let n = 1; n <= 2 ; n++) { + // this runs twice, the first time, the server will use + // setHeader, the second time it uses writeHead. The + // result on the client side should be the same in + // either case -- only the first instance of the header + // value should be reported for the header fields listed + // in the norepeat array. + http.get( + {port:common.PORT, headers:{'x-num': n}}, + common.mustCall(function(res) { + if (n == 2) server.close(); + for (let name of norepeat) { + assert.equal(res.headers[name], 'A'); + } + assert.equal(res.headers['x-a'], 'A, B'); + }) + ); + } +}));