mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
* Trim path prefix using EscapedPath() * clarify comments * Added Tests for trimPathPrefix * Ensure path with trailing slash is properly trimmed * Updated tests to match prepatch behaviour * Updated tests to match prepatch behaviour * call parse on url rather than instance * add additional tests * return unmodified url if error. Additional tests
This commit is contained in:
parent
986d4ffe3d
commit
faa5248d1f
2 changed files with 105 additions and 4 deletions
|
@ -413,15 +413,27 @@ func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) (int, error)
|
||||||
// the URL path, so a request to example.com/foo/blog on the site
|
// the URL path, so a request to example.com/foo/blog on the site
|
||||||
// defined as example.com/foo appears as /blog instead of /foo/blog.
|
// defined as example.com/foo appears as /blog instead of /foo/blog.
|
||||||
if pathPrefix != "/" {
|
if pathPrefix != "/" {
|
||||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, pathPrefix)
|
r.URL = trimPathPrefix(r.URL, pathPrefix)
|
||||||
if !strings.HasPrefix(r.URL.Path, "/") {
|
|
||||||
r.URL.Path = "/" + r.URL.Path
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return vhost.middlewareChain.ServeHTTP(w, r)
|
return vhost.middlewareChain.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func trimPathPrefix(u *url.URL, prefix string) *url.URL {
|
||||||
|
// We need to use URL.EscapedPath() when trimming the pathPrefix as
|
||||||
|
// URL.Path is ambiguous about / or %2f - see docs. See #1927
|
||||||
|
trimmed := strings.TrimPrefix(u.EscapedPath(), prefix)
|
||||||
|
if !strings.HasPrefix(trimmed, "/") {
|
||||||
|
trimmed = "/" + trimmed
|
||||||
|
}
|
||||||
|
trimmedURL, err := url.Parse(trimmed)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Unable to parse trimmed URL %s: %v", trimmed, err)
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
return trimmedURL
|
||||||
|
}
|
||||||
|
|
||||||
// Address returns the address s was assigned to listen on.
|
// Address returns the address s was assigned to listen on.
|
||||||
func (s *Server) Address() string {
|
func (s *Server) Address() string {
|
||||||
return s.Server.Addr
|
return s.Server.Addr
|
||||||
|
|
|
@ -16,6 +16,7 @@ package httpserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -126,6 +127,94 @@ func TestMakeHTTPServerWithTimeouts(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTrimPathPrefix(t *testing.T) {
|
||||||
|
for i, pt := range []struct {
|
||||||
|
path string
|
||||||
|
prefix string
|
||||||
|
expected string
|
||||||
|
shouldFail bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
path: "/my/path",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/path",
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/my/%2f/path",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/%2f/path",
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/my/path",
|
||||||
|
prefix: "/my/",
|
||||||
|
expected: "/path",
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/my///path",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/path",
|
||||||
|
shouldFail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/my///path",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "///path",
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/my/path///slash",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/path///slash",
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/my/%2f/path/%2f",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/%2f/path/%2f",
|
||||||
|
shouldFail: false,
|
||||||
|
}, {
|
||||||
|
path: "/my/%20/path",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/%20/path",
|
||||||
|
shouldFail: false,
|
||||||
|
}, {
|
||||||
|
path: "/path",
|
||||||
|
prefix: "",
|
||||||
|
expected: "/path",
|
||||||
|
shouldFail: false,
|
||||||
|
}, {
|
||||||
|
path: "/path/my/",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/path/my/",
|
||||||
|
shouldFail: false,
|
||||||
|
}, {
|
||||||
|
path: "",
|
||||||
|
prefix: "/my",
|
||||||
|
expected: "/",
|
||||||
|
shouldFail: false,
|
||||||
|
}, {
|
||||||
|
path: "/apath",
|
||||||
|
prefix: "",
|
||||||
|
expected: "/apath",
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
|
||||||
|
u, _ := url.Parse(pt.path)
|
||||||
|
if got, want := trimPathPrefix(u, pt.prefix), pt.expected; got.EscapedPath() != want {
|
||||||
|
if !pt.shouldFail {
|
||||||
|
|
||||||
|
t.Errorf("Test %d: Expected='%s', but was '%s' ", i, want, got.EscapedPath())
|
||||||
|
}
|
||||||
|
} else if pt.shouldFail {
|
||||||
|
t.Errorf("SHOULDFAIL Test %d: Expected='%s', and was '%s' but should fail", i, want, got.EscapedPath())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMakeHTTPServerWithHeaderLimit(t *testing.T) {
|
func TestMakeHTTPServerWithHeaderLimit(t *testing.T) {
|
||||||
for name, c := range map[string]struct {
|
for name, c := range map[string]struct {
|
||||||
group []*SiteConfig
|
group []*SiteConfig
|
||||||
|
|
Loading…
Reference in a new issue