diff --git a/docs/api/response.md b/docs/api/response.md index 531bd72d5..5e5b43e47 100644 --- a/docs/api/response.md +++ b/docs/api/response.md @@ -177,6 +177,15 @@ app.use(async ctx => { const etag = ctx.response.get('ETag'); ``` +### response.has(field) + + Returns `true` if the header identified by name is currently set in the outgoing headers. + The header name matching is case-insensitive. + +```js +const rateLimited = ctx.response.has('X-RateLimit-Limit'); +``` + ### response.set(field, value) Set response header `field` to `value`: diff --git a/lib/context.js b/lib/context.js index 3e9575593..caee62718 100644 --- a/lib/context.js +++ b/lib/context.js @@ -193,6 +193,7 @@ delegate(proto, 'response') .method('redirect') .method('remove') .method('vary') + .method('has') .method('set') .method('append') .method('flushHeaders') diff --git a/lib/response.js b/lib/response.js index b8477c24a..978988320 100644 --- a/lib/response.js +++ b/lib/response.js @@ -149,7 +149,7 @@ module.exports = { if (!this._explicitStatus) this.status = 200; // set the content-type only if not yet set - const setType = !this.header['content-type']; + const setType = !this.has('Content-Type'); // string if ('string' == typeof val) { @@ -419,6 +419,29 @@ module.exports = { return this.header[field.toLowerCase()] || ''; }, + /** + * Returns true if the header identified by name is currently set in the outgoing headers. + * The header name matching is case-insensitive. + * + * Examples: + * + * this.has('Content-Type'); + * // => true + * + * this.get('content-type'); + * // => true + * + * @param {String} field + * @return {boolean} + * @api public + */ + has(field) { + return typeof this.res.hasHeader === 'function' + ? this.res.hasHeader(field) + // Node < 7.7 + : field.toLowerCase() in this.headers; + }, + /** * Set header `field` to `val`, or pass * an object of header fields. diff --git a/test/response/has.js b/test/response/has.js new file mode 100644 index 000000000..f271c4c71 --- /dev/null +++ b/test/response/has.js @@ -0,0 +1,21 @@ + +'use strict'; + +const assert = require('assert'); +const context = require('../helpers/context'); + +describe('ctx.response.has(name)', () => { + it('should check a field value, case insensitive way', () => { + const ctx = context(); + ctx.set('X-Foo', ''); + assert.ok(ctx.response.has('x-Foo')); + assert.ok(ctx.has('x-foo')); + }); + + it('should return false for non-existent header', () => { + const ctx = context(); + assert.strictEqual(ctx.response.has('boo'), false); + ctx.set('x-foo', 5); + assert.strictEqual(ctx.has('x-boo'), false); + }); +});