http: expose headers on an http.ClientRequest "information" event

1xx intermediate status responses are allowed to have headers; so
expose the "httpVersion", "httpVersionMajor", "httpVersionMinor",
"headers", "rawHeaders", and "statusMessage" properties on this
event.

PR-URL: https://github.com/nodejs/node/pull/28459
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Austin Wright 2019-06-27 16:10:55 -07:00 committed by Rich Trott
parent 2111207f44
commit d5737a8537
3 changed files with 83 additions and 3 deletions

View File

@ -421,10 +421,18 @@ added: v10.0.0
--> -->
* `info` {Object} * `info` {Object}
* `httpVersion` {string}
* `httpVersionMajor` {integer}
* `httpVersionMinor` {integer}
* `statusCode` {integer} * `statusCode` {integer}
* `statusMessage` {string}
* `headers` {Object}
* `rawHeaders` {string[]}
Emitted when the server sends a 1xx response (excluding 101 Upgrade). The Emitted when the server sends a 1xx intermediate response (excluding 101
listeners of this event will receive an object containing the status code. Upgrade). The listeners of this event will receive an object containing the
HTTP version, status code, status message, key-value headers object,
and array with the raw header names followed by their respective values.
```js ```js
const http = require('http'); const http = require('http');

View File

@ -549,7 +549,15 @@ function parserOnIncomingClient(res, shouldKeepAlive) {
req.emit('continue'); req.emit('continue');
} }
// Send information events to all 1xx responses except 101 Upgrade. // Send information events to all 1xx responses except 101 Upgrade.
req.emit('information', { statusCode: res.statusCode }); req.emit('information', {
statusCode: res.statusCode,
statusMessage: res.statusMessage,
httpVersion: res.httpVersion,
httpVersionMajor: res.httpVersionMajor,
httpVersionMinor: res.httpVersionMinor,
headers: res.headers,
rawHeaders: res.rawHeaders
});
return 1; // Skip body but don't treat as Upgrade. return 1; // Skip body but don't treat as Upgrade.
} }

View File

@ -0,0 +1,64 @@
'use strict';
require('../common');
const assert = require('assert');
const http = require('http');
const Countdown = require('../common/countdown');
const test_res_body = 'other stuff!\n';
const countdown = new Countdown(2, () => server.close());
const server = http.createServer((req, res) => {
console.error('Server sending informational message #1...');
// These function calls may rewritten as necessary
// to call res.writeHead instead
res._writeRaw('HTTP/1.1 102 Processing\r\n');
res._writeRaw('Foo: Bar\r\n');
res._writeRaw('\r\n');
console.error('Server sending full response...');
res.writeHead(200, {
'Content-Type': 'text/plain',
'ABCD': '1'
});
res.end(test_res_body);
});
server.listen(0, function() {
const req = http.request({
port: this.address().port,
path: '/world'
});
req.end();
console.error('Client sending request...');
let body = '';
req.on('information', function(res) {
assert.strictEqual(res.httpVersion, '1.1');
assert.strictEqual(res.httpVersionMajor, 1);
assert.strictEqual(res.httpVersionMinor, 1);
assert.strictEqual(res.statusCode, 102,
`Received ${res.statusCode}, not 102.`);
assert.strictEqual(res.statusMessage, 'Processing',
`Received ${res.statusMessage}, not "Processing".`);
assert.strictEqual(res.headers.foo, 'Bar');
assert.strictEqual(res.rawHeaders[0], 'Foo');
assert.strictEqual(res.rawHeaders[1], 'Bar');
console.error('Client got 102 Processing...');
countdown.dec();
});
req.on('response', function(res) {
// Check that all 102 Processing received before full response received.
assert.strictEqual(countdown.remaining, 1);
assert.strictEqual(res.statusCode, 200,
`Final status code was ${res.statusCode}, not 200.`);
res.setEncoding('utf8');
res.on('data', function(chunk) { body += chunk; });
res.on('end', function() {
console.error('Got full response.');
assert.strictEqual(body, test_res_body);
assert.ok('abcd' in res.headers);
countdown.dec();
});
});
});