mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-10-31 10:37:24 -04: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
					
				| @ -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 | ||||
| 	// defined as example.com/foo appears as /blog instead of /foo/blog. | ||||
| 	if pathPrefix != "/" { | ||||
| 		r.URL.Path = strings.TrimPrefix(r.URL.Path, pathPrefix) | ||||
| 		if !strings.HasPrefix(r.URL.Path, "/") { | ||||
| 			r.URL.Path = "/" + r.URL.Path | ||||
| 		} | ||||
| 		r.URL = trimPathPrefix(r.URL, pathPrefix) | ||||
| 	} | ||||
| 
 | ||||
| 	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. | ||||
| func (s *Server) Address() string { | ||||
| 	return s.Server.Addr | ||||
|  | ||||
| @ -16,6 +16,7 @@ package httpserver | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"testing" | ||||
| 	"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) { | ||||
| 	for name, c := range map[string]struct { | ||||
| 		group  []*SiteConfig | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user