0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00

Consume HTTP trailing headers

This commit is contained in:
Mark Nottingham 2010-09-29 19:38:48 +10:00 committed by Ryan Dahl
parent 43ddc04bb0
commit 1b24fc6678
3 changed files with 54 additions and 13 deletions

View File

@ -1791,6 +1791,10 @@ you can use the `require('querystring').parse` function, or pass
Read only.
### request.trailers
Read only; HTTP trailers (if present). Only populated after the 'end' event.
### request.httpVersion
The HTTP protocol version as a string. Read only. Examples:
@ -2093,6 +2097,10 @@ Also `response.httpVersionMajor` is the first integer and
The response headers object.
### response.trailers
The response trailers object. Only populated after the 'end' event.
### response.setEncoding(encoding=null)
Set the encoding for the response body. Either `'utf8'`, `'ascii'`, or `'base64'`.

34
lib/http.js Normal file → Executable file
View File

@ -60,6 +60,8 @@ var parsers = new FreeList('parsers', 1000, function () {
parser.onHeadersComplete = function (info) {
if (parser.field && (parser.value != undefined)) {
parser.incoming._addHeaderLine(parser.field, parser.value);
parser.field = null;
parser.value = null;
}
parser.incoming.httpVersionMajor = info.versionMajor;
@ -101,6 +103,10 @@ var parsers = new FreeList('parsers', 1000, function () {
};
parser.onMessageComplete = function () {
this.incoming.complete = true;
if (parser.field && (parser.value != undefined)) {
parser.incoming._addHeaderLine(parser.field, parser.value);
}
if (!parser.incoming.upgrade) {
// For upgraded connections, also emit this after parser.execute
parser.incoming.emit("end");
@ -183,7 +189,9 @@ function IncomingMessage (socket) {
this.connection = socket;
this.httpVersion = null;
this.complete = false;
this.headers = {};
this.trailers = {};
// request (server) only
this.url = "";
@ -223,13 +231,19 @@ IncomingMessage.prototype.resume = function () {
// and drop the second. Extended header fields (those beginning with 'x-') are
// always joined.
IncomingMessage.prototype._addHeaderLine = function (field, value) {
var dest;
if (this.complete) {
dest = this.trailers
} else {
dest = this.headers
}
switch (field) {
// Array headers:
case 'set-cookie':
if (field in this.headers) {
this.headers[field].push(value);
if (field in dest) {
dest[field].push(value);
} else {
this.headers[field] = [value];
dest[field] = [value];
}
break;
@ -240,10 +254,10 @@ IncomingMessage.prototype._addHeaderLine = function (field, value) {
case 'accept-language':
case 'connection':
case 'cookie':
if (field in this.headers) {
this.headers[field] += ', ' + value;
if (field in dest) {
dest[field] += ', ' + value;
} else {
this.headers[field] = value;
dest[field] = value;
}
break;
@ -251,14 +265,14 @@ IncomingMessage.prototype._addHeaderLine = function (field, value) {
default:
if (field.slice(0,2) == 'x-') {
// except for x-
if (field in this.headers) {
this.headers[field] += ', ' + value;
if (field in dest) {
dest[field] += ', ' + value;
} else {
this.headers[field] = value;
dest[field] = value;
}
} else {
// drop duplicates
if (!(field in this.headers)) this.headers[field] = value;
if (!(field in dest)) dest[field] = value;
}
break;
}

View File

@ -62,14 +62,33 @@ server.addListener("listening", function() {
outstanding_reqs--;
clearTimeout(tid);
assert.ok(
/0\r\nx-foo: bar\r\n\r\n$/.test(res_buffer),
/0\r\nx-foo: bar\r\n\r\n$/.test(res_buffer),
"No trailer in HTTP/1.1 response."
);
);
if (outstanding_reqs == 0) {
server.close();
process.exit();
}
}
});
});
// now, see if the client sees the trailers.
server.addListener('listening', function() {
var client = http.createClient(common.PORT);
var req = client.request("/hello", {});
req.end();
outstanding_reqs++;
req.addListener('response', function (res) {
res.addListener('end', function () {
// console.log(res.trailers);
assert.ok("x-foo" in res.trailers,
"Client doesn't see trailers.");
outstanding_reqs--;
if (outstanding_reqs == 0) {
server.close();
process.exit();
}
});
});
});