From 5200fabb63410e5cd38fa8321143ba6bacc34688 Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Mon, 8 Jan 2018 00:11:05 -0800 Subject: [PATCH 01/20] Process 100, 102-199 status codes according to specs. Relevant references: RFC7231 Section 6.2.1 RFC2518 RFC8297 This affects several modules downstream that use the http module, e.g., node-fetch, all of whom violate HTTP RFCs due to this module. As such, this could introduce a breaking change for downstream if HTTP standards were ignored in an ad-hoc fashion. 101 Upgrade is excluded due to its non-informational processing according to RFC7231, Section 6.2.2. --- lib/_http_client.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index ebfd809e21e0a0..eba6042218e9bd 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -447,10 +447,13 @@ function socketOnData(d) { socket.destroy(); } } else if (parser.incoming && parser.incoming.complete && - // When the status code is 100 (Continue), the server will + // When the status code is 100 (Continue), 102 (Processing), + // 103 (Early Hints), or 104-199 (Unassigned), the server will // send a final response after this client sends a request - // body. So, we must not free the parser. - parser.incoming.statusCode !== 100) { + // body. 101 (Switching Protocols) and all other status codes + // should be handled separately. So, we must not free the parser. + (parser.incoming.statusCode >= 200 || + parser.incoming.statusCode === 101)) { socket.removeListener('data', socketOnData); socket.removeListener('end', socketOnEnd); freeParser(parser, req, socket); @@ -486,8 +489,17 @@ function parserOnIncomingClient(res, shouldKeepAlive) { return 2; // Skip body and treat as Upgrade. } - if (res.statusCode === 100) { - // restart the parser, as this is a continue message. + // Responses to HEAD requests are crazy. + // HEAD responses aren't allowed to have an entity-body + // but *can* have a content-length which actually corresponds + // to the content-length of the entity-body had the request + // been a GET. + var isHeadResponse = req.method === 'HEAD'; + debug('AGENT isHeadResponse', isHeadResponse); + + var statusCode = res.statusCode; + if (statusCode < 200 && statusCode >= 100 && statusCode !== 101) { + // restart the parser, as this is an intermediate message. req.res = null; // Clear res so that we don't hit double-responses. req.emit('continue'); return 1; // Skip body but don't treat as Upgrade. From fba79a8a66396b20eb1ab2b70e650f2e9bb1d3f8 Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Mon, 8 Jan 2018 00:40:14 -0800 Subject: [PATCH 02/20] Cleaning up status code comment to be clearer. --- lib/_http_client.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index eba6042218e9bd..e75cb8d66dedd5 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -450,8 +450,9 @@ function socketOnData(d) { // When the status code is 100 (Continue), 102 (Processing), // 103 (Early Hints), or 104-199 (Unassigned), the server will // send a final response after this client sends a request - // body. 101 (Switching Protocols) and all other status codes - // should be handled separately. So, we must not free the parser. + // body, so we must not free the parser. + // 101 (Switching Protocols) and all other status codes + // should be processed normally. (parser.incoming.statusCode >= 200 || parser.incoming.statusCode === 101)) { socket.removeListener('data', socketOnData); From 58bb0ca93870bdf30f971c2f1c6efc9b5d662b9d Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Mon, 8 Jan 2018 00:54:17 -0800 Subject: [PATCH 03/20] Cleaning up code to reuse informational status check. Lint is clean. --- lib/_http_client.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index e75cb8d66dedd5..caa3e74ba1da54 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -447,20 +447,26 @@ function socketOnData(d) { socket.destroy(); } } else if (parser.incoming && parser.incoming.complete && - // When the status code is 100 (Continue), 102 (Processing), - // 103 (Early Hints), or 104-199 (Unassigned), the server will - // send a final response after this client sends a request - // body, so we must not free the parser. + // When the status code is informational (100, 102-199), + // the server will send a final response after this client + // sends a request body, so we must not free the parser. // 101 (Switching Protocols) and all other status codes // should be processed normally. - (parser.incoming.statusCode >= 200 || - parser.incoming.statusCode === 101)) { + !informational(parser.incoming.statusCode)) { socket.removeListener('data', socketOnData); socket.removeListener('end', socketOnEnd); freeParser(parser, req, socket); } } +// client +function informational(status) { + // 100 (Continue) RFC7231 Section 6.2.1 + // 102 (Processing) RFC2518 + // 103 (Early Hints) RFC8297 + // 104-199 (Unassigned) + return (status < 200 && status >= 100 && status !== 101); +} // client function parserOnIncomingClient(res, shouldKeepAlive) { @@ -498,8 +504,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) { var isHeadResponse = req.method === 'HEAD'; debug('AGENT isHeadResponse', isHeadResponse); - var statusCode = res.statusCode; - if (statusCode < 200 && statusCode >= 100 && statusCode !== 101) { + if (informational(res.statusCode)) { // restart the parser, as this is an intermediate message. req.res = null; // Clear res so that we don't hit double-responses. req.emit('continue'); From 79301fa19d0f9af18698ef21ae1b479a42b227ea Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Mon, 8 Jan 2018 00:58:05 -0800 Subject: [PATCH 04/20] Fine tuning comment change. --- lib/_http_client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index caa3e74ba1da54..9bb038d6e3bbce 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -505,7 +505,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) { debug('AGENT isHeadResponse', isHeadResponse); if (informational(res.statusCode)) { - // restart the parser, as this is an intermediate message. + // restart the parser, as this is a 1xx informational message. req.res = null; // Clear res so that we don't hit double-responses. req.emit('continue'); return 1; // Skip body but don't treat as Upgrade. From b2c81fc482e46b5f910eb49c3a9278579b844391 Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Mon, 8 Jan 2018 10:07:39 -0800 Subject: [PATCH 05/20] Renamed 'informational' function to be more explicit. --- lib/_http_client.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index 9bb038d6e3bbce..02aab19e2729ed 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -452,7 +452,7 @@ function socketOnData(d) { // sends a request body, so we must not free the parser. // 101 (Switching Protocols) and all other status codes // should be processed normally. - !informational(parser.incoming.statusCode)) { + !statusIsInformational(parser.incoming.statusCode)) { socket.removeListener('data', socketOnData); socket.removeListener('end', socketOnEnd); freeParser(parser, req, socket); @@ -460,7 +460,7 @@ function socketOnData(d) { } // client -function informational(status) { +function statusIsInformational(status) { // 100 (Continue) RFC7231 Section 6.2.1 // 102 (Processing) RFC2518 // 103 (Early Hints) RFC8297 @@ -504,7 +504,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) { var isHeadResponse = req.method === 'HEAD'; debug('AGENT isHeadResponse', isHeadResponse); - if (informational(res.statusCode)) { + if (statusIsInformational(res.statusCode)) { // restart the parser, as this is a 1xx informational message. req.res = null; // Clear res so that we don't hit double-responses. req.emit('continue'); From fd33e98a54c49bbabf74ed5faec6ff2e52e4ceef Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Sat, 3 Feb 2018 17:38:40 -0800 Subject: [PATCH 06/20] Firing event for information messages Must be distinct from `continue` event due to slightly different behavior/triggering rules from 102/103 status codes. For example, 103 is explicitly made to take headers for pre-processing while 100 status codes never include headers. --- lib/_http_client.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index 02aab19e2729ed..a55eac84cd984b 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -507,7 +507,11 @@ function parserOnIncomingClient(res, shouldKeepAlive) { if (statusIsInformational(res.statusCode)) { // restart the parser, as this is a 1xx informational message. req.res = null; // Clear res so that we don't hit double-responses. - req.emit('continue'); + if (res.statusCode === 100) { + req.emit('continue'); + } + req.emit('information', { headers: res.headers }); + return 1; // Skip body but don't treat as Upgrade. } From 2113f0af90ed5640ac50b53e586c93393adbfd2c Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Sat, 3 Feb 2018 17:42:42 -0800 Subject: [PATCH 07/20] Adding writeInformation to handle 1xx status codes `writeContinue` is highly specific to 100 status codes and sets state for further processing. For example, keep-alive behavior is changed by 100 responses. `writeContinue` also cannot set header values, needed by 103 responses (so far). --- lib/_http_server.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/_http_server.js b/lib/_http_server.js index 496ebf285c814e..7fb2192f90754a 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -180,10 +180,35 @@ ServerResponse.prototype.detachSocket = function detachSocket(socket) { }; ServerResponse.prototype.writeContinue = function writeContinue(cb) { - this._writeRaw(`HTTP/1.1 100 Continue${CRLF}${CRLF}`, 'ascii', cb); + this.writeInformation(100, 'Continue', null, cb); this._sent100 = true; }; +ServerResponse.prototype.writeInformation = writeInformation; +function writeInformation(statusCode, reason, obj, cb) { + statusCode |= 0; + + if (statusCode >= 200 || statusCode < 100 || statusCode === 101) { + throw new errors.RangeError('ERR_HTTP_INVALID_STATUS_CODE', statusCode); + } + + let headers = ''; + if (obj) { + var headerParts = []; + var keys = Object.keys(obj); + var k; + if (keys.length > 0) { + for (var i = 0; i < keys.length; i++) { + k = keys[i]; + headerParts[i] = k + ': ' + (obj[k] || '').replace(/\r|\n/g, ''); + } + headers = CRLF + headerParts.join(CRLF); + } + } + this._writeRaw(`HTTP/1.1 ${statusCode} ${reason}${headers}${CRLF}${CRLF}`, + 'ascii', cb); +} + ServerResponse.prototype._implicitHeader = function _implicitHeader() { this.writeHead(this.statusCode); }; From 65405c40184ce2cca3bec4d1a3c2536c92a24668 Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Sat, 3 Feb 2018 17:46:20 -0800 Subject: [PATCH 08/20] Adding 102 Processing test --- test/parallel/test-http-webdav-processing.js | 74 ++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 test/parallel/test-http-webdav-processing.js diff --git a/test/parallel/test-http-webdav-processing.js b/test/parallel/test-http-webdav-processing.js new file mode 100644 index 00000000000000..1de15de6278fb6 --- /dev/null +++ b/test/parallel/test-http-webdav-processing.js @@ -0,0 +1,74 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +require('../common'); +const assert = require('assert'); +const http = require('http'); + +const test_res_body = 'other stuff!\n'; +let got_processing = false; + + +const server = http.createServer((req, res) => { + console.error('Server sending informational message...'); + res.writeInformation(102, 'Processing'); + 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(payload) { + console.error('Client got 102 Processing...'); + assert.strictEqual(JSON.stringify(payload.headers), '{}', + '102 Processing contained headers'); + got_processing = true; + }); + + req.on('response', function(res) { + assert.strictEqual(got_processing, true, + 'Full response received before 102 Processing'); + assert.strictEqual(200, res.statusCode, + `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, 'Response body doesn\'t match.'); + assert.ok('abcd' in res.headers, 'Response headers missing.'); + server.close(); + process.exit(); + }); + }); +}); From ea72928a224cf64c22431953e157278d5e9d208b Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Sat, 3 Feb 2018 17:48:17 -0800 Subject: [PATCH 09/20] Renaming 102 status test --- ...p-webdav-processing.js => test-http-information-processing.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/parallel/{test-http-webdav-processing.js => test-http-information-processing.js} (100%) diff --git a/test/parallel/test-http-webdav-processing.js b/test/parallel/test-http-information-processing.js similarity index 100% rename from test/parallel/test-http-webdav-processing.js rename to test/parallel/test-http-information-processing.js From 29cae690327bad0cdea1eaf4fc1dee0384003bb7 Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Sat, 3 Feb 2018 18:49:12 -0800 Subject: [PATCH 10/20] Added test for 103 Early Hints Since 103 is affected by this patch, added test. 104-199 is not yet defined, so leaving behavior undefined with no explicit tests. --- .../test-http-information-earlyhints.js | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 test/parallel/test-http-information-earlyhints.js diff --git a/test/parallel/test-http-information-earlyhints.js b/test/parallel/test-http-information-earlyhints.js new file mode 100644 index 00000000000000..fd2b253261fdde --- /dev/null +++ b/test/parallel/test-http-information-earlyhints.js @@ -0,0 +1,77 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +require('../common'); +const assert = require('assert'); +const http = require('http'); + +const test_res_body = 'other stuff!\n'; +const test_hint_header_value = 'hinty hinty'; +let got_hint = false; + + +const server = http.createServer((req, res) => { + console.error('Server sending informational message...'); + res.writeInformation(103, 'Early Hints', { + 'X-Hinty': test_hint_header_value + }); + 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(payload) { + console.error('Client got 103 Early Hints...'); + assert.strictEqual(payload.headers['x-hinty'], test_hint_header_value, + '103 Early Hints missing header'); + got_hint = true; + }); + + req.on('response', function(res) { + assert.strictEqual(got_hint, true, + 'Full response received before 103 Get Hints'); + assert.strictEqual(200, res.statusCode, + `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, 'Response body doesn\'t match.'); + assert.ok('abcd' in res.headers, 'Response headers missing.'); + server.close(); + process.exit(); + }); + }); +}); From 5f4049cb0a0688723c1a874f932d2be34ceb6299 Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Sat, 3 Feb 2018 22:41:12 -0800 Subject: [PATCH 11/20] Making a record --- doc/api/http.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/doc/api/http.md b/doc/api/http.md index 46ea8511ffe6b8..de9f5c1c9cd22a 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -400,6 +400,16 @@ Emitted when the server sends a '100 Continue' HTTP response, usually because the request contained 'Expect: 100-continue'. This is an instruction that the client should send the request body. +### Event: 'information' + + +Emitted when the server sends a '102 Processing', '103 Early Hints', or +undefined HTTP response with a status code between 104 and 199. This event is +emitted with a 'headers' property, which can be used to retrieve early +response information as is the case with 103 status codes. + ### Event: 'response' + +* `statusCode` {number} +* `statusMessage` {string} +* `headers` {Object} + +Sends an informational response header (1xx status codes) to the request. The +status code is a 3-digit HTTP status code, like `103`. The last argument, +`headers`, are the response headers. Optionally one can give a human-readable +`statusMessage` as the second argument. + +Information responses are always followed by either additional information +responses or a more typical 2xx, 3xx, 4xx, or 5xx response. + +Example: + +```js +const body = …; +response.writeInformation(103, { + 'Link': '; rel=preload; as=style', + 'Link': '; rel=preload; as=script' +}); + +response.writeHead(200, { + 'Content-Length': Buffer.byteLength(body), + 'Content-Type': 'text/html', + 'Link': '; rel=preload; as=style', + 'Link': '; rel=preload; as=script' +}); +response.end(body); +``` + +This method may be called multiple times but must be called before +[`response.writeHead()`][], [`response.write()`][], or +[`response.end()`][] is called. + +If [`response.writeHead()`][], [`response.write()`][], or [`response.end()`][] +are called before calling this, an exception will be thrown stating that +headers have already been sent, mirroring the behavior where +[`response.write()`][] or [`response.end()`][] are called before +[`response.writeHead()`][]. + +Attempting to set a header field name or value that contains invalid characters +will result in a [`TypeError`][] being thrown. + ## Class: http.IncomingMessage -Emitted when the server sends a '102 Processing', '103 Early Hints', or -undefined HTTP response with a status code between 104 and 199. This event is -emitted with a 'headers' property, which can be used to retrieve early -response information as is the case with 103 status codes. +Emitted when the server sends a 1xx response (excluding 101 Upgrade). This +event is emitted with a object, which can be used to retrieve the status code. ### Event: 'response' -* `statusCode` {number} -* `statusMessage` {string} -* `headers` {Object} - -Sends an informational response header (1xx status codes) to the request. The -status code is a 3-digit HTTP status code, like `103`. The last argument, -`headers`, are the response headers. Optionally one can give a human-readable -`statusMessage` as the second argument. - -Information responses are always followed by either additional information -responses or a more typical 2xx, 3xx, 4xx, or 5xx response. - -Example: - -```js -const body = …; -response.writeInformation(103, { - 'Link': '; rel=preload; as=style', - 'Link': '; rel=preload; as=script' -}); - -response.writeHead(200, { - 'Content-Length': Buffer.byteLength(body), - 'Content-Type': 'text/html', - 'Link': '; rel=preload; as=style', - 'Link': '; rel=preload; as=script' -}); -response.end(body); -``` - -This method may be called multiple times but must be called before -[`response.writeHead()`][], [`response.write()`][], or -[`response.end()`][] is called. - -If [`response.writeHead()`][], [`response.write()`][], or [`response.end()`][] -are called before calling this, an exception will be thrown stating that -headers have already been sent, mirroring the behavior where -[`response.write()`][] or [`response.end()`][] are called before -[`response.writeHead()`][]. - -Attempting to set a header field name or value that contains invalid characters -will result in a [`TypeError`][] being thrown. +Sends a HTTP/1.1 102 Processing message to the client, indicating that +the request body should be sent. ## Class: http.IncomingMessage Emitted when the server sends a 1xx response (excluding 101 Upgrade). This @@ -1392,7 +1392,7 @@ will result in a [`TypeError`][] being thrown. ### response.writeProcessing() Sends a HTTP/1.1 102 Processing message to the client, indicating that diff --git a/lib/_http_server.js b/lib/_http_server.js index 7d07e347afd9af..40a844decab8fe 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -180,20 +180,14 @@ ServerResponse.prototype.detachSocket = function detachSocket(socket) { }; ServerResponse.prototype.writeContinue = function writeContinue(cb) { - this._writeInformation(100, 'Continue', cb); + this._writeRaw(`HTTP/1.1 100 Continue${CRLF}${CRLF}`, 'ascii', cb); this._sent100 = true; }; ServerResponse.prototype.writeProcessing = function writeProcessing(cb) { - this._writeInformation(102, 'Processing', cb); + this._writeRaw(`HTTP/1.1 102 Processing${CRLF}${CRLF}`, 'ascii', cb); }; -ServerResponse.prototype._writeInformation = _writeInformation; -function _writeInformation(statusCode, statusMessage, cb) { - this._writeRaw(`HTTP/1.1 ${statusCode} ${statusMessage}${CRLF}${CRLF}`, - 'ascii', cb); -} - ServerResponse.prototype._implicitHeader = function _implicitHeader() { this.writeHead(this.statusCode); }; diff --git a/test/parallel/test-http-information-processing.js b/test/parallel/test-http-information-processing.js index 30819ea4333536..2b7259c8039800 100644 --- a/test/parallel/test-http-information-processing.js +++ b/test/parallel/test-http-information-processing.js @@ -1,24 +1,3 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - 'use strict'; require('../common'); const assert = require('assert'); @@ -67,7 +46,6 @@ server.listen(0, function() { assert.strictEqual(body, test_res_body, 'Response body doesn\'t match.'); assert.ok('abcd' in res.headers, 'Response headers missing.'); server.close(); - process.exit(); }); }); }); From 0386a11d459cfa8ff7ccf2ec2277aeefb5ed2ce7 Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Sat, 10 Feb 2018 12:31:56 -0800 Subject: [PATCH 15/20] Updated docs to clarify and show usage --- doc/api/http.md | 26 +++++++++++++++++++++++++- doc/api/http2.md | 23 +++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/doc/api/http.md b/doc/api/http.md index 8b55f22e8f7c07..a194382ef451c2 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -406,7 +406,30 @@ added: REPLACEME --> Emitted when the server sends a 1xx response (excluding 101 Upgrade). This -event is emitted with a object, which can be used to retrieve the status code. +event is emitted with a callback containing an object with a status code. + +```js +const http = require('http'); + +const options = { + hostname: '127.0.0.1', + port: 8080, + path: '/length_request' +}; + +// make a request +const req = http.request(options); +req.end(); + +req.on('information', (res) => { + console.log('got information status prior to main response: ' + res.statusCode); +}); +``` + +101 Upgrade statuses do not fire this event due to their break from the +traditional HTTP request/response chain, such as web sockets, in-place TLS +upgrades, or HTTP 2.0. To be notified of 101 Upgrade notices, listen for the +[`'upgrade'`]() event instead. ### Event: 'response' + +Emitted when the server sends a 1xx response (excluding 101 Upgrade). This +event is emitted with a callback containing an object with a status code. + +```js +const http2 = require('http2'); +const client = http2.connect('https://localhost'); +const req = client.request({ ':path': '/' }); + +req.on('information', (res) => { + console.log('got information status prior to main response: ' + res.statusCode); +}); +``` + +101 Upgrade statuses are not used within HTTP 2.0 since this status was already +explicitly used to establish an HTTP 2.0 connection. If this event were fired +for 101 Upgrade statuses, it would do so (arguably uselessly) for each and +every HTTP 2.0 connection made by the client. + #### Event: 'push' - -Emitted when the server sends a 1xx response (excluding 101 Upgrade). This -event is emitted with a callback containing an object with a status code. - -```js -const http2 = require('http2'); -const client = http2.connect('https://localhost'); -const req = client.request({ ':path': '/' }); - -req.on('information', (res) => { - console.log('got information prior to main response: ' + res.statusCode); -}); -``` - -101 Upgrade statuses are not used within HTTP 2.0 since this status was already -explicitly used to establish an HTTP 2.0 connection. If this event were fired -for 101 Upgrade statuses, it would do so (arguably uselessly) for each and -every HTTP 2.0 connection made by the client. - #### Event: 'push'