From 1335df3603e64e2da67db86a853072490babffef Mon Sep 17 00:00:00 2001 From: Andrei Dumitrescu <5057797+andreidcm@users.noreply.github.com> Date: Tue, 22 Oct 2019 14:22:55 +0200 Subject: [PATCH] fix: If route action returns null or undefined, respond with empty object --- src/middleware/res-goodbye.js | 16 +++++++--------- tests/index.js | 12 ++++++++++-- tests/routes/return-undefined.route.js | 26 ++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 tests/routes/return-undefined.route.js diff --git a/src/middleware/res-goodbye.js b/src/middleware/res-goodbye.js index 161ebfd..10964f6 100644 --- a/src/middleware/res-goodbye.js +++ b/src/middleware/res-goodbye.js @@ -1,24 +1,22 @@ const debug = require("debug")("Blocks:GoodbyeMiddleware") -import { forEach } from "@mutantlove/m" +import { forEach, is } from "@mutantlove/m" module.exports = () => (req, res) => { debug(`${req.method}:${req.url} responding with ${res.ctx.status}`) - const payloadType = typeof res.ctx.payload + const payload = is(res.ctx.payload) ? res.ctx.payload : {} + const isObject = typeof payload === "object" const endAt = process.hrtime(req.ctx.startAt) - const body = - payloadType === "object" ? JSON.stringify(res.ctx.payload) : res.ctx.payload - const contentType = - payloadType === "object" - ? "application/json; charset=utf-8" - : "text/plain; charset=utf-8" + const body = isObject ? JSON.stringify(payload) : payload + const contentType = isObject + ? "application/json; charset=utf-8" + : "text/plain; charset=utf-8" forEach(([name, value]) => res.setHeader(name, value))([ // from the first middleware to now ["X-Response-Time", `${endAt[0]}s ${endAt[1] / 1000000}ms`], - ["Content-Type", contentType], ["Content-Length", Buffer.byteLength(body, "utf8")], ]) diff --git a/tests/index.js b/tests/index.js index dc8b625..12f93e6 100644 --- a/tests/index.js +++ b/tests/index.js @@ -18,6 +18,7 @@ describe("blocks :: init with defaults", async assert => { require("./routes/no-schema.route"), require("./routes/with-schema.route"), require("./routes/no-allow.route"), + require("./routes/return-undefined.route"), ], }) @@ -29,10 +30,10 @@ describe("blocks :: init with defaults", async assert => { }) assert({ - given: "3 custom routes", + given: "4 custom routes", should: "load default /ping and custom", actual: Plugins.Router.count(), - expected: 4, + expected: 5, }) assert({ @@ -112,5 +113,12 @@ describe("blocks :: init with defaults", async assert => { }, }) + assert({ + given: "route that returns undefined", + should: "return empty JSON object", + actual: await request(`${API_URL}/return-undefined`), + expected: {}, + }) + server.close() }) diff --git a/tests/routes/return-undefined.route.js b/tests/routes/return-undefined.route.js new file mode 100644 index 0000000..e2d36b5 --- /dev/null +++ b/tests/routes/return-undefined.route.js @@ -0,0 +1,26 @@ +module.exports = { + method: "GET", + path: "/return-undefined", + + /** + * Permission checking, if allowed: + * -> continue to action + * -> otherwise return 403 + * + * @param {Object} plugins Plugins + * @param {Object} req Node request + * + * @return {boolean} + */ + isAllowed: (/* plugins */) => async () => true, + + /** + * After schema validation and permission checking, do route logic + * + * @param {Object} plugins Plugins + * @param {Object} req Node request + * + * @return {mixed} + */ + action: () => () => {}, +}