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

Commit

Permalink
Browse files Browse the repository at this point in the history
Generate Date headers on responses when not already present.
  • Loading branch information
mnot authored and isaacs committed Feb 15, 2012
1 parent d653732 commit 1e425e3
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 2 deletions.
7 changes: 7 additions & 0 deletions doc/api/http.markdown
Expand Up @@ -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)

Expand Down
25 changes: 24 additions & 1 deletion lib/http.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -383,6 +396,7 @@ function OutgoingMessage() {
this.chunkedEncoding = false;
this.shouldKeepAlive = true;
this.useChunkedEncodingByDefault = true;
this.sendDate = false;

this._hasBody = true;
this._trailer = '';
Expand Down Expand Up @@ -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'
Expand All @@ -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;
}
Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions test/simple/test-http-1.0.js
Expand Up @@ -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('');
Expand Down Expand Up @@ -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('');
Expand Down
35 changes: 35 additions & 0 deletions test/simple/test-http-date-header.js
@@ -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();
});
2 changes: 1 addition & 1 deletion test/simple/test-http-max-headers-count.js
Expand Up @@ -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();

Expand Down

4 comments on commit 1e425e3

@s3u
Copy link

@s3u s3u commented on 1e425e3 Feb 15, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally! Thanks @mnot

@ry
Copy link

@ry ry commented on 1e425e3 Feb 16, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@mnot
Copy link
Author

@mnot mnot commented on 1e425e3 Feb 16, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@rtomayko
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Please sign in to comment.