summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/_http_incoming.js20
-rw-r--r--test/parallel/test-http-incoming-matchKnownFields.js11
-rw-r--r--test/parallel/test-http-server-multiheaders2.js4
3 files changed, 21 insertions, 14 deletions
diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js
index 53419323f4..d838891790 100644
--- a/lib/_http_incoming.js
+++ b/lib/_http_incoming.js
@@ -194,6 +194,9 @@ function matchKnownFields(field) {
case 'Set-Cookie':
case 'set-cookie':
return '\u0001';
+ case 'Cookie':
+ case 'cookie':
+ return '\u0002cookie';
// The fields below are not used in _addHeaderLine(), but they are common
// headers where we can avoid toLowerCase() if the mixed or lower case
// versions match the first time through.
@@ -215,9 +218,6 @@ function matchKnownFields(field) {
case 'Content-Encoding':
case 'content-encoding':
return '\u0000content-encoding';
- case 'Cookie':
- case 'cookie':
- return '\u0000cookie';
case 'Origin':
case 'origin':
return '\u0000origin';
@@ -263,18 +263,20 @@ function matchKnownFields(field) {
//
// Per RFC2616, section 4.2 it is acceptable to join multiple instances of the
// same header with a ', ' if the header in question supports specification of
-// multiple values this way. If not, we declare the first instance the winner
-// and drop the second. Extended header fields (those beginning with 'x-') are
-// always joined.
+// multiple values this way. The one exception to this is the Cookie header,
+// which has multiple values joined with a '; ' instead. If a header's values
+// cannot be joined in either of these ways, we declare the first instance the
+// winner and drop the second. Extended header fields (those beginning with
+// 'x-') are always joined.
IncomingMessage.prototype._addHeaderLine = _addHeaderLine;
function _addHeaderLine(field, value, dest) {
field = matchKnownFields(field);
var flag = field.charCodeAt(0);
- if (flag === 0) {
+ if (flag === 0 || flag === 2) {
field = field.slice(1);
- // Make comma-separated list
+ // Make a delimited list
if (typeof dest[field] === 'string') {
- dest[field] += ', ' + value;
+ dest[field] += (flag === 0 ? ', ' : '; ') + value;
} else {
dest[field] = value;
}
diff --git a/test/parallel/test-http-incoming-matchKnownFields.js b/test/parallel/test-http-incoming-matchKnownFields.js
index 7411be4e84..f301b9169f 100644
--- a/test/parallel/test-http-incoming-matchKnownFields.js
+++ b/test/parallel/test-http-incoming-matchKnownFields.js
@@ -6,9 +6,10 @@ const IncomingMessage = require('http').IncomingMessage;
function checkDest(field, result, value) {
const dest = {};
- if (value) dest[field] = 'test';
const incomingMessage = new IncomingMessage(field);
// dest is changed by IncomingMessage._addHeaderLine
+ if (value)
+ incomingMessage._addHeaderLine(field, 'test', dest);
incomingMessage._addHeaderLine(field, value, dest);
assert.deepStrictEqual(dest, result);
}
@@ -49,7 +50,7 @@ checkDest('age', {age: 'test'}, 'value');
checkDest('Expires', {expires: undefined});
checkDest('expires', {expires: 'test'}, 'value');
checkDest('Set-Cookie', {'set-cookie': [undefined]});
-checkDest('set-cookie', {'set-cookie': [undefined]});
+checkDest('set-cookie', {'set-cookie': ['test', 'value']}, 'value');
checkDest('Transfer-Encoding', {'transfer-encoding': undefined});
checkDest('transfer-encoding', {'transfer-encoding': 'test, value'}, 'value');
checkDest('Date', {date: undefined});
@@ -64,8 +65,8 @@ checkDest('Vary', {vary: undefined});
checkDest('vary', {vary: 'test, value'}, 'value');
checkDest('Content-Encoding', {'content-encoding': undefined}, undefined);
checkDest('content-encoding', {'content-encoding': 'test, value'}, 'value');
-checkDest('Cookies', {cookies: undefined});
-checkDest('cookies', {cookies: 'test, value'}, 'value');
+checkDest('Cookie', {cookie: undefined});
+checkDest('cookie', {cookie: 'test; value'}, 'value');
checkDest('Origin', {origin: undefined});
checkDest('origin', {origin: 'test, value'}, 'value');
checkDest('Upgrade', {upgrade: undefined});
@@ -88,3 +89,5 @@ checkDest('X-Forwarded-Host', {'x-forwarded-host': undefined});
checkDest('x-forwarded-host', {'x-forwarded-host': 'test, value'}, 'value');
checkDest('X-Forwarded-Proto', {'x-forwarded-proto': undefined});
checkDest('x-forwarded-proto', {'x-forwarded-proto': 'test, value'}, 'value');
+checkDest('X-Foo', {'x-foo': undefined});
+checkDest('x-foo', {'x-foo': 'test, value'}, 'value');
diff --git a/test/parallel/test-http-server-multiheaders2.js b/test/parallel/test-http-server-multiheaders2.js
index 53e68e6f0d..febffe0523 100644
--- a/test/parallel/test-http-server-multiheaders2.js
+++ b/test/parallel/test-http-server-multiheaders2.js
@@ -54,8 +54,10 @@ const srv = http.createServer(function(req, res) {
'foo', 'header parsed incorrectly: ' + header);
});
multipleAllowed.forEach(function(header) {
+ const sep = (header.toLowerCase() === 'cookie' ? '; ' : ', ');
assert.strictEqual(req.headers[header.toLowerCase()],
- 'foo, bar', 'header parsed incorrectly: ' + header);
+ 'foo' + sep + 'bar',
+ 'header parsed incorrectly: ' + header);
});
res.writeHead(200, {'Content-Type': 'text/plain'});