fix(provider): harden proxy path stripping
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
cd4e24d15f
commit
c9627729b5
4 changed files with 60 additions and 7 deletions
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-Licence-Identifier: EUPL-1.2
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
// Package provider defines the Service Provider Framework interfaces.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-Licence-Identifier: EUPL-1.2
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
package provider
|
||||
|
||||
|
|
@ -59,11 +59,10 @@ func NewProxy(cfg ProxyConfig) *ProxyProvider {
|
|||
proxy.Director = func(req *http.Request) {
|
||||
defaultDirector(req)
|
||||
// Strip the base path prefix from the request path.
|
||||
req.URL.Path = strings.TrimPrefix(req.URL.Path, basePath)
|
||||
if req.URL.Path == "" {
|
||||
req.URL.Path = "/"
|
||||
req.URL.Path = stripBasePath(req.URL.Path, basePath)
|
||||
if req.URL.RawPath != "" {
|
||||
req.URL.RawPath = stripBasePath(req.URL.RawPath, basePath)
|
||||
}
|
||||
req.URL.RawPath = strings.TrimPrefix(req.URL.RawPath, basePath)
|
||||
}
|
||||
|
||||
return &ProxyProvider{
|
||||
|
|
@ -72,6 +71,34 @@ func NewProxy(cfg ProxyConfig) *ProxyProvider {
|
|||
}
|
||||
}
|
||||
|
||||
// stripBasePath removes an exact base path prefix from a request path.
|
||||
// It only strips when the path matches the base path itself or lives under
|
||||
// the base path boundary, so "/api" will not accidentally trim "/api-v2".
|
||||
func stripBasePath(path, basePath string) string {
|
||||
basePath = strings.TrimSuffix(strings.TrimSpace(basePath), "/")
|
||||
if basePath == "" || basePath == "/" {
|
||||
if path == "" {
|
||||
return "/"
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
if path == basePath {
|
||||
return "/"
|
||||
}
|
||||
|
||||
prefix := basePath + "/"
|
||||
if strings.HasPrefix(path, prefix) {
|
||||
trimmed := strings.TrimPrefix(path, basePath)
|
||||
if trimmed == "" {
|
||||
return "/"
|
||||
}
|
||||
return trimmed
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// Name returns the provider identity.
|
||||
func (p *ProxyProvider) Name() string {
|
||||
return p.config.Name
|
||||
|
|
|
|||
26
pkg/provider/proxy_internal_test.go
Normal file
26
pkg/provider/proxy_internal_test.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
package provider
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestStripBasePath_Good_ExactBoundary(t *testing.T) {
|
||||
got := stripBasePath("/api/v1/cool-widget/items", "/api/v1/cool-widget")
|
||||
if got != "/items" {
|
||||
t.Fatalf("expected stripped path %q, got %q", "/items", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStripBasePath_Good_RootPath(t *testing.T) {
|
||||
got := stripBasePath("/api/v1/cool-widget", "/api/v1/cool-widget")
|
||||
if got != "/" {
|
||||
t.Fatalf("expected stripped root path %q, got %q", "/", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStripBasePath_Good_DoesNotTrimPartialPrefix(t *testing.T) {
|
||||
got := stripBasePath("/api/v1/cool-widget-2/items", "/api/v1/cool-widget")
|
||||
if got != "/api/v1/cool-widget-2/items" {
|
||||
t.Fatalf("expected partial prefix to remain unchanged, got %q", got)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-Licence-Identifier: EUPL-1.2
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
package provider
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue