Skip to content

Commit e996fa1

Browse files
committed
fix(binding-http): include CORS headers for 404 responses
Signed-off-by: Pranav-0440 <pranavghorpade61@gmail.com>
1 parent 7bda06d commit e996fa1

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

packages/binding-http/src/http-server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ export default class HttpServer implements ProtocolServer {
103103
}
104104

105105
// No url-rewrite mapping found -> resource not found
106+
const origin = req.headers.origin;
107+
if (origin != null) {
108+
res.setHeader("Access-Control-Allow-Origin", origin);
109+
res.setHeader("Vary", "Origin");
110+
}
111+
106112
res.writeHead(404);
107113
res.end("Not Found");
108114
},

packages/binding-http/test/http-server-cors-test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,4 +249,59 @@ class HttpServerCorsTest {
249249
expect(response.status).to.equal(204); // Action without output returns 204
250250
expect(response.headers.get("Access-Control-Allow-Origin")).to.equal("*");
251251
}
252+
@test async "should include CORS headers on 405 response"() {
253+
this.thing = new ExposedThing(this.servient, {
254+
title: "TestThing405",
255+
properties: {
256+
test: {
257+
type: "string",
258+
forms: [],
259+
},
260+
},
261+
});
262+
263+
await this.httpServer.expose(this.thing);
264+
265+
const uri = `http://localhost:${this.httpServer.getPort()}/testthing405/properties/test`;
266+
267+
const response = await fetch(uri, {
268+
method: "DELETE", // not allowed
269+
headers: {
270+
Origin: "http://example.com",
271+
},
272+
});
273+
274+
expect(response.status).to.equal(404);
275+
276+
// Ensure CORS header exists even on 405
277+
expect(response.headers.get("Access-Control-Allow-Origin")).to.exist;
278+
}
279+
280+
@test async "should handle preflight with custom headers"() {
281+
this.thing = new ExposedThing(this.servient, {
282+
title: "TestThingCustomHeaders",
283+
properties: {
284+
test: {
285+
type: "string",
286+
forms: [],
287+
},
288+
},
289+
});
290+
291+
await this.httpServer.expose(this.thing);
292+
293+
const uri = `http://localhost:${this.httpServer.getPort()}/testthingcustomheaders/properties/test`;
294+
295+
const response = await fetch(uri, {
296+
method: "OPTIONS",
297+
headers: {
298+
Origin: "http://example.com",
299+
"Access-Control-Request-Method": "GET",
300+
"Access-Control-Request-Headers": "Authorization, Content-Type",
301+
},
302+
});
303+
304+
expect(response.status).to.equal(200);
305+
expect(response.headers.get("Access-Control-Allow-Headers")).to.contain("authorization");
306+
}
252307
}

0 commit comments

Comments
 (0)