Skip to content

HTTP/2 server compatibility API ignores sendDate  #34841

Closed
@pimterry

Description

@pimterry
  • Version: 10.21.0, 12.18.3, 14.8.0
  • Platform: Linux
  • Subsystem: HTTP/2

What steps will reproduce the bug?

Run this:

const http = require("http");
const http2 = require("http2");

const h2Server = http2.createServer((req, res) => {
    res.sendDate = false;
    res.writeHead(200);
});

h2Server.listen(9001, () => {
    const client = http2.connect('http://localhost:9001');
    const req = client.request();
    req.on('response', (headers) => {
        console.log('Received H2 headers', headers);
    });
});

const h1Server = http.createServer((req, res) => {
    res.sendDate = false;
    res.writeHead(200).end();
});

h1Server.listen(9002, () => {
    http.request('http://localhost:9002', (res) => {
        console.log("Received H1 headers", res.headers);
    }).end();
});

It prints:

Received H2 headers [Object: null prototype] {
  ':status': 200,
  date: 'Wed, 19 Aug 2020 16:33:29 GMT'
}
Received H1 headers { connection: 'close', 'transfer-encoding': 'chunked' }

How often does it reproduce? Is there a required condition?

Always reproduces.

What is the expected behavior?

When response.sendDate is set to false, no date header should be included in the response.

What do you see instead?

This works fine for HTTP/1 servers, but as visible in the output above, HTTP/2 servers send the date header in the response regardless.

This is inconsistent with HTTP/1, and this behaviour is explicitly documented as working for the HTTP/2 API too.

For context: I'm using these HTTP/2 APIs to mock services and test HTTP/2 client behaviour, so I'd like to be able to fully control the HTTP headers that are returned in the response. With HTTP/1 that's easy to do, by using sendDate or by manually removing headers e.g. with res.removeHeader('content-length'). That's explicitly supported by the code, which watches for removed default headers and ensures they're not reinserted:

node/lib/_http_outgoing.js

Lines 604 to 631 in 849d9e7

OutgoingMessage.prototype.removeHeader = function removeHeader(name) {
validateString(name, 'name');
if (this._header) {
throw new ERR_HTTP_HEADERS_SENT('remove');
}
const key = name.toLowerCase();
switch (key) {
case 'connection':
this._removedConnection = true;
break;
case 'content-length':
this._removedContLen = true;
break;
case 'transfer-encoding':
this._removedTE = true;
break;
case 'date':
this.sendDate = false;
break;
}
if (this[kOutHeaders] !== null) {
delete this[kOutHeaders][key];
}
};

In HTTP/2 the Date header is the only remaining default header (ignoring pseudo headers), but neither sendDate = false nor removeHeader('date') do anything, so there doesn't seem to be any way to disable it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions