Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Generate Date headers on responses when not already present.

  • Loading branch information...
mnot authored and isaacs committed Feb 14, 2012
1 parent d653732 commit 1e425e3fa774fefd3553ecaa6f0ac35f9b0a1355
@@ -344,6 +344,13 @@ or

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)

@@ -226,9 +226,22 @@ var transferEncodingExpression = /Transfer-Encoding/i;
var closeExpression = /close/i;
var chunkExpression = /chunk/i;
var contentLengthExpression = /Content-Length/i;
var dateExpression = /Date/i;
var expectExpression = /Expect/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;
}


This comment has been minimized.

Copy link
@tj

tj Feb 17, 2012

should this maybe be specific (or somehow tied to) server instances? so that on close the cyclic timeout stops

This comment has been minimized.

Copy link
@mnot

mnot Feb 17, 2012

Author

It's not really cyclic; if no responses are sent, there isn't a callback. So when a server stops, the timeout function will be called at most once.

Also, Date isn't really instance-specific...

This comment has been minimized.

Copy link
@tj

tj Feb 17, 2012

sure, cool that's the part I was worried about (just glanced at the code)

This comment has been minimized.

Copy link
@bobrik

bobrik Feb 17, 2012

When server stopped it's probably better to clearTimeout. Not a big deal, btw

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

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

// 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)) {
sentContentLengthHeader = true;

} else if (dateExpression.test(field)) {
sentDateHeader = true;
} else if (expectExpression.test(field)) {
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
if (sentConnectionHeader === false) {
if (this.shouldKeepAlive &&
@@ -816,6 +837,8 @@ function ServerResponse(req) {

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

this.sendDate = true;

if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
this.useChunkedEncodingByDefault = false;
this.shouldKeepAlive = false;
@@ -104,6 +104,7 @@ function test(handler, request_generator, response_validator) {
assert.equal('1.0', req.httpVersion);
assert.equal(1, req.httpVersionMajor);
assert.equal(0, req.httpVersionMinor);
res.sendDate = false;
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello, '); 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, req.httpVersionMajor);
assert.equal(1, req.httpVersionMinor);
res.sendDate = false;
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello, '); res._send('');
res.write('world!'); res._send('');
@@ -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();
});
@@ -56,7 +56,7 @@ server.listen(common.PORT, function() {
var maxAndExpected = [ // for client
[20, 20],
[1200, 1200],
[0, N + 2], // Connection and Transfer-Encoding
[0, N + 3], // Connection, Date and Transfer-Encoding
];
doRequest();

4 comments on commit 1e425e3

@s3u

This comment has been minimized.

Copy link

replied Feb 15, 2012

Finally! Thanks @mnot

@ry

This comment has been minimized.

Copy link

replied Feb 16, 2012

Now much does this slow down our hello-world benchmark?

@mnot

This comment has been minimized.

Copy link
Author

replied Feb 16, 2012

Last I checked, it was in the noise; the expensive part was the toUTCString(), and that's cached.

@rtomayko

This comment has been minimized.

Copy link

replied Feb 17, 2012

❤️

Please sign in to comment.
You can’t perform that action at this time.