Skip to content

feat: proxy and admin cors#94

Merged
bzp2010 merged 2 commits intomainfrom
bzp/feat-cors
May 8, 2026
Merged

feat: proxy and admin cors#94
bzp2010 merged 2 commits intomainfrom
bzp/feat-cors

Conversation

@bzp2010
Copy link
Copy Markdown
Collaborator

@bzp2010 bzp2010 commented May 7, 2026

Summary by CodeRabbit

  • New Features

    • Added configurable CORS support for proxy and admin servers with options for enabling, allowed origins, methods, headers, exposed headers, and credentials.
  • Improvements

    • Improved startup error handling to surface configuration and router construction failures with clearer context.
  • Tests

    • Added unit tests validating CORS configuration parsing and error handling.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 845f9702-aaff-4bd6-8f5c-47122aab452a

📥 Commits

Reviewing files that changed from the base of the PR and between 3b6ab5b and f52b2c0.

📒 Files selected for processing (1)
  • config.yaml

📝 Walkthrough

Walkthrough

This PR adds configurable CORS support: the root crate gains the tower-http CORS dependency; ServerCommonCors and its to_cors_layer() are added and wired into ServerProxy and config.yaml; proxy and admin router builders become fallible and apply CORS conditionally; entry points propagate router creation errors.

Changes

CORS Support for Proxy and Admin Routers

Layer / File(s) Summary
Dependencies and Configuration Types
Cargo.toml, src/config/types.rs, config.yaml
Adds tower-http dependency with cors feature. Introduces ServerCommonCors struct and to_cors_layer() method. Extends ServerProxy with cors field and updates config.yaml with proxy/admin CORS entries.
Proxy Router CORS Integration
src/proxy/mod.rs
create_router now returns anyhow::Result<Router>, initializes a mutable router, preserves existing routes/body limits, and conditionally layers the CORS middleware via cors.to_cors_layer()?.
Admin Router CORS Integration
src/admin/mod.rs
create_router now returns anyhow::Result<Router>, moves OpenAPI merge earlier, conditionally applies the CORS layer, and keeps auth middleware unchanged.
Application Entry Points
src/lib.rs
run and serve_admin now handle fallible router creation and wrap errors with contextual messages via .context(...)?.
Tests
src/config/types.rs
Unit tests added for ServerCommonCors::to_cors_layer() validating success and an invalid-method error path.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • api7/aisix#111: Modifies the same server configuration structures (ServerProxy, ServerAdmin, Server) to add TLS and listen support, which is related to these configuration and router changes.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Security Check ❌ Error Missing validation in ServerCommonCors::to_cors_layer() to prevent wildcard origin with credentials enabled - an insecure CORS configuration that goes against security best practices. Add validation in to_cors_layer() that returns an error if allow_credentials is true AND wildcard "" is in allowed_origins. Example: if self.allow_credentials.unwrap_or(false) && origins.iter().any(|o| o == "") { return Err(...) }
E2e Test Quality Review ⚠️ Warning PR lacks E2E test coverage (blocking issue). Only 2 unit tests for config parsing exist. No integration tests verify CORS headers in actual HTTP responses or router behavior. Add E2E tests covering: CORS headers in proxy/admin responses when enabled, disabled state, invalid config error handling, and preflight requests. Verify actual HTTP response headers.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: proxy and admin cors' accurately describes the main changes: adding CORS support to both proxy and admin routers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bzp/feat-cors

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/proxy/mod.rs (1)

26-27: 💤 Low value

#[allow(dead_code)] on config is now stale.

state.config is accessed at Line 86 after this PR, so the suppression attribute can be dropped and the compiler will naturally validate usage.

🔧 Suggested change
 #[derive(Clone)]
 pub struct AppState {
-    #[allow(dead_code)]
     config: Arc<Config>,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/proxy/mod.rs` around lines 26 - 27, Remove the now-stale
#[allow(dead_code)] attribute on the config field: open the struct containing
"config: Arc<Config>" (the same struct whose instance is referenced as
state.config) and delete the #[allow(dead_code)] line so the compiler will
validate usage normally; no other code changes are required since state.config
is accessed elsewhere in the file.
src/config/types.rs (1)

308-325: ⚡ Quick win

Add a test case for the wildcard + credentials combination.

The existing tests cover a valid multi-field config and an invalid method, but miss the "*" origin + allow_credentials: true case — the exact combination that causes the panic. Without the validation guard from above, this test would itself panic rather than assert is_err().

🧪 Suggested test
+    #[test]
+    fn to_cors_layer_rejects_wildcard_with_credentials() {
+        let cors = ServerCommonCors {
+            enabled: true,
+            allowed_origins: Some(vec!["*".into()]),
+            allow_credentials: Some(true),
+            ..Default::default()
+        };
+
+        let result = cors.to_cors_layer();
+        assert!(result.is_err());
+        assert!(
+            result
+                .err()
+                .map(|e| e.to_string().contains("wildcard origin"))
+                .unwrap_or(false)
+        );
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/config/types.rs` around lines 308 - 325, Add a unit test that verifies
ServerCommonCors::to_cors_layer rejects the combination of origin "*" with
allow_credentials set to true (the case that previously panicked); create a new
test (e.g., to_cors_layer_rejects_wildcard_with_credentials) that constructs
ServerCommonCors with allowed_origins = Some(vec!["*".into()]) and
allow_credentials = Some(true), calls to_cors_layer(), and asserts the result is
Err (assert!(result.is_err())) and that the error message contains a clear token
(e.g., "wildcard" or "credentials") to ensure the guard prevents a panic rather
than letting the test crash.
Cargo.toml (1)

140-140: 💤 Low value

Consider adding default-features = false for consistency with other tower crates.

The sibling tower entry on Line 132 uses default-features = false, features = ["util"]. Applying the same pattern to tower-http ensures only the explicitly requested cors feature surface is compiled in.

🔧 Suggested change
-tower-http = { version = "0.6.10", features = ["cors"] }
+tower-http = { version = "0.6.10", default-features = false, features = ["cors"] }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Cargo.toml` at line 140, Update the tower-http dependency declaration to
mirror the sibling tower entry by disabling default features: change the
tower-http dependency to include default-features = false while keeping features
= ["cors"] so only the cors feature is enabled; locate the existing tower-http =
{ version = "0.6.10", features = ["cors"] } line and add default-features =
false to that table.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config.yaml`:
- Around line 23-29: Update the example CORS config to avoid the wildcard-origin
+ credentials combination that panics: change cors.allowed_origins from ["*"] to
a specific origin (e.g., ["http://localhost:3000"]) if cors.allow_credentials is
true, or set cors.allow_credentials to false if you want to keep a wildcard;
ensure this matches the expectations in the to_cors_layer() code that constructs
the tower-http CORS middleware (so cors.allowed_origins and
cors.allow_credentials are consistent and do not trigger the Any +
allow_credentials panic).

In `@src/config/types.rs`:
- Around line 62-103: The to_cors_layer implementation on ServerCommonCors
currently sets allow_credentials before processing allowed_origins which causes
tower-http to panic when AllowOrigin::any() is later applied; change the logic
to first parse allowed_origins (using Self::parse_cors_values and checking for
"*" / AllowOrigin::any()) and if the parsed origins indicate a wildcard and
self.allow_credentials.unwrap_or(false) is true, return an Err explaining the
invalid combination, otherwise build the CorsLayer with the parsed AllowOrigin
and only then apply allow_credentials (or apply allow_credentials false) so that
AllowOrigin::any() is never combined with allow_credentials(true); update
references in the flow around allowed_origins, allow_credentials,
AllowOrigin::any, and to_cors_layer accordingly.

---

Nitpick comments:
In `@Cargo.toml`:
- Line 140: Update the tower-http dependency declaration to mirror the sibling
tower entry by disabling default features: change the tower-http dependency to
include default-features = false while keeping features = ["cors"] so only the
cors feature is enabled; locate the existing tower-http = { version = "0.6.10",
features = ["cors"] } line and add default-features = false to that table.

In `@src/config/types.rs`:
- Around line 308-325: Add a unit test that verifies
ServerCommonCors::to_cors_layer rejects the combination of origin "*" with
allow_credentials set to true (the case that previously panicked); create a new
test (e.g., to_cors_layer_rejects_wildcard_with_credentials) that constructs
ServerCommonCors with allowed_origins = Some(vec!["*".into()]) and
allow_credentials = Some(true), calls to_cors_layer(), and asserts the result is
Err (assert!(result.is_err())) and that the error message contains a clear token
(e.g., "wildcard" or "credentials") to ensure the guard prevents a panic rather
than letting the test crash.

In `@src/proxy/mod.rs`:
- Around line 26-27: Remove the now-stale #[allow(dead_code)] attribute on the
config field: open the struct containing "config: Arc<Config>" (the same struct
whose instance is referenced as state.config) and delete the #[allow(dead_code)]
line so the compiler will validate usage normally; no other code changes are
required since state.config is accessed elsewhere in the file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 12774070-de7d-4b9d-aa4d-3c507a316234

📥 Commits

Reviewing files that changed from the base of the PR and between bb8c0c9 and 3b6ab5b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • Cargo.toml
  • config.yaml
  • src/admin/mod.rs
  • src/config/types.rs
  • src/lib.rs
  • src/proxy/mod.rs

Comment thread config.yaml Outdated
Comment thread src/config/types.rs
@bzp2010 bzp2010 merged commit ee56b20 into main May 8, 2026
3 checks passed
@bzp2010 bzp2010 deleted the bzp/feat-cors branch May 8, 2026 01:59
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.

1 participant