diff --git a/apidef/api_definitions.go b/apidef/api_definitions.go index 4a54845ee61..004adaf33b4 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"` + TargetURLDontStripSlash bool `bson:"target_url_dont_strip_slash" json:"target_url_dont_strip_slash"` 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..24fc9a5bebe 100644 --- a/reverse_proxy.go +++ b/reverse_proxy.go @@ -234,9 +234,11 @@ 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) + fmt.Println(spec.Proxy.TargetURLDontStripSlash) + req.URL.Path = singleJoiningSlash(targetToUse.Path, req.URL.Path, spec.Proxy.TargetURLDontStripSlash) + fmt.Println(req.URL.Path) if req.URL.RawPath != "" { - req.URL.RawPath = singleJoiningSlash(targetToUse.Path, req.URL.RawPath) + req.URL.RawPath = singleJoiningSlash(targetToUse.Path, req.URL.RawPath, spec.Proxy.TargetURLDontStripSlash) } } if !spec.Proxy.PreserveHostHeader { @@ -317,7 +319,10 @@ func defaultTransport() *http.Transport { } } -func singleJoiningSlash(a, b string) string { +func singleJoiningSlash(a, b string, dontStripTargetSlash bool) string { + if dontStripTargetSlash && 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) }