diff --git a/package-lock.json b/package-lock.json index 70d40cac..172fded7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6291,9 +6291,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "wrap-ansi": { diff --git a/src/index.js b/src/index.js index 311c7db5..ad8f0d60 100644 --- a/src/index.js +++ b/src/index.js @@ -746,7 +746,12 @@ module.exports = { if (key == "Content-Type" && !responseType) responseType = ctx.meta.$responseHeaders[key]; else - res.setHeader(key, ctx.meta.$responseHeaders[key]); + try { + res.setHeader(key, ctx.meta.$responseHeaders[key]); + } catch (error) { + this.logger.warn("Invalid header value", req.url, error); + res.setHeader(key, encodeURI(ctx.meta.$responseHeaders[key])); + } }); } if (data == null) @@ -898,7 +903,12 @@ module.exports = { if (key === "Content-Type" && !responseType) responseType = ctx.meta.$responseHeaders[key]; else - res.setHeader(key, ctx.meta.$responseHeaders[key]); + try { + res.setHeader(key, ctx.meta.$responseHeaders[key]); + } catch (error) { + this.logger.warn("Invalid header value", req.url, error); + res.setHeader(key, encodeURI(ctx.meta.$responseHeaders[key])); + } }); } } diff --git a/test/integration/index.spec.js b/test/integration/index.spec.js index 61421682..bb8c4c97 100644 --- a/test/integration/index.spec.js +++ b/test/integration/index.spec.js @@ -387,7 +387,7 @@ describe("Test responses", () => { .then(res => { expect(res.statusCode).toBe(500); expect(res.headers["content-type"]).toBe("application/json; charset=utf-8"); - expect(res.header["x-request-id"]).toBeDefined(); + expect(res.headers["x-request-id"]).toBeDefined(); expect(res.body).toEqual({ "code": 500, "message": "I'm dangerous", @@ -402,11 +402,22 @@ describe("Test responses", () => { .then(res => { expect(res.statusCode).toBe(500); expect(res.headers["content-type"]).toBe("text/plain"); - expect(res.header["x-request-id"]).toBeDefined(); - expect(res.header["x-custom-header"]).toBe("Custom content"); + expect(res.headers["x-invalid-header"]).toBe(encodeURI("\r\nBOOM")); + expect(res.headers["x-request-id"]).toBeDefined(); + expect(res.headers["x-custom-header"]).toBe("Custom content"); expect(res.text).toBe("{\"name\":\"MoleculerServerError\",\"message\":\"It is a wrong action! I always throw error!\",\"code\":500}"); }); }); + + it("GET /test/invalidResponseHeaders", () => { + return request(server) + .get("/test/invalidResponseHeaders") + .then(res => { + expect(res.headers["x-valid-header"]).toBe("valid header"); + expect(res.headers["x-invalid-header"]).toBe(encodeURI("\r\nBOOM")); + expect(res.text).toBe("{\"x-invalid-header\":\"\\r\\nBOOM\"}"); + }); + }); }); describe("Test with `path` prefix", () => { @@ -1626,7 +1637,7 @@ describe("Test REST shorthand aliases and except filter", () => { }); }); -describe("Test REST shorthand aliases and only, execpt filter", () => { +describe("Test REST shorthand aliases and only, except filter", () => { let broker; let service; let server; diff --git a/test/services/test.service.js b/test/services/test.service.js index a214d026..7fd5398c 100644 --- a/test/services/test.service.js +++ b/test/services/test.service.js @@ -281,12 +281,24 @@ module.exports = { errorWithHeader(ctx) { ctx.meta.$responseType = "text/plain"; ctx.meta.$responseHeaders = { - "X-Custom-Header": "Custom content" + "X-Custom-Header": "Custom content", + "x-invalid-header": "\r\nBOOM" }; throw new MoleculerServerError("It is a wrong action! I always throw error!"); }, + invalidResponseHeaders(ctx) { + ctx.meta.$responseHeaders = { + "x-valid-header": "valid header", + "x-invalid-header": "\r\nBOOM" + }; + + return { + "x-invalid-header": "\r\nBOOM" + }; + }, + update: { rest: ["PUT /update", "PATCH /update"], params: {