diff --git a/packages/binding-http/src/http-server.ts b/packages/binding-http/src/http-server.ts index 4f4f7dd62..a5cfa18a3 100644 --- a/packages/binding-http/src/http-server.ts +++ b/packages/binding-http/src/http-server.ts @@ -103,7 +103,13 @@ export default class HttpServer implements ProtocolServer { } // No url-rewrite mapping found -> resource not found - res.writeHead(404); + const origin = req.headers["origin"]; + if (typeof origin === "string") { + res.setHeader("Access-Control-Allow-Origin", origin); + res.setHeader("Vary", "Origin"); + } + + res.writeHead(404, { "Content-Type": "text/plain" }); res.end("Not Found"); }, }); @@ -622,6 +628,14 @@ export default class HttpServer implements ProtocolServer { } private async handleRequest(req: http.IncomingMessage, res: http.ServerResponse) { + // --- GLOBAL CORS HANDLING --- + const origin = req.headers["origin"]; + if (typeof origin === "string") { + res.setHeader("Access-Control-Allow-Origin", origin); + res.setHeader("Vary", "Origin"); + } + // ----------------------------- + const requestUri = new URL(req.url ?? "", `${this.scheme}://${req.headers.host}`); debug( diff --git a/packages/binding-http/test/http-server-cors-test.ts b/packages/binding-http/test/http-server-cors-test.ts index 3feeada8e..2595ae062 100644 --- a/packages/binding-http/test/http-server-cors-test.ts +++ b/packages/binding-http/test/http-server-cors-test.ts @@ -249,4 +249,17 @@ class HttpServerCorsTest { expect(response.status).to.equal(204); // Action without output returns 204 expect(response.headers.get("Access-Control-Allow-Origin")).to.equal("*"); } + + @test async "should include CORS headers on 404 response"() { + const uri = `http://localhost:${this.httpServer.getPort()}/nonexistent-resource`; + + const response = await fetch(uri, { + headers: { + Origin: "http://example.com", + }, + }); + + expect(response.status).to.equal(404); + expect(response.headers.get("Access-Control-Allow-Origin")).to.equal("http://example.com"); + } }