From 86996c5838f7ee38e3cc96b3c65c8ca6965a36a2 Mon Sep 17 00:00:00 2001 From: Brian White Date: Sun, 5 Mar 2017 21:11:32 -0500 Subject: [PATCH 1/4] doc: deprecate private http properties PR-URL: https://github.com/nodejs/node/pull/10941 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum --- doc/api/deprecations.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 786a6453161b9b..8de386118af960 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -556,6 +556,32 @@ The `NODE_REPL_MODE` environment variable is used to set the underlying `replMode` of an interactive `node` session. Its default value, `magic`, is similarly deprecated in favor of `sloppy`. + +### DEP0066: outgoingMessage.\_headers, outgoingMessage.\_headerNames + +Type: Documentation-only + +The `http` module `outgoingMessage._headers` and `outgoingMessage._headerNames` +properties have been deprecated. Please instead use one of the public methods +(e.g. `outgoingMessage.getHeader()`, `outgoingMessage.getHeaders()`, +`outgoingMessage.getHeaderNames()`, `outgoingMessage.hasHeader()`, +`outgoingMessage.removeHeader()`, `outgoingMessage.setHeader()`) for working +with outgoing headers. + +*Note*: `outgoingMessage._headers` and `outgoingMessage._headerNames` were never +documented as officially supported properties. + + +### DEP0067: OutgoingMessage.prototype.\_renderHeaders + +Type: Documentation-only + +The `http` module `OutgoingMessage.prototype._renderHeaders()` API has been +deprecated. + +*Note*: `OutgoingMessage.prototype._renderHeaders` was never documented as +an officially supported API. + [alloc]: buffer.html#buffer_class_method_buffer_alloc_size_fill_encoding [alloc_unsafe_size]: buffer.html#buffer_class_method_buffer_allocunsafe_size [`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size From 940b5303bef7aee9b24214c62e4b6f182f23f82a Mon Sep 17 00:00:00 2001 From: Brian White Date: Sun, 5 Mar 2017 21:13:09 -0500 Subject: [PATCH 2/4] http: use Symbol for outgoing headers PR-URL: https://github.com/nodejs/node/pull/10941 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum --- lib/_http_client.js | 5 +++-- lib/_http_outgoing.js | 26 ++++++++++++++------------ lib/_http_server.js | 5 +++-- lib/internal/http.js | 5 +++++ node.gyp | 1 + 5 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 lib/internal/http.js diff --git a/lib/_http_client.js b/lib/_http_client.js index e8285fe81012c7..babe772281909f 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -14,6 +14,7 @@ const OutgoingMessage = require('_http_outgoing').OutgoingMessage; const Agent = require('_http_agent'); const Buffer = require('buffer').Buffer; const urlToOptions = require('internal/url').urlToOptions; +const outHeadersKey = require('internal/http').outHeadersKey; // The actual list of disallowed characters in regexp form is more like: // /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ @@ -182,7 +183,7 @@ function ClientRequest(options, cb) { 'client'); } self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n', - self._headers); + self[outHeadersKey]); } this._ended = false; @@ -278,7 +279,7 @@ ClientRequest.prototype._implicitHeader = function _implicitHeader() { throw new Error('Can\'t render headers after they are sent to the client'); } this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n', - this._headers); + this[outHeadersKey]); }; ClientRequest.prototype.abort = function abort() { diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index a095b64230e98e..6ada7bd99f285b 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -9,6 +9,8 @@ const Buffer = require('buffer').Buffer; const common = require('_http_common'); const checkIsHttpToken = common._checkIsHttpToken; const checkInvalidHeaderChar = common._checkInvalidHeaderChar; +const outHeadersKey = require('internal/http').outHeadersKey; +const StorageObject = require('internal/querystring').StorageObject; const CRLF = common.CRLF; const debug = common.debug; @@ -74,7 +76,7 @@ function OutgoingMessage() { this.socket = null; this.connection = null; this._header = null; - this._headers = null; + this[outHeadersKey] = null; this._onPendingData = null; } @@ -201,7 +203,7 @@ function _storeHeader(firstLine, headers) { var value; var i; var j; - if (headers === this._headers) { + if (headers === this[outHeadersKey]) { for (key in headers) { var entry = headers[key]; field = entry[0]; @@ -393,11 +395,11 @@ function validateHeader(msg, name, value) { OutgoingMessage.prototype.setHeader = function setHeader(name, value) { validateHeader(this, name, value); - if (!this._headers) - this._headers = {}; + if (!this[outHeadersKey]) + this[outHeadersKey] = {}; const key = name.toLowerCase(); - this._headers[key] = [name, value]; + this[outHeadersKey][key] = [name, value]; switch (key.length) { case 10: @@ -421,9 +423,9 @@ OutgoingMessage.prototype.getHeader = function getHeader(name) { throw new TypeError('"name" argument must be a string'); } - if (!this._headers) return; + if (!this[outHeadersKey]) return; - var entry = this._headers[name.toLowerCase()]; + var entry = this[outHeadersKey][name.toLowerCase()]; if (!entry) return; return entry[1]; @@ -432,13 +434,13 @@ OutgoingMessage.prototype.getHeader = function getHeader(name) { // Returns an array of the names of the current outgoing headers. OutgoingMessage.prototype.getHeaderNames = function getHeaderNames() { - return (this._headers ? Object.keys(this._headers) : []); + return (this[outHeadersKey] ? Object.keys(this[outHeadersKey]) : []); }; // Returns a shallow copy of the current outgoing headers. OutgoingMessage.prototype.getHeaders = function getHeaders() { - const headers = this._headers; + const headers = this[outHeadersKey]; const ret = new OutgoingHeaders(); if (headers) { const keys = Object.keys(headers); @@ -457,7 +459,7 @@ OutgoingMessage.prototype.hasHeader = function hasHeader(name) { throw new TypeError('"name" argument must be a string'); } - return !!(this._headers && this._headers[name.toLowerCase()]); + return !!(this[outHeadersKey] && this[outHeadersKey][name.toLowerCase()]); }; @@ -491,8 +493,8 @@ OutgoingMessage.prototype.removeHeader = function removeHeader(name) { break; } - if (this._headers) { - delete this._headers[key]; + if (this[outHeadersKey]) { + delete this[outHeadersKey][key]; } }; diff --git a/lib/_http_server.js b/lib/_http_server.js index 082920839459e9..32da9cfe95ed69 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -13,6 +13,7 @@ const continueExpression = common.continueExpression; const chunkExpression = common.chunkExpression; const httpSocketSetup = common.httpSocketSetup; const OutgoingMessage = require('_http_outgoing').OutgoingMessage; +const outHeadersKey = require('internal/http').outHeadersKey; const STATUS_CODES = exports.STATUS_CODES = { 100: 'Continue', @@ -179,7 +180,7 @@ function writeHead(statusCode, reason, obj) { this.statusCode = statusCode; var headers; - if (this._headers) { + if (this[outHeadersKey]) { // Slow-case: when progressive API and header fields are passed. var k; if (obj) { @@ -196,7 +197,7 @@ function writeHead(statusCode, reason, obj) { } } // only progressive api is used - headers = this._headers; + headers = this[outHeadersKey]; } else { // only writeHead() called headers = obj; diff --git a/lib/internal/http.js b/lib/internal/http.js new file mode 100644 index 00000000000000..1ba68a41a5692b --- /dev/null +++ b/lib/internal/http.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + outHeadersKey: Symbol('outHeadersKey') +}; diff --git a/node.gyp b/node.gyp index 673a1d10effaa8..637a1934287841 100644 --- a/node.gyp +++ b/node.gyp @@ -85,6 +85,7 @@ 'lib/internal/errors.js', 'lib/internal/freelist.js', 'lib/internal/fs.js', + 'lib/internal/http.js', 'lib/internal/linkedlist.js', 'lib/internal/net.js', 'lib/internal/module.js', From b377034359aa07f2ba83a5a0c9f859418cb80e39 Mon Sep 17 00:00:00 2001 From: Brian White Date: Sun, 5 Mar 2017 21:15:15 -0500 Subject: [PATCH 3/4] http: support old private properties and function PR-URL: https://github.com/nodejs/node/pull/10941 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum --- lib/_http_outgoing.js | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 6ada7bd99f285b..51ded1eae6e88b 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -83,6 +83,75 @@ function OutgoingMessage() { util.inherits(OutgoingMessage, Stream); +Object.defineProperty(OutgoingMessage.prototype, '_headers', { + get: function() { + return this.getHeaders(); + }, + set: function(val) { + if (val == null) { + this[outHeadersKey] = null; + } else if (typeof val === 'object') { + const headers = this[outHeadersKey] = {}; + const keys = Object.keys(val); + for (var i = 0; i < keys.length; ++i) { + const name = keys[i]; + headers[name.toLowerCase()] = [name, val[name]]; + } + } + } +}); + +Object.defineProperty(OutgoingMessage.prototype, '_headerNames', { + get: function() { + const headers = this[outHeadersKey]; + if (headers) { + const out = new StorageObject(); + const keys = Object.keys(headers); + for (var i = 0; i < keys.length; ++i) { + const key = keys[i]; + const val = headers[key][0]; + out[key] = val; + } + return out; + } else { + return headers; + } + }, + set: function(val) { + if (typeof val === 'object' && val !== null) { + const headers = this[outHeadersKey]; + if (!headers) + return; + const keys = Object.keys(val); + for (var i = 0; i < keys.length; ++i) { + const header = headers[keys[i]]; + if (header) + header[0] = val[keys[i]]; + } + } + } +}); + + +OutgoingMessage.prototype._renderHeaders = function _renderHeaders() { + if (this._header) { + throw new Error('Can\'t render headers after they are sent to the client'); + } + + var headersMap = this[outHeadersKey]; + if (!headersMap) return {}; + + var headers = {}; + var keys = Object.keys(headersMap); + + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + headers[headersMap[key][0]] = headersMap[key][1]; + } + return headers; +}; + + exports.OutgoingMessage = OutgoingMessage; From 8243ca0e0e87b3e114d9ddf2843d1272bc56b053 Mon Sep 17 00:00:00 2001 From: Brian White Date: Mon, 20 Feb 2017 17:00:14 -0500 Subject: [PATCH 4/4] http: reuse existing StorageObject PR-URL: https://github.com/nodejs/node/pull/10941 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum --- lib/_http_outgoing.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 51ded1eae6e88b..373476a3c43d52 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -20,10 +20,6 @@ var RE_FIELDS = new RegExp('^(?:Connection|Transfer-Encoding|Content-Length|' + var RE_CONN_VALUES = /(?:^|\W)close|upgrade(?:$|\W)/ig; var RE_TE_CHUNKED = common.chunkExpression; -// Used to store headers returned by getHeaders() -function OutgoingHeaders() {} -OutgoingHeaders.prototype = Object.create(null); - var dateCache; function utcDate() { if (!dateCache) { @@ -510,7 +506,7 @@ OutgoingMessage.prototype.getHeaderNames = function getHeaderNames() { // Returns a shallow copy of the current outgoing headers. OutgoingMessage.prototype.getHeaders = function getHeaders() { const headers = this[outHeadersKey]; - const ret = new OutgoingHeaders(); + const ret = new StorageObject(); if (headers) { const keys = Object.keys(headers); for (var i = 0; i < keys.length; ++i) {