Permalink
Browse files

http: add new functions to OutgoingMessage

PR-URL: #10805
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
  • Loading branch information...
mscdex committed Jan 14, 2017
1 parent 52ddb41 commit 3e6f1032a4fdb8ca7fba02c7d2103fba68c0ee1f
Showing with 140 additions and 1 deletion.
  1. +60 −0 doc/api/http.md
  2. +35 −0 lib/_http_outgoing.js
  3. +45 −1 test/parallel/test-http-mutable-headers.js
View
@@ -934,6 +934,66 @@ Example:
var contentType = response.getHeader('content-type');
```
### response.getHeaderNames()
<!-- YAML
added: REPLACEME
-->
* Returns: {Array}
Returns an array containing the unique names of the current outgoing headers.
All header names are lowercase.
Example:
```js
response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);
var headerNames = response.getHeaderNames();
// headerNames === ['foo', 'set-cookie']
```
### response.getHeaders()
<!-- YAML
added: REPLACEME
-->
* Returns: {Object}
Returns a shallow copy of the current outgoing headers. Since a shallow copy
is used, array values may be mutated without additional calls to various
header-related http module methods. The keys of the returned object are the
header names and the values are the respective header values. All header names
are lowercase.
Example:
```js
response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);
var headers = response.getHeaders();
// headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] }
```
### response.hasHeader(name)
<!-- YAML
added: REPLACEME
-->
* `name` {String}
* Returns: {Boolean}
Returns `true` if the header identified by `name` is currently set in the
outgoing headers. Note that the header name matching is case-insensitive.
Example:
```js
var hasContentType = response.hasHeader('content-type');
```
### response.headersSent
<!-- YAML
added: v0.9.3
View
@@ -18,6 +18,10 @@ 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) {
@@ -426,6 +430,37 @@ 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) : []);
};
// Returns a shallow copy of the current outgoing headers.
OutgoingMessage.prototype.getHeaders = function getHeaders() {
const headers = this._headers;
const ret = new OutgoingHeaders();
if (headers) {
const keys = Object.keys(headers);
for (var i = 0; i < keys.length; ++i) {
const key = keys[i];
const val = headers[key][1];
ret[key] = val;
}
}
return ret;
};
OutgoingMessage.prototype.hasHeader = function hasHeader(name) {
if (typeof name !== 'string') {
throw new TypeError('"name" argument must be a string');
}
return !!(this._headers && this._headers[name.toLowerCase()]);
};
OutgoingMessage.prototype.removeHeader = function removeHeader(name) {
if (typeof name !== 'string') {
throw new TypeError('"name" argument must be a string');
@@ -21,6 +21,13 @@ const cookies = [
const s = http.createServer(common.mustCall((req, res) => {
switch (test) {
case 'headers':
// Check that header-related functions work before setting any headers
// eslint-disable-next-line no-restricted-properties
assert.deepEqual(res.getHeaders(), {});
assert.deepStrictEqual(res.getHeaderNames(), []);
assert.deepStrictEqual(res.hasHeader('Connection'), false);
assert.deepStrictEqual(res.getHeader('Connection'), undefined);
assert.throws(() => {
res.setHeader();
}, /^TypeError: Header name must be a valid HTTP Token \["undefined"\]$/);
@@ -34,15 +41,52 @@ const s = http.createServer(common.mustCall((req, res) => {
res.removeHeader();
}, /^TypeError: "name" argument must be a string$/);
const arrayValues = [1, 2, 3];
res.setHeader('x-test-header', 'testing');
res.setHeader('X-TEST-HEADER2', 'testing');
res.setHeader('set-cookie', cookies);
res.setHeader('x-test-array-header', [1, 2, 3]);
res.setHeader('x-test-array-header', arrayValues);
assert.strictEqual(res.getHeader('x-test-header'), 'testing');
assert.strictEqual(res.getHeader('x-test-header2'), 'testing');
const headersCopy = res.getHeaders();
// eslint-disable-next-line no-restricted-properties
assert.deepEqual(headersCopy, {
'x-test-header': 'testing',
'x-test-header2': 'testing',
'set-cookie': cookies,
'x-test-array-header': arrayValues
});
// eslint-disable-next-line no-restricted-properties
assert.deepEqual(headersCopy['set-cookie'], cookies);
assert.strictEqual(headersCopy['x-test-array-header'], arrayValues);
assert.deepStrictEqual(res.getHeaderNames(),
['x-test-header', 'x-test-header2',
'set-cookie', 'x-test-array-header']);
assert.strictEqual(res.hasHeader('x-test-header2'), true);
assert.strictEqual(res.hasHeader('X-TEST-HEADER2'), true);
assert.strictEqual(res.hasHeader('X-Test-Header2'), true);
assert.throws(() => {
res.hasHeader();
}, /^TypeError: "name" argument must be a string$/);
assert.throws(() => {
res.hasHeader(null);
}, /^TypeError: "name" argument must be a string$/);
assert.throws(() => {
res.hasHeader(true);
}, /^TypeError: "name" argument must be a string$/);
assert.throws(() => {
res.hasHeader({ toString: () => 'X-TEST-HEADER2' });
}, /^TypeError: "name" argument must be a string$/);
res.removeHeader('x-test-header2');
assert.strictEqual(res.hasHeader('x-test-header2'), false);
assert.strictEqual(res.hasHeader('X-TEST-HEADER2'), false);
assert.strictEqual(res.hasHeader('X-Test-Header2'), false);
break;
case 'contentLength':

0 comments on commit 3e6f103

Please sign in to comment.