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

Trailers part deux #312

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/api.markdown
Expand Up @@ -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:
Expand Down Expand Up @@ -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'`.
Expand Down
34 changes: 24 additions & 10 deletions lib/http.js 100644 → 100755
Expand Up @@ -61,6 +61,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;
Expand Down Expand Up @@ -102,6 +104,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");
Expand Down Expand Up @@ -184,7 +190,9 @@ function IncomingMessage (socket) {
this.connection = socket;

this.httpVersion = null;
this.complete = false;
this.headers = {};
this.trailers = {};

// request (server) only
this.url = "";
Expand Down Expand Up @@ -224,13 +232,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;

Expand All @@ -241,25 +255,25 @@ 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;


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;
}
Expand Down
19 changes: 19 additions & 0 deletions test/simple/test-http-set-trailers.js
Expand Up @@ -71,5 +71,24 @@ server.addListener("listening", function() {
}
}
});
});

// 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();
}
});
});
});