diff --git a/docs/Response.md b/docs/Response.md index 94a5e7b..48d7ea5 100644 --- a/docs/Response.md +++ b/docs/Response.md @@ -25,14 +25,14 @@ app.get('/user/:id', function(req, res) { **Methods:** -+ [`.append(field, value)`](#append) ++ [`.appendHeader(field, value)`](#appendHeader) + [`.error([statusCode,] error)`](#error) -+ [`.get(field)`](#get) -+ [`.has(field)`](#has) ++ [`.getHeader(field)`](#getHeader) ++ [`.hasHeader(field)`](#hasHeader) + [`.redirect([statusCode,] url)`](#redirect) -+ [`.remove(field)`](#remove) ++ [`.removeHeader(field)`](#removeHeader) + [`.send([payload])`](#send) -+ [`.set(field [, value])`](#set) ++ [`.setHeader(field [, value])`](#setHeader) + [`.status(statusCode)`](#status) + [`.type(contentType)`](#type) @@ -112,25 +112,25 @@ is not supported by Medley and may cause undefined behavior. ## Methods - -### `res.append(field, value)` + +### `res.appendHeader(name, value)` -+ `field` *(string)* ++ `name` *(string)* + `value` *(string|string[])* + Chainable -+ Alias: `res.appendHeader()` ++ Alias: `res.append()` -Appends the `value` to the HTTP response header `field`. If the header is not -already set, it creates the header with the specified `value`. +Appends the `value` to the HTTP response header. If the header is not +already set, this is the same as calling [`res.setHeader()`](#setHeader). ```js -res.append('set-cookie', 'foo=bar') -res.get('set-cookie') // 'foo=bar' -res.append('set-cookie', 'bar=baz; Path=/; HttpOnly') -res.get('set-cookie') // ['foo=bar', 'bar=baz; Path=/; HttpOnly'] +res.appendHeader('set-cookie', 'foo=bar') +res.getHeader('set-cookie') // 'foo=bar' +res.appendHeader('set-cookie', 'bar=baz; Path=/; HttpOnly') +res.getHeader('set-cookie') // ['foo=bar', 'bar=baz; Path=/; HttpOnly'] ``` -Note that calling `res.set()` after `res.append()` will reset the previously set header value. +Note that calling `res.setHeader()` after `res.appendHeader()` will overwrite the header value. ### `res.error([statusCode,] error)` @@ -162,35 +162,35 @@ err.status = 400 res.error(err) ``` - -### `res.get(field)` + +### `res.getHeader(name)` -+ `field` *(string)* ++ `name` *(string)* + Returns: *(string|string[])* -+ Alias: `res.getHeader()` ++ Alias: `res.get()` Gets a previously set response header. ```js -res.get('content-type') // 'application/json' +res.getHeader('content-type') // 'application/json' ``` -**Tip:** While not required, it is best to use lowercase header field names for the best performance +**Tip:** While not required, using lowercase header names is better for performance and for consistency with HTTP/2 (which always sends header names in lowercase). - -### `res.has(field)` + +### `res.hasHeader(name)` -+ `field` *(string)* ++ `name` *(string)* + Returns: *(boolean)* -+ Alias: `res.hasHeader()` ++ Alias: `res.has()` Returns `true` if the specified response header was previously set, otherwise returns `false`. ```js -res.has('content-type') // false -res.set('content-type', 'application/json') -res.has('content-type') // true +res.hasHeader('content-type') // false +res.setHeader('content-type', 'application/json') +res.hasHeader('content-type') // true ``` @@ -209,17 +209,17 @@ res.redirect('/home'); res.redirect(301, '/moved-permanently'); ``` - -### `res.remove(field)` + +### `res.removeHeader(name)` -+ `field` *(string)* ++ `name` *(string)* + Chainable -+ Alias: `res.removeHeader()` ++ Alias: `res.remove()` Removes a response header. ```js -res.remove('content-type') +res.removeHeader('content-type') ``` @@ -331,32 +331,32 @@ app.get('/', (req, res) => { See [Routes#async-await](Routes.md#async-await) for more examples. - -### `res.set(field [, value])` + +### `res.setHeader(name [, value])` -+ `field` *(string|object)* ++ `name` *(string|object)* + `value` *(string|string[])* + Chainable -+ Alias: `res.setHeader()` ++ Alias: `res.set()` Sets a response HTTP header. If the header already exists, its value will be replaced. -Use an array of strings to set multiple headers for the same field. +Supports using an array of strings to set multiple headers with the same same. ```js -res.set('content-encoding', 'gzip') -res.set('set-cookie', ['user=medley', 'session=123456']) +res.setHeader('content-encoding', 'gzip') +res.setHeader('set-cookie', ['user=medley', 'session=123456']) ``` -Multiple headers can be set at once by passing an object as the `field` parameter: +Multiple headers can be set at once by passing an object as the `name` parameter: ```js -res.set({ +res.setHeader({ 'content-type': 'text/plain', 'etag': '123456' }); ``` -**Tip:** While not required, it is best to use lowercase header field names for the best performance +**Tip:** While not required, using lowercase header names is better for performance and for consistency with HTTP/2 (which always sends header names in lowercase). @@ -387,6 +387,6 @@ Sets the `Content-Type` header for the response. res.type('text/html') ``` -This is a shortcut for: `res.set('content-type', contentType)`. +This is a shortcut for: `res.setHeader('content-type', contentType)`. [http.ServerResponse]: https://nodejs.org/dist/latest/docs/api/http.html#http_class_http_serverresponse diff --git a/lib/Response.js b/lib/Response.js index c48380e..4f4fa56 100644 --- a/lib/Response.js +++ b/lib/Response.js @@ -35,11 +35,11 @@ function buildResponse() { return this } - get(field) { + getHeader(field) { return this._headers[field.toLowerCase()] } - set(field, value) { + setHeader(field, value) { if (typeof field === 'string') { if (value === undefined) { throw new TypeError("Cannot set header value to 'undefined'") @@ -57,7 +57,7 @@ function buildResponse() { return this } - append(field, value) { + appendHeader(field, value) { if (value === undefined) { throw new TypeError("Cannot set header value to 'undefined'") } @@ -78,11 +78,11 @@ function buildResponse() { return this } - has(field) { + hasHeader(field) { return this._headers.hasOwnProperty(field.toLowerCase()) } - remove(field) { + removeHeader(field) { delete this._headers[field.toLowerCase()] return this } @@ -156,11 +156,11 @@ function buildResponse() { // Aliases Object.defineProperties(Response.prototype, { - appendHeader: Object.getOwnPropertyDescriptor(Response.prototype, 'append'), - getHeader: Object.getOwnPropertyDescriptor(Response.prototype, 'get'), - hasHeader: Object.getOwnPropertyDescriptor(Response.prototype, 'has'), - removeHeader: Object.getOwnPropertyDescriptor(Response.prototype, 'remove'), - setHeader: Object.getOwnPropertyDescriptor(Response.prototype, 'set'), + append: Object.getOwnPropertyDescriptor(Response.prototype, 'appendHeader'), + get: Object.getOwnPropertyDescriptor(Response.prototype, 'getHeader'), + has: Object.getOwnPropertyDescriptor(Response.prototype, 'hasHeader'), + remove: Object.getOwnPropertyDescriptor(Response.prototype, 'removeHeader'), + set: Object.getOwnPropertyDescriptor(Response.prototype, 'setHeader'), }) // Prevent users from decorating constructor properties diff --git a/test/Response-send.test.js b/test/Response-send.test.js index f983def..7607189 100644 --- a/test/Response-send.test.js +++ b/test/Response-send.test.js @@ -41,7 +41,7 @@ test('within a sub-app', (t) => { app.get('/', function(req, res) { res.status(201) - res.set('content-type', 'text/plain') + res.setHeader('content-type', 'text/plain') res.send('hello world!') }) @@ -59,7 +59,7 @@ test('within a sub-app', (t) => { app.createSubApp() .addHook('onSend', function(req, res, payload, next) { - res.set('x-onsend', 'yes') + res.setHeader('x-onsend', 'yes') next() }) .get('/redirect-onsend', function(req, res) { @@ -164,7 +164,7 @@ test('buffer with Content-Type should not change the Content-Type', (t) => { const app = medley() app.get('/', function(req, res) { - res.set('content-type', 'text/plain') + res.setHeader('content-type', 'text/plain') res.send(Buffer.alloc(1024)) }) diff --git a/test/Response.test.js b/test/Response.test.js index 71de7a9..372ce3f 100644 --- a/test/Response.test.js +++ b/test/Response.test.js @@ -28,11 +28,11 @@ test('Response properties', (t) => { test('Response aliases', (t) => { const response = new Response() - t.equal(response.appendHeader, response.append) - t.equal(response.getHeader, response.get) - t.equal(response.hasHeader, response.has) - t.equal(response.removeHeader, response.remove) - t.equal(response.setHeader, response.set) + t.equal(response.append, response.appendHeader) + t.equal(response.get, response.getHeader) + t.equal(response.has, response.hasHeader) + t.equal(response.remove, response.removeHeader) + t.equal(response.set, response.setHeader) t.end() }) @@ -95,40 +95,40 @@ test('res.status() should set the status code', (t) => { }) }) -test('res.append() sets headers and adds to existing headers', (t) => { +test('res.appendHeader() sets headers and adds to existing headers', (t) => { t.plan(18) const app = medley() app.get('/', (req, res) => { - res.append('x-custom-header', 'first') - t.equal(res.get('x-custom-header'), 'first') + res.appendHeader('x-custom-header', 'first') + t.equal(res.getHeader('x-custom-header'), 'first') - t.equal(res.append('x-custom-header', 'second'), res) - t.deepEqual(res.get('x-custom-header'), ['first', 'second']) + t.equal(res.appendHeader('x-custom-header', 'second'), res) + t.deepEqual(res.getHeader('x-custom-header'), ['first', 'second']) - t.equal(res.append('x-custom-header', ['3', '4']), res) - t.deepEqual(res.get('x-custom-header'), ['first', 'second', '3', '4']) + t.equal(res.appendHeader('x-custom-header', ['3', '4']), res) + t.deepEqual(res.getHeader('x-custom-header'), ['first', 'second', '3', '4']) res.send() }) app.get('/append-multiple-to-string', (req, res) => { - res.append('x-custom-header', 'first') - t.equal(res.get('x-custom-header'), 'first') + res.appendHeader('x-custom-header', 'first') + t.equal(res.getHeader('x-custom-header'), 'first') - res.append('x-custom-header', ['second', 'third']) - t.deepEqual(res.get('x-custom-header'), ['first', 'second', 'third']) + res.appendHeader('x-custom-header', ['second', 'third']) + t.deepEqual(res.getHeader('x-custom-header'), ['first', 'second', 'third']) res.send() }) app.get('/append-case-insensitive', (req, res) => { - res.append('X-Custom-Header', 'first') - t.equal(res.get('x-custom-header'), 'first') + res.appendHeader('X-Custom-Header', 'first') + t.equal(res.getHeader('x-custom-header'), 'first') - res.append('X-Custom-Header', ['second', 'third']) - t.deepEqual(res.get('x-custom-header'), ['first', 'second', 'third']) + res.appendHeader('X-Custom-Header', ['second', 'third']) + t.deepEqual(res.getHeader('x-custom-header'), ['first', 'second', 'third']) res.send() }) @@ -152,23 +152,23 @@ test('res.append() sets headers and adds to existing headers', (t) => { }) }) -test('res.append() does not allow setting a header value to `undefined`', (t) => { +test('res.appendHeader() does not allow setting a header value to `undefined`', (t) => { t.plan(8) const app = medley() app.get('/', (req, res) => { try { - res.append('set-cookie', undefined) + res.appendHeader('set-cookie', undefined) t.fail('should not allow setting a header to `undefined`') } catch (err) { t.type(err, TypeError) t.equal(err.message, "Cannot set header value to 'undefined'") } - res.append('x-custom-header', ['a value']) + res.appendHeader('x-custom-header', ['a value']) try { - res.append('x-custom-header', undefined) + res.appendHeader('x-custom-header', undefined) t.fail('should not allow setting a header to `undefined`') } catch (err) { t.type(err, TypeError) @@ -186,29 +186,29 @@ test('res.append() does not allow setting a header value to `undefined`', (t) => }) }) -test('res.get/set() get and set the response headers', (t) => { +test('res.getHeader/setHeader() get and set the response headers', (t) => { t.plan(16) const app = medley() app.get('/', (req, res) => { - t.equal(res.get('x-custom-header'), undefined) + t.equal(res.getHeader('x-custom-header'), undefined) - t.equal(res.set('x-custom-header', 'custom header'), res) - t.equal(res.get('x-custom-header'), 'custom header') + t.equal(res.setHeader('x-custom-header', 'custom header'), res) + t.equal(res.getHeader('x-custom-header'), 'custom header') - res.set('content-type', 'custom/type') + res.setHeader('content-type', 'custom/type') res.send('text') }) app.get('/case-insensitive', (req, res) => { - t.equal(res.get('X-Custom-Header'), undefined) + t.equal(res.getHeader('X-Custom-Header'), undefined) - res.set('X-Custom-Header', 'custom header') - t.equal(res.get('X-Custom-Header'), 'custom header') - t.equal(res.get('x-custom-header'), 'custom header') + res.setHeader('X-Custom-Header', 'custom header') + t.equal(res.getHeader('X-Custom-Header'), 'custom header') + t.equal(res.getHeader('x-custom-header'), 'custom header') - res.set('Content-Type', 'custom/type') + res.setHeader('Content-Type', 'custom/type') res.send('text') }) @@ -229,19 +229,19 @@ test('res.get/set() get and set the response headers', (t) => { }) }) -test('res.has() checks if a response header has been set', (t) => { +test('res.hasHeader() checks if a response header has been set', (t) => { t.plan(6) const app = medley() app.get('/', (req, res) => { - t.equal(res.has('x-custom-header'), false) + t.equal(res.hasHeader('x-custom-header'), false) - res.set('x-custom-header', 'custom header') - t.equal(res.has('x-custom-header'), true) - t.equal(res.has('X-Custom-Header'), true, 'is case-insensitive') + res.setHeader('x-custom-header', 'custom header') + t.equal(res.hasHeader('x-custom-header'), true) + t.equal(res.hasHeader('X-Custom-Header'), true, 'is case-insensitive') - t.equal(res.has('__proto__'), false, 'does not report unset properties that are on Object.prototype') + t.equal(res.hasHeader('__proto__'), false, 'does not report unset properties that are on Object.prototype') res.send() }) @@ -252,22 +252,22 @@ test('res.has() checks if a response header has been set', (t) => { }) }) -test('res.set() accepts an object of headers', (t) => { +test('res.setHeader() accepts an object of headers', (t) => { t.plan(8) const app = medley() app.get('/', (req, res) => { - res.set({ + res.setHeader({ 'X-Custom-Header1': 'custom header1', 'x-custom-header2': 'custom header2', }) - t.equal(res.get('x-custom-header1'), 'custom header1') - t.equal(res.get('x-custom-header2'), 'custom header2') + t.equal(res.getHeader('x-custom-header1'), 'custom header1') + t.equal(res.getHeader('x-custom-header2'), 'custom header2') - t.equal(res.set({}), res) + t.equal(res.setHeader({}), res) - res.set({'content-type': 'custom/type'}).send() + res.setHeader({'content-type': 'custom/type'}).send() }) request(app, '/', (err, res) => { @@ -279,14 +279,14 @@ test('res.set() accepts an object of headers', (t) => { }) }) -test('res.set() does not allow setting a header value to `undefined`', (t) => { +test('res.setHeader() does not allow setting a header value to `undefined`', (t) => { t.plan(9) const app = medley() app.get('/', (req, res) => { try { - res.set('content-type', undefined) + res.setHeader('content-type', undefined) t.fail('should not allow setting a header to `undefined`') } catch (err) { t.type(err, TypeError) @@ -294,7 +294,7 @@ test('res.set() does not allow setting a header value to `undefined`', (t) => { } try { - res.set({ + res.setHeader({ 'x-custom-header1': 'string', 'x-custom-header2': undefined, }) @@ -316,27 +316,27 @@ test('res.set() does not allow setting a header value to `undefined`', (t) => { }) }) -test('res.remove() removes response headers', (t) => { +test('res.removeHeader() removes response headers', (t) => { t.plan(10) const app = medley() app.get('/', (req, res) => { - res.set('x-custom-header', 'custom header') - t.equal(res.get('x-custom-header'), 'custom header') + res.setHeader('x-custom-header', 'custom header') + t.equal(res.getHeader('x-custom-header'), 'custom header') - t.equal(res.remove('x-custom-header'), res) - t.equal(res.get('x-custom-header'), undefined) + t.equal(res.removeHeader('x-custom-header'), res) + t.equal(res.getHeader('x-custom-header'), undefined) res - .set('x-custom-header-2', ['a', 'b']) - .remove('x-custom-header-2') - t.equal(res.get('x-custom-header-2'), undefined) + .setHeader('x-custom-header-2', ['a', 'b']) + .removeHeader('x-custom-header-2') + t.equal(res.getHeader('x-custom-header-2'), undefined) res - .set('X-Custom-Header-3', 'custom header 3') - .remove('X-Custom-Header-3') - t.equal(res.get('X-Custom-Header-3'), undefined) + .setHeader('X-Custom-Header-3', 'custom header 3') + .removeHeader('X-Custom-Header-3') + t.equal(res.getHeader('X-Custom-Header-3'), undefined) res.send() }) diff --git a/test/hooks.test.js b/test/hooks.test.js index 75ec77a..e39d128 100644 --- a/test/hooks.test.js +++ b/test/hooks.test.js @@ -359,7 +359,7 @@ test('onSend hook is called after payload is serialized and headers are set', (t app.createSubApp() .addHook('onSend', (req, res, serializedPayload, next) => { t.strictDeepEqual(JSON.parse(serializedPayload), payload) - t.equal(res.get('content-type'), 'application/json') + t.equal(res.getHeader('content-type'), 'application/json') next() }) .get('/json', (req, res) => { @@ -370,7 +370,7 @@ test('onSend hook is called after payload is serialized and headers are set', (t app.createSubApp() .addHook('onSend', (req, res, serializedPayload, next) => { t.strictEqual(serializedPayload, 'some text') - t.strictEqual(res.get('content-type'), 'text/plain; charset=utf-8') + t.strictEqual(res.getHeader('content-type'), 'text/plain; charset=utf-8') next() }) .get('/text', (req, res) => { @@ -383,7 +383,7 @@ test('onSend hook is called after payload is serialized and headers are set', (t app.createSubApp() .addHook('onSend', (req, res, serializedPayload, next) => { t.strictEqual(serializedPayload, payload) - t.strictEqual(res.get('content-type'), 'application/octet-stream') + t.strictEqual(res.getHeader('content-type'), 'application/octet-stream') next() }) .get('/buffer', (req, res) => { @@ -403,7 +403,7 @@ test('onSend hook is called after payload is serialized and headers are set', (t app.createSubApp() .addHook('onSend', (req, res, serializedPayload, next) => { t.strictEqual(serializedPayload, payload) - t.strictEqual(res.get('content-type'), 'application/octet-stream') + t.strictEqual(res.getHeader('content-type'), 'application/octet-stream') next() }) .get('/stream', (req, res) => { diff --git a/test/http-methods/head.test.js b/test/http-methods/head.test.js index a3af711..24b3f8e 100644 --- a/test/http-methods/head.test.js +++ b/test/http-methods/head.test.js @@ -57,7 +57,7 @@ t.test('head request without sending a body', (t) => { }) app.head('/length-set', (req, res) => { - res.set('content-length', '4').send() + res.setHeader('content-length', '4').send() }) request(app, { diff --git a/test/stream.test.js b/test/stream.test.js index 00b8671..80fbab0 100644 --- a/test/stream.test.js +++ b/test/stream.test.js @@ -53,7 +53,7 @@ test('should trigger the onSend hook', (t) => { app.addHook('onSend', (req, res, payload, next) => { t.ok(payload._readableState) - res.set('content-type', 'application/javascript') + res.setHeader('content-type', 'application/javascript') next() }) @@ -95,7 +95,7 @@ test('onSend hook stream', (t) => { app.addHook('onSend', (req, res, payload, next) => { const gzStream = zlib.createGzip() - res.set('content-encoding', 'gzip') + res.setHeader('content-encoding', 'gzip') pump( fs.createReadStream(__filename, 'utf8'), gzStream,