Skip to content

feat(binding-http): Make Access-Control-Allow-Origin header configurable#1500

Open
jona42-ui wants to merge 1 commit intoeclipse-thingweb:masterfrom
jona42-ui:feat/configurable-cors-origin
Open

feat(binding-http): Make Access-Control-Allow-Origin header configurable#1500
jona42-ui wants to merge 1 commit intoeclipse-thingweb:masterfrom
jona42-ui:feat/configurable-cors-origin

Conversation

@jona42-ui
Copy link
Contributor

Added allowedOrigins option to HttpConfig interface to let users configure the Access-Control-Allow-Origin header value. Defaults to '*' for backward compatibility.

Since allowedOrigins is an optional field, this is fully backward compatible .

Fixes #941

Copilot AI review requested due to automatic review settings February 25, 2026 04:44
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a configurable allowedOrigins option to the HttpServer to allow users to customize the Access-Control-Allow-Origin CORS header. Previously, this value was hardcoded to "*" for unsecured (nosec) things. The new option defaults to "*" for full backward compatibility.

Changes:

  • Added allowedOrigins optional field to the HttpConfig interface with documentation
  • Updated HttpServer to store and expose the allowedOrigins configuration
  • Modified all route handlers to use the configured value instead of hardcoded "*"
  • Added comprehensive test suite to verify the new configuration works correctly while maintaining backward compatibility

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/binding-http/src/http.ts Added optional allowedOrigins field to HttpConfig interface with JSDoc
packages/binding-http/src/http-server.ts Added allowedOrigins property and getAllowedOrigins() public method
packages/binding-http/src/routes/things.ts Updated to use getAllowedOrigins() instead of hardcoded "*"
packages/binding-http/src/routes/thing-description.ts Updated to use getAllowedOrigins() instead of hardcoded "*"
packages/binding-http/src/routes/common.ts Added allowedOrigins parameter to utility functions setCorsForThing and respondUnallowedMethod
packages/binding-http/src/routes/property.ts Updated to pass getAllowedOrigins() to CORS utility functions
packages/binding-http/src/routes/property-observe.ts Updated to pass getAllowedOrigins() to CORS utility functions
packages/binding-http/src/routes/properties.ts Updated to pass getAllowedOrigins() to CORS utility functions
packages/binding-http/src/routes/event.ts Updated to pass getAllowedOrigins() to CORS utility functions
packages/binding-http/src/routes/action.ts Updated to pass getAllowedOrigins() to CORS utility functions
packages/binding-http/test/http-server-cors-test.ts Added comprehensive test suite for the new configuration option

} finally {
await httpServer.stop();
}
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite provides good coverage for properties, thing listing, thing description, and CORS preflight scenarios. However, it's missing test cases for actions and events with the custom allowedOrigins configuration. Consider adding tests similar to the existing "should handle CORS for invoke action (POST)" test in the HttpServerCorsTest suite, but with a configured allowedOrigins value to ensure actions and events also respect the configuration.

Suggested change
}
}
@test async "should use configured allowedOrigins for invoke action (POST) on nosec thing"() {
const servient = new Servient();
const httpServer = new HttpServer({ port: 0, allowedOrigins: "http://my-app.example.com" });
await httpServer.start(servient);
try {
const thing = new ExposedThing(servient, {
title: "TestOriginAction",
actions: {
invoke: {
output: {
type: "string",
},
forms: [],
},
},
});
thing.setActionHandler("invoke", () => Promise.resolve("ok"));
await httpServer.expose(thing);
const uri = `http://localhost:${httpServer.getPort()}/testoriginaction/actions/invoke`;
const response = await fetch(uri, {
method: "POST",
headers: {
Origin: "http://other.example.com",
"Content-Type": "application/json",
},
body: JSON.stringify({}),
});
expect(response.status).to.equal(200);
expect(response.headers.get("Access-Control-Allow-Origin")).to.equal("http://my-app.example.com");
} finally {
await httpServer.stop();
}
}
@test async "should use configured allowedOrigins for subscribe event (GET) on nosec thing"() {
const servient = new Servient();
const httpServer = new HttpServer({ port: 0, allowedOrigins: "http://my-app.example.com" });
await httpServer.start(servient);
try {
const thing = new ExposedThing(servient, {
title: "TestOriginEvent",
events: {
tick: {
data: {
type: "string",
},
forms: [],
},
},
});
await httpServer.expose(thing);
const uri = `http://localhost:${httpServer.getPort()}/testoriginevent/events/tick`;
const response = await fetch(uri, {
method: "GET",
headers: {
Origin: "http://other.example.com",
},
});
expect(response.status).to.equal(200);
expect(response.headers.get("Access-Control-Allow-Origin")).to.equal("http://my-app.example.com");
} finally {
await httpServer.stop();
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +52
* Configures the Access-Control-Allow-Origin header.
* Default is "*" (any origin allowed).
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new allowedOrigins configuration option should be documented in the README.md file. Consider adding documentation in the HttpServer Configuration section (around line 271-280) to show users how to configure this option. Example:

new HttpServer({
    port: 8080,
    allowedOrigins: "https://my-app.example.com" // Restrict CORS to specific origin (default: "*")
})

This would help users understand how to use this feature and what the default behavior is.

Suggested change
* Configures the Access-Control-Allow-Origin header.
* Default is "*" (any origin allowed).
* Configures the Access-Control-Allow-Origin header used for CORS.
*
* Default: "*" (any origin allowed).
*
* Example:
* ```ts
* new HttpServer({
* port: 8080,
* allowedOrigins: "https://my-app.example.com" // restrict CORS to specific origin
* });
* ```

Copilot uses AI. Check for mistakes.
@jona42-ui
Copy link
Contributor Author

@relu91 I suppose these reviews from copilot make sense

Add allowedOrigins option to HttpConfig interface to let users configure
the Access-Control-Allow-Origin header value. Defaults to '*' for backward
compatibility. Secured things still echo the request origin with credentials
regardless of this setting.

Fixes eclipse-thingweb#941

Signed-off-by: jona42-ui <jonathanthembo123@gmail.com>
@jona42-ui jona42-ui force-pushed the feat/configurable-cors-origin branch from b0c3768 to 93392e6 Compare February 26, 2026 19:41
@relu91
Copy link
Member

relu91 commented Feb 27, 2026

Looking good, I'm a little bit concerned about the new tests structure... there's a lot of duplicated code for just two different setup configurations 🤔 . @danielpeintner what do you think?

@jona42-ui
Copy link
Contributor Author

@relu91 I see well your point, can we separate each configuration in a test suite or we can look at parameterizing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Let user configure Access-Control-Allow-Origin header

3 participants