From ceb576ea017d434c92d3413e8d5b5aae09c7c0b8 Mon Sep 17 00:00:00 2001 From: joshblakeley Date: Thu, 8 Nov 2018 14:32:49 +0000 Subject: [PATCH] optionally dont strip target url trailing slash in reverse proxy --- apidef/api_definitions.go | 1 + reverse_proxy.go | 9 ++++++--- reverse_proxy_test.go | 20 +++++++++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apidef/api_definitions.go b/apidef/api_definitions.go index 4a54845ee61..a76d451edae 100644 --- a/apidef/api_definitions.go +++ b/apidef/api_definitions.go @@ -377,6 +377,7 @@ type APIDefinition struct { PreserveHostHeader bool `bson:"preserve_host_header" json:"preserve_host_header"` ListenPath string `bson:"listen_path" json:"listen_path"` TargetURL string `bson:"target_url" json:"target_url"` + DisableStripPrefix bool `bson:"disable_strip_prefix" json:"disable_strip_prefix"` StripListenPath bool `bson:"strip_listen_path" json:"strip_listen_path"` EnableLoadBalancing bool `bson:"enable_load_balancing" json:"enable_load_balancing"` Targets []string `bson:"target_list" json:"target_list"` diff --git a/reverse_proxy.go b/reverse_proxy.go index 5e5423e9ec4..e5d39259460 100644 --- a/reverse_proxy.go +++ b/reverse_proxy.go @@ -234,9 +234,9 @@ func TykNewSingleHostReverseProxy(target *url.URL, spec *APISpec) *ReverseProxy if targetToUse == target { req.URL.Scheme = targetToUse.Scheme req.URL.Host = targetToUse.Host - req.URL.Path = singleJoiningSlash(targetToUse.Path, req.URL.Path) + req.URL.Path = singleJoiningSlash(targetToUse.Path, req.URL.Path, spec.Proxy.DisableStripPrefix) if req.URL.RawPath != "" { - req.URL.RawPath = singleJoiningSlash(targetToUse.Path, req.URL.RawPath) + req.URL.RawPath = singleJoiningSlash(targetToUse.Path, req.URL.RawPath, spec.Proxy.DisableStripPrefix) } } if !spec.Proxy.PreserveHostHeader { @@ -317,7 +317,10 @@ func defaultTransport() *http.Transport { } } -func singleJoiningSlash(a, b string) string { +func singleJoiningSlash(a, b string, disableStripPrefix bool) string { + if disableStripPrefix && len(b) == 0 { + return a + } a = strings.TrimRight(a, "/") b = strings.TrimLeft(b, "/") if len(b) > 0 { diff --git a/reverse_proxy_test.go b/reverse_proxy_test.go index 92743a8ce13..266cdc86c82 100644 --- a/reverse_proxy_test.go +++ b/reverse_proxy_test.go @@ -109,7 +109,7 @@ func TestWrappedServeHTTP(t *testing.T) { } func TestSingleJoiningSlash(t *testing.T) { - tests := []struct { + testsFalse := []struct { a, b, want string }{ {"foo", "", "foo"}, @@ -119,9 +119,23 @@ func TestSingleJoiningSlash(t *testing.T) { {"foo/", "/bar", "foo/bar"}, {"foo//", "//bar", "foo/bar"}, } - for _, tc := range tests { + for _, tc := range testsFalse { + t.Run(fmt.Sprintf("%s+%s", tc.a, tc.b), func(t *testing.T) { + got := singleJoiningSlash(tc.a, tc.b, false) + if got != tc.want { + t.Fatalf("want %s, got %s", tc.want, got) + } + }) + } + testsTrue := []struct { + a, b, want string + }{ + {"foo/", "", "foo/"}, + {"foo", "", "foo"}, + } + for _, tc := range testsTrue { t.Run(fmt.Sprintf("%s+%s", tc.a, tc.b), func(t *testing.T) { - got := singleJoiningSlash(tc.a, tc.b) + got := singleJoiningSlash(tc.a, tc.b, true) if got != tc.want { t.Fatalf("want %s, got %s", tc.want, got) }