From 344017dc21e80380447eedf515bbc3389451a672 Mon Sep 17 00:00:00 2001 From: Tw Date: Mon, 17 Apr 2017 11:00:36 +0800 Subject: [PATCH] proxy: use untouched URL for concatenating Signed-off-by: Tw --- caddyhttp/proxy/proxy_test.go | 18 ++++++++++++++---- caddyhttp/proxy/reverseproxy.go | 9 ++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/caddyhttp/proxy/proxy_test.go b/caddyhttp/proxy/proxy_test.go index f8c96dd83..b4280548b 100644 --- a/caddyhttp/proxy/proxy_test.go +++ b/caddyhttp/proxy/proxy_test.go @@ -26,6 +26,7 @@ import ( "github.com/mholt/caddy/caddyfile" "github.com/mholt/caddy/caddyhttp/httpserver" + "github.com/mholt/caddy/caddyhttp/staticfiles" "golang.org/x/net/websocket" ) @@ -896,10 +897,11 @@ func basicAuthTestcase(t *testing.T, upstreamUser, clientUser *url.Userinfo) { func TestProxyDirectorURL(t *testing.T) { for i, c := range []struct { - requestURL string - targetURL string - without string - expectURL string + originalPath string + requestURL string + targetURL string + without string + expectURL string }{ { requestURL: `http://localhost:2020/test`, @@ -969,6 +971,12 @@ func TestProxyDirectorURL(t *testing.T) { targetURL: `https://localhost:2021/%2C`, expectURL: `https://localhost:2021/%2C/%2C`, }, + { + originalPath: `///test`, + requestURL: `http://localhost:2020/%2F/test`, + targetURL: `https://localhost:2021/`, + expectURL: `https://localhost:2021/%2F/test`, + }, } { targetURL, err := url.Parse(c.targetURL) if err != nil { @@ -980,6 +988,8 @@ func TestProxyDirectorURL(t *testing.T) { t.Errorf("case %d failed to create request: %s", i, err) continue } + req = req.WithContext(context.WithValue(req.Context(), + staticfiles.URLPathCtxKey, c.originalPath)) NewSingleHostReverseProxy(targetURL, c.without, 0).Director(req) if expect, got := c.expectURL, req.URL.String(); expect != got { diff --git a/caddyhttp/proxy/reverseproxy.go b/caddyhttp/proxy/reverseproxy.go index 336f92942..ad0381ff5 100644 --- a/caddyhttp/proxy/reverseproxy.go +++ b/caddyhttp/proxy/reverseproxy.go @@ -25,6 +25,7 @@ import ( "golang.org/x/net/http2" "github.com/mholt/caddy/caddyhttp/httpserver" + "github.com/mholt/caddy/caddyhttp/staticfiles" ) var ( @@ -154,7 +155,13 @@ func NewSingleHostReverseProxy(target *url.URL, without string, keepalive int) * prefer(target.RawPath, target.Path), prefer(req.URL.RawPath, req.URL.Path)) } - req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) + untouchedPath, _ := req.Context().Value(staticfiles.URLPathCtxKey).(string) + req.URL.Path = singleJoiningSlash(target.Path, + prefer(untouchedPath, req.URL.Path)) + // req.URL.Path must be consistent with decoded form of req.URL.RawPath if any + if req.URL.RawPath != "" && req.URL.RawPath != req.URL.EscapedPath() { + panic("RawPath doesn't match Path") + } // Trims the path of the socket from the URL path. // This is done because req.URL passed to your proxied service