Skip to content

Fix 301 redirect of non-trailing-slash GETs breaking /openapi/v2 and /openapi/v3 - #32

Open
shahab96 wants to merge 2 commits into
netbirdio:mainfrom
shahab96:fix/openapi-redirect
Open

Fix 301 redirect of non-trailing-slash GETs breaking /openapi/v2 and /openapi/v3#32
shahab96 wants to merge 2 commits into
netbirdio:mainfrom
shahab96:fix/openapi-redirect

Conversation

@shahab96

@shahab96 shahab96 commented Jul 21, 2026

Copy link
Copy Markdown

Summary

Fixes #31

When the proxy is configured with a --kubernetes-api-server URL that has an empty path (e.g. https://kubernetes.default.svc.cluster.local — the ClusterProxy CRD default in kubernetes-operator <= v0.7.0), UpgradeAwareHandler.ServeHTTP 301-redirects every GET/HEAD whose path does not end in / to its trailing-slash form, instead of proxying it. This comes from proxyRedirectsforRootPath in k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go (a legacy workaround for https://issue.k8s.io/4958), which fires whenever Location.Path is empty.

Most API discovery endpoints tolerate this because the API server also serves their trailing-slash variants (/api/, /apis/, /version/), but /openapi/v2 and /openapi/v3 are exact-path handlers, so the redirected requests 404. This breaks clients that need the OpenAPI document through the proxy, e.g. Terraform's kubernetes_manifest resource ("failed get OpenAPI spec") and kubectl apply client-side validation.

Changes

  • internal/proxy/proxy.go: normalize the target URL in proxyHandler so the Location passed to UpgradeAwareHandler always has a non-empty path (/ when empty), which avoids the redirect branch entirely. Done at the use site so it is robust regardless of how the URL was provided (flag default, operator CR, etc.).
  • internal/proxy/proxy_test.go: the proxy handler test now parses the test server URL without a manually appended trailing slash, providing regression coverage. Without the fix, the test fails with 301 responses instead of 200.

Testing

  • go test ./... — passes
  • go vet ./... — clean
  • gofmt — clean
  • Verified the test reproduces the reported behavior when the fix is reverted (301 Moved Permanently instead of proxying the request)

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed proxy handling of Kubernetes API requests when the base server URL has no path, preventing incorrect redirect behavior.
    • Ensured exact-path endpoints like /openapi/v2 and /openapi/v3 are proxied correctly without being redirected to trailing-slash routes.
  • Tests
    • Expanded proxy handler test coverage to validate valid Kubernetes target paths and correct 404 behavior for unsupported paths.

UpgradeAwareHandler 301-redirects any GET or HEAD request to its
trailing-slash form when the target location path is empty, as a
workaround for https://issue.k8s.io/4958. When the proxy is configured
with a kubernetes-api-server URL without a trailing slash (the default
in kubernetes-operator <= v0.7.0 ClusterProxy CRs), every such request
is redirected instead of proxied.

Most API discovery endpoints tolerate this because the API server also
serves their trailing-slash variants (/api/, /apis/, /version/), but
/openapi/v2 and /openapi/v3 are exact-path handlers, so the redirected
requests return 404. This breaks clients that need the OpenAPI document
through the proxy, e.g. Terraform's kubernetes_manifest resource
("failed get OpenAPI spec") and kubectl apply client-side validation.

Ensure the location passed to UpgradeAwareHandler always has a
non-empty path, and update the proxy handler test to use an empty-path
target URL as regression coverage.
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

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: 33efdd05-ea2c-422f-a83d-baf2692a2dc1

📥 Commits

Reviewing files that changed from the base of the PR and between 89e07d1 and 7556c0e.

📒 Files selected for processing (1)
  • internal/proxy/proxy_test.go

📝 Walkthrough

Walkthrough

The proxy handler copies and normalizes the Kubernetes API server URL before constructing the upgrade-aware handler. Tests preserve an empty target path and verify exact OpenAPI endpoints proxy without trailing-slash redirects.

Changes

Proxy path normalization

Layer / File(s) Summary
Normalize target path and regression coverage
internal/proxy/proxy.go, internal/proxy/proxy_test.go
The handler sets an empty target path to /, while tests cover /version, /openapi/v2, and /openapi/v3 using an empty-path target URL.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: phillebaba

Poem

I’m a rabbit with routes in my den,
No crooked redirects again.
An empty path grows /,
OpenAPI knocks at the door,
And hops straight through—amen!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the proxy redirect fix for exact-path OpenAPI endpoints.
Linked Issues check ✅ Passed The proxy now normalizes empty target paths and adds regression tests for /openapi/v2 and /openapi/v3, matching the linked issue goals.
Out of Scope Changes check ✅ Passed The changes stay focused on the redirect bug fix and related test coverage, with no obvious unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/proxy/proxy_test.go (1)

81-86: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add explicit OpenAPI endpoint cases.

The regression test currently exercises only /version. Add requests for /openapi/v2 and /openapi/v3 (and HEAD if applicable) so the stated client-facing contract is covered directly, not only via a generic path.

🤖 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 `@internal/proxy/proxy_test.go` around lines 81 - 86, Add explicit
regression-test requests for /openapi/v2 and /openapi/v3 alongside the existing
/version coverage in the test using kubeAPIServerURL and UpgradeAwareHandler;
include corresponding HEAD requests if the test covers HEAD behavior, and assert
they are served without trailing-slash redirects.
🤖 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.

Nitpick comments:
In `@internal/proxy/proxy_test.go`:
- Around line 81-86: Add explicit regression-test requests for /openapi/v2 and
/openapi/v3 alongside the existing /version coverage in the test using
kubeAPIServerURL and UpgradeAwareHandler; include corresponding HEAD requests if
the test covers HEAD behavior, and assert they are served without trailing-slash
redirects.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 831939c4-f2aa-4aff-8a38-97aad5fe4a19

📥 Commits

Reviewing files that changed from the base of the PR and between e648b63 and 89e07d1.

📒 Files selected for processing (2)
  • internal/proxy/proxy.go
  • internal/proxy/proxy_test.go

/version alone does not mirror the production failure mode, since the
API server also serves its trailing-slash variant. The OpenAPI
endpoints are exact-path handlers, so extend the test backend to serve
/openapi/v2 and /openapi/v3 only at their exact paths and add cases
asserting they are proxied without a trailing-slash redirect.
@shahab96

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

Proxy 301-redirects non-trailing-slash GETs, breaking /openapi/v2 and /openapi/v3 (Terraform kubernetes_manifest, kubectl apply validation)

1 participant