Skip to content

Commit 1e425e3

Browse files
mnotisaacs
authored andcommitted
Generate Date headers on responses when not already present.
1 parent d653732 commit 1e425e3

File tree

5 files changed

+69
-2
lines changed

5 files changed

+69
-2
lines changed

doc/api/http.markdown

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,13 @@ or
344344

345345
response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
346346

347+
### response.sendDate
348+
349+
When true, the Date header will be automatically generated and sent in
350+
the response if it is not already present in the headers. Defaults to true.
351+
352+
This should only be disabled for testing; HTTP requires the Date header
353+
in responses.
347354

348355
### response.getHeader(name)
349356

lib/http.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,22 @@ var transferEncodingExpression = /Transfer-Encoding/i;
226226
var closeExpression = /close/i;
227227
var chunkExpression = /chunk/i;
228228
var contentLengthExpression = /Content-Length/i;
229+
var dateExpression = /Date/i;
229230
var expectExpression = /Expect/i;
230231
var continueExpression = /100-continue/i;
231232

233+
var dateCache;
234+
function utcDate() {
235+
if (! dateCache) {
236+
var d = new Date();
237+
dateCache = d.toUTCString();
238+
setTimeout(function () {
239+
dateCache = undefined;
240+
}, 1000 - d.getMilliseconds());
241+
}
242+
return dateCache;
243+
}
244+
232245

233246
/* Abstract base class for ServerRequest and ClientResponse. */
234247
function IncomingMessage(socket) {
@@ -383,6 +396,7 @@ function OutgoingMessage() {
383396
this.chunkedEncoding = false;
384397
this.shouldKeepAlive = true;
385398
this.useChunkedEncodingByDefault = true;
399+
this.sendDate = false;
386400

387401
this._hasBody = true;
388402
this._trailer = '';
@@ -473,6 +487,7 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
473487
var sentConnectionHeader = false;
474488
var sentContentLengthHeader = false;
475489
var sentTransferEncodingHeader = false;
490+
var sentDateHeader = false;
476491
var sentExpect = false;
477492

478493
// firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n'
@@ -498,7 +513,8 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
498513

499514
} else if (contentLengthExpression.test(field)) {
500515
sentContentLengthHeader = true;
501-
516+
} else if (dateExpression.test(field)) {
517+
sentDateHeader = true;
502518
} else if (expectExpression.test(field)) {
503519
sentExpect = true;
504520
}
@@ -529,6 +545,11 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
529545
}
530546
}
531547

548+
// Date header
549+
if (this.sendDate == true && sentDateHeader == false) {
550+
messageHeader += "Date: " + utcDate() + CRLF;
551+
}
552+
532553
// keep-alive logic
533554
if (sentConnectionHeader === false) {
534555
if (this.shouldKeepAlive &&
@@ -816,6 +837,8 @@ function ServerResponse(req) {
816837

817838
if (req.method === 'HEAD') this._hasBody = false;
818839

840+
this.sendDate = true;
841+
819842
if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
820843
this.useChunkedEncodingByDefault = false;
821844
this.shouldKeepAlive = false;

test/simple/test-http-1.0.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ function test(handler, request_generator, response_validator) {
104104
assert.equal('1.0', req.httpVersion);
105105
assert.equal(1, req.httpVersionMajor);
106106
assert.equal(0, req.httpVersionMinor);
107+
res.sendDate = false;
107108
res.writeHead(200, {'Content-Type': 'text/plain'});
108109
res.write('Hello, '); res._send('');
109110
res.write('world!'); res._send('');
@@ -140,6 +141,7 @@ function test(handler, request_generator, response_validator) {
140141
assert.equal('1.1', req.httpVersion);
141142
assert.equal(1, req.httpVersionMajor);
142143
assert.equal(1, req.httpVersionMinor);
144+
res.sendDate = false;
143145
res.writeHead(200, {'Content-Type': 'text/plain'});
144146
res.write('Hello, '); res._send('');
145147
res.write('world!'); res._send('');

test/simple/test-http-date-header.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
var common = require("../common");
2+
var assert = require('assert');
3+
var http = require("http");
4+
5+
var testResBody = "other stuff!\n";
6+
7+
var server = http.createServer(function(req, res) {
8+
assert.ok(! ("date" in req.headers),
9+
"Request headers contained a Date."
10+
);
11+
res.writeHead(200, {
12+
'Content-Type' : 'text/plain',
13+
});
14+
res.end(testResBody);
15+
});
16+
server.listen(common.PORT);
17+
18+
19+
server.addListener("listening", function() {
20+
var options = {
21+
port: common.PORT,
22+
path: "/",
23+
method: "GET"
24+
}
25+
var req = http.request(options, function (res) {
26+
assert.ok("date" in res.headers,
27+
"Response headers didn't contain a Date."
28+
);
29+
res.addListener('end', function () {
30+
server.close();
31+
process.exit();
32+
});
33+
});
34+
req.end();
35+
});

test/simple/test-http-max-headers-count.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ server.listen(common.PORT, function() {
5656
var maxAndExpected = [ // for client
5757
[20, 20],
5858
[1200, 1200],
59-
[0, N + 2], // Connection and Transfer-Encoding
59+
[0, N + 3], // Connection, Date and Transfer-Encoding
6060
];
6161
doRequest();
6262

0 commit comments

Comments
 (0)