mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
ipn/ipnlocal: fix proxy path that matches mount point (#10864)
Don't append a trailing slash to a request path to the reverse proxy that matches the mount point exactly. Updates tailscale/tailscale#10730 Signed-off-by: Irbe Krumina <irbe@tailscale.com>
This commit is contained in:
parent
8b47322acc
commit
6ee956333f
@ -605,7 +605,20 @@ func (rp *reverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
p := &httputil.ReverseProxy{Rewrite: func(r *httputil.ProxyRequest) {
|
||||
oldOutPath := r.Out.URL.Path
|
||||
r.SetURL(rp.url)
|
||||
|
||||
// If mount point matches the request path exactly, the outbound
|
||||
// request URL was set to empty string in serveWebHandler which
|
||||
// would have resulted in the outbound path set to <proxy path>
|
||||
// + '/' in SetURL. In that case, if the proxy path was set, we
|
||||
// want to send the request to the <proxy path> (without the
|
||||
// '/') .
|
||||
if oldOutPath == "" && rp.url.Path != "" {
|
||||
r.Out.URL.Path = rp.url.Path
|
||||
r.Out.URL.RawPath = rp.url.RawPath
|
||||
}
|
||||
|
||||
r.Out.Host = r.In.Host
|
||||
addProxyForwardedHeaders(r)
|
||||
rp.lb.addTailscaleIdentityHeaders(r)
|
||||
|
@ -348,7 +348,108 @@ func TestServeConfigETag(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServeHTTPProxy(t *testing.T) {
|
||||
func TestServeHTTPProxyPath(t *testing.T) {
|
||||
b := newTestBackend(t)
|
||||
// Start test serve endpoint.
|
||||
testServ := httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
// Set the request URL path to a response header, so the
|
||||
// requested URL path can be checked in tests.
|
||||
t.Logf("adding path %s", r.URL.Path)
|
||||
w.Header().Add("Path", r.URL.Path)
|
||||
},
|
||||
))
|
||||
defer testServ.Close()
|
||||
tests := []struct {
|
||||
name string
|
||||
mountPoint string
|
||||
proxyPath string
|
||||
requestPath string
|
||||
wantRequestPath string
|
||||
}{
|
||||
{
|
||||
name: "/foo -> /foo, with mount point and path /foo",
|
||||
mountPoint: "/foo",
|
||||
proxyPath: "/foo",
|
||||
requestPath: "/foo",
|
||||
wantRequestPath: "/foo",
|
||||
},
|
||||
{
|
||||
name: "/foo/ -> /foo/, with mount point and path /foo",
|
||||
mountPoint: "/foo",
|
||||
proxyPath: "/foo",
|
||||
requestPath: "/foo/",
|
||||
wantRequestPath: "/foo/",
|
||||
},
|
||||
{
|
||||
name: "/foo -> /foo/, with mount point and path /foo/",
|
||||
mountPoint: "/foo/",
|
||||
proxyPath: "/foo/",
|
||||
requestPath: "/foo",
|
||||
wantRequestPath: "/foo/",
|
||||
},
|
||||
{
|
||||
name: "/-> /, with mount point and path /",
|
||||
mountPoint: "/",
|
||||
proxyPath: "/",
|
||||
requestPath: "/",
|
||||
wantRequestPath: "/",
|
||||
},
|
||||
{
|
||||
name: "/foo -> /foo, with mount point and path /",
|
||||
mountPoint: "/",
|
||||
proxyPath: "/",
|
||||
requestPath: "/foo",
|
||||
wantRequestPath: "/foo",
|
||||
},
|
||||
{
|
||||
name: "/foo/bar -> /foo/bar, with mount point and path /foo",
|
||||
mountPoint: "/foo",
|
||||
proxyPath: "/foo",
|
||||
requestPath: "/foo/bar",
|
||||
wantRequestPath: "/foo/bar",
|
||||
},
|
||||
{
|
||||
name: "/foo/bar/baz -> /foo/bar/baz, with mount point and path /foo",
|
||||
mountPoint: "/foo",
|
||||
proxyPath: "/foo",
|
||||
requestPath: "/foo/bar/baz",
|
||||
wantRequestPath: "/foo/bar/baz",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
conf := &ipn.ServeConfig{
|
||||
Web: map[ipn.HostPort]*ipn.WebServerConfig{
|
||||
"example.ts.net:443": {Handlers: map[string]*ipn.HTTPHandler{
|
||||
tt.mountPoint: {Proxy: testServ.URL + tt.proxyPath},
|
||||
}},
|
||||
},
|
||||
}
|
||||
if err := b.SetServeConfig(conf, ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req := &http.Request{
|
||||
URL: &url.URL{Path: tt.requestPath},
|
||||
TLS: &tls.ConnectionState{ServerName: "example.ts.net"},
|
||||
}
|
||||
req = req.WithContext(context.WithValue(req.Context(), serveHTTPContextKey{}, &serveHTTPContext{
|
||||
DestPort: 443,
|
||||
SrcAddr: netip.MustParseAddrPort("1.2.3.4:1234"), // random src
|
||||
}))
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
b.serveWebHandler(w, req)
|
||||
|
||||
// Verify what path was requested
|
||||
p := w.Result().Header.Get("Path")
|
||||
if p != tt.wantRequestPath {
|
||||
t.Errorf("wanted request path %s got %s", tt.wantRequestPath, p)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestServeHTTPProxyHeaders(t *testing.T) {
|
||||
b := newTestBackend(t)
|
||||
|
||||
// Start test serve endpoint.
|
||||
|
Loading…
Reference in New Issue
Block a user