Generate Date headers on responses when not already present.

This commit is contained in:
Mark Nottingham 2012-02-15 07:38:24 +11:00 committed by isaacs
parent d653732157
commit 1e425e3fa7
5 changed files with 69 additions and 2 deletions

View File

@ -344,6 +344,13 @@ or
response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]); response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
### response.sendDate
When true, the Date header will be automatically generated and sent in
the response if it is not already present in the headers. Defaults to true.
This should only be disabled for testing; HTTP requires the Date header
in responses.
### response.getHeader(name) ### response.getHeader(name)

View File

@ -226,9 +226,22 @@ var transferEncodingExpression = /Transfer-Encoding/i;
var closeExpression = /close/i; var closeExpression = /close/i;
var chunkExpression = /chunk/i; var chunkExpression = /chunk/i;
var contentLengthExpression = /Content-Length/i; var contentLengthExpression = /Content-Length/i;
var dateExpression = /Date/i;
var expectExpression = /Expect/i; var expectExpression = /Expect/i;
var continueExpression = /100-continue/i; var continueExpression = /100-continue/i;
var dateCache;
function utcDate() {
if (! dateCache) {
var d = new Date();
dateCache = d.toUTCString();
setTimeout(function () {
dateCache = undefined;
}, 1000 - d.getMilliseconds());
}
return dateCache;
}
/* Abstract base class for ServerRequest and ClientResponse. */ /* Abstract base class for ServerRequest and ClientResponse. */
function IncomingMessage(socket) { function IncomingMessage(socket) {
@ -383,6 +396,7 @@ function OutgoingMessage() {
this.chunkedEncoding = false; this.chunkedEncoding = false;
this.shouldKeepAlive = true; this.shouldKeepAlive = true;
this.useChunkedEncodingByDefault = true; this.useChunkedEncodingByDefault = true;
this.sendDate = false;
this._hasBody = true; this._hasBody = true;
this._trailer = ''; this._trailer = '';
@ -473,6 +487,7 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
var sentConnectionHeader = false; var sentConnectionHeader = false;
var sentContentLengthHeader = false; var sentContentLengthHeader = false;
var sentTransferEncodingHeader = false; var sentTransferEncodingHeader = false;
var sentDateHeader = false;
var sentExpect = false; var sentExpect = false;
// firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n' // 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) {
} else if (contentLengthExpression.test(field)) { } else if (contentLengthExpression.test(field)) {
sentContentLengthHeader = true; sentContentLengthHeader = true;
} else if (dateExpression.test(field)) {
sentDateHeader = true;
} else if (expectExpression.test(field)) { } else if (expectExpression.test(field)) {
sentExpect = true; sentExpect = true;
} }
@ -529,6 +545,11 @@ OutgoingMessage.prototype._storeHeader = function(firstLine, headers) {
} }
} }
// Date header
if (this.sendDate == true && sentDateHeader == false) {
messageHeader += "Date: " + utcDate() + CRLF;
}
// keep-alive logic // keep-alive logic
if (sentConnectionHeader === false) { if (sentConnectionHeader === false) {
if (this.shouldKeepAlive && if (this.shouldKeepAlive &&
@ -816,6 +837,8 @@ function ServerResponse(req) {
if (req.method === 'HEAD') this._hasBody = false; if (req.method === 'HEAD') this._hasBody = false;
this.sendDate = true;
if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) { if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
this.useChunkedEncodingByDefault = false; this.useChunkedEncodingByDefault = false;
this.shouldKeepAlive = false; this.shouldKeepAlive = false;

View File

@ -104,6 +104,7 @@ function test(handler, request_generator, response_validator) {
assert.equal('1.0', req.httpVersion); assert.equal('1.0', req.httpVersion);
assert.equal(1, req.httpVersionMajor); assert.equal(1, req.httpVersionMajor);
assert.equal(0, req.httpVersionMinor); assert.equal(0, req.httpVersionMinor);
res.sendDate = false;
res.writeHead(200, {'Content-Type': 'text/plain'}); res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello, '); res._send(''); res.write('Hello, '); res._send('');
res.write('world!'); res._send(''); res.write('world!'); res._send('');
@ -140,6 +141,7 @@ function test(handler, request_generator, response_validator) {
assert.equal('1.1', req.httpVersion); assert.equal('1.1', req.httpVersion);
assert.equal(1, req.httpVersionMajor); assert.equal(1, req.httpVersionMajor);
assert.equal(1, req.httpVersionMinor); assert.equal(1, req.httpVersionMinor);
res.sendDate = false;
res.writeHead(200, {'Content-Type': 'text/plain'}); res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello, '); res._send(''); res.write('Hello, '); res._send('');
res.write('world!'); res._send(''); res.write('world!'); res._send('');

View File

@ -0,0 +1,35 @@
var common = require("../common");
var assert = require('assert');
var http = require("http");
var testResBody = "other stuff!\n";
var server = http.createServer(function(req, res) {
assert.ok(! ("date" in req.headers),
"Request headers contained a Date."
);
res.writeHead(200, {
'Content-Type' : 'text/plain',
});
res.end(testResBody);
});
server.listen(common.PORT);
server.addListener("listening", function() {
var options = {
port: common.PORT,
path: "/",
method: "GET"
}
var req = http.request(options, function (res) {
assert.ok("date" in res.headers,
"Response headers didn't contain a Date."
);
res.addListener('end', function () {
server.close();
process.exit();
});
});
req.end();
});

View File

@ -56,7 +56,7 @@ server.listen(common.PORT, function() {
var maxAndExpected = [ // for client var maxAndExpected = [ // for client
[20, 20], [20, 20],
[1200, 1200], [1200, 1200],
[0, N + 2], // Connection and Transfer-Encoding [0, N + 3], // Connection, Date and Transfer-Encoding
]; ];
doRequest(); doRequest();