From 8d52105a34234be9e771ff3b76b43e4e30328943 Mon Sep 17 00:00:00 2001 From: ejose19 <8742215+ejose19@users.noreply.github.com> Date: Tue, 28 Apr 2020 00:30:51 -0300 Subject: [PATCH] feat: allow bodyless responses for non empty status codes (#1447) Co-authored-by: Eladio Mora --- lib/application.js | 5 +++++ lib/response.js | 1 + test/application/respond.js | 37 ++++++++++++++++++++++++++++++++++++ test/application/response.js | 28 +++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/lib/application.js b/lib/application.js index 57b701cef..ab711d294 100644 --- a/lib/application.js +++ b/lib/application.js @@ -238,6 +238,11 @@ function respond(ctx) { // status body if (null == body) { + if (ctx.response._explicitNullBody) { + ctx.response.remove('Content-Type'); + ctx.response.remove('Transfer-Encoding'); + return res.end(); + } if (ctx.req.httpVersionMajor >= 2) { body = String(code); } else { diff --git a/lib/response.js b/lib/response.js index 87ecc56a9..c16991ec3 100644 --- a/lib/response.js +++ b/lib/response.js @@ -139,6 +139,7 @@ module.exports = { // no content if (null == val) { if (!statuses.empty[this.status]) this.status = 204; + if (val === null) this._explicitNullBody = true; this.remove('Content-Type'); this.remove('Content-Length'); this.remove('Transfer-Encoding'); diff --git a/test/application/respond.js b/test/application/respond.js index d254ead6e..b7080c9ef 100644 --- a/test/application/respond.js +++ b/test/application/respond.js @@ -810,4 +810,41 @@ describe('app.respond', () => { assert.equal(res.headers.hasOwnProperty('content-type'), false); }); }); + + describe('with explicit null body', () => { + it('should preserve given status', async() => { + const app = new Koa(); + + app.use(ctx => { + ctx.body = null; + ctx.status = 404; + }); + + const server = app.listen(); + + return request(server) + .get('/') + .expect(404) + .expect('') + .expect({}); + }); + it('should respond with correct headers', async() => { + const app = new Koa(); + + app.use(ctx => { + ctx.body = null; + ctx.status = 401; + }); + + const server = app.listen(); + + const res = await request(server) + .get('/') + .expect(401) + .expect('') + .expect({}); + + assert.equal(res.headers.hasOwnProperty('content-type'), false); + }); + }); }); diff --git a/test/application/response.js b/test/application/response.js index 9fb4fc90c..c9c725334 100644 --- a/test/application/response.js +++ b/test/application/response.js @@ -10,6 +10,8 @@ describe('app.response', () => { app1.response.msg = 'hello'; const app2 = new Koa(); const app3 = new Koa(); + const app4 = new Koa(); + const app5 = new Koa(); it('should merge properties', () => { app1.use((ctx, next) => { @@ -43,4 +45,30 @@ describe('app.response', () => { .expect(404); assert.equal(response.text, '404'); }); + + it('should set ._explicitNullBody correctly', async() => { + app4.use((ctx, next) => { + ctx.body = null; + assert.strictEqual(ctx.response._explicitNullBody, true); + }); + + return request(app4.listen()) + .get('/') + .expect(204); + }); + + it('should not set ._explicitNullBody incorrectly', async() => { + app5.use((ctx, next) => { + ctx.body = undefined; + assert.strictEqual(ctx.response._explicitNullBody, undefined); + ctx.body = ''; + assert.strictEqual(ctx.response._explicitNullBody, undefined); + ctx.body = false; + assert.strictEqual(ctx.response._explicitNullBody, undefined); + }); + + return request(app5.listen()) + .get('/') + .expect(204); + }); });