From f4b6f15e07b91976d6579c8445a3321dcc63d8ae Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Wed, 7 Jun 2017 14:40:17 -0600 Subject: [PATCH] staticfiles: Build redirect based on rewritten URL (fixes #1706) --- caddyhttp/httpserver/server.go | 2 ++ caddyhttp/staticfiles/fileserver.go | 27 +++++++++++++----------- caddyhttp/staticfiles/fileserver_test.go | 4 +++- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/caddyhttp/httpserver/server.go b/caddyhttp/httpserver/server.go index 4498f38e0..72706f750 100644 --- a/caddyhttp/httpserver/server.go +++ b/caddyhttp/httpserver/server.go @@ -352,6 +352,8 @@ func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) (int, error) // look up the virtualhost; if no match, serve error vhost, pathPrefix := s.vhosts.Match(hostname + r.URL.Path) + c := context.WithValue(r.Context(), caddy.CtxKey("path_prefix"), pathPrefix) + r = r.WithContext(c) if vhost == nil { // check for ACME challenge even if vhost is nil; diff --git a/caddyhttp/staticfiles/fileserver.go b/caddyhttp/staticfiles/fileserver.go index c44d9715d..d5cca1d3a 100644 --- a/caddyhttp/staticfiles/fileserver.go +++ b/caddyhttp/staticfiles/fileserver.go @@ -7,7 +7,6 @@ package staticfiles import ( "math/rand" "net/http" - "net/url" "os" "path" "path/filepath" @@ -82,37 +81,41 @@ func (fs FileServer) serveFile(w http.ResponseWriter, r *http.Request) (int, err // redirect to canonical path (being careful to preserve other parts of URL and // considering cases where a site is defined with a path prefix that gets stripped) - u := r.Context().Value(caddy.CtxKey("original_url")).(url.URL) - if u.Path == "" { - u.Path = "/" + urlCopy := *r.URL + pathPrefix, _ := r.Context().Value(caddy.CtxKey("path_prefix")).(string) + if pathPrefix != "/" { + urlCopy.Path = pathPrefix + urlCopy.Path + } + if urlCopy.Path == "" { + urlCopy.Path = "/" } if d.IsDir() { // ensure there is a trailing slash - if u.Path[len(u.Path)-1] != '/' { - u.Path += "/" - http.Redirect(w, r, u.String(), http.StatusMovedPermanently) + if urlCopy.Path[len(urlCopy.Path)-1] != '/' { + urlCopy.Path += "/" + http.Redirect(w, r, urlCopy.String(), http.StatusMovedPermanently) return http.StatusMovedPermanently, nil } } else { // ensure no trailing slash redir := false - if u.Path[len(u.Path)-1] == '/' { - u.Path = u.Path[:len(u.Path)-1] + if urlCopy.Path[len(urlCopy.Path)-1] == '/' { + urlCopy.Path = urlCopy.Path[:len(urlCopy.Path)-1] redir = true } // if an index file was explicitly requested, strip file name from the request // ("/foo/index.html" -> "/foo/") for _, indexPage := range IndexPages { - if strings.HasSuffix(u.Path, indexPage) { - u.Path = u.Path[:len(u.Path)-len(indexPage)] + if strings.HasSuffix(urlCopy.Path, indexPage) { + urlCopy.Path = urlCopy.Path[:len(urlCopy.Path)-len(indexPage)] redir = true break } } if redir { - http.Redirect(w, r, u.String(), http.StatusMovedPermanently) + http.Redirect(w, r, urlCopy.String(), http.StatusMovedPermanently) return http.StatusMovedPermanently, nil } } diff --git a/caddyhttp/staticfiles/fileserver_test.go b/caddyhttp/staticfiles/fileserver_test.go index d5f3a42bc..a71998a76 100644 --- a/caddyhttp/staticfiles/fileserver_test.go +++ b/caddyhttp/staticfiles/fileserver_test.go @@ -230,9 +230,11 @@ func TestServeHTTP(t *testing.T) { continue } - // set the original URL on the context + // set the original URL and path prefix on the context ctx := context.WithValue(request.Context(), caddy.CtxKey("original_url"), *request.URL) request = request.WithContext(ctx) + ctx = context.WithValue(request.Context(), caddy.CtxKey("path_prefix"), test.stripPathPrefix) + request = request.WithContext(ctx) request.Header.Add("Accept-Encoding", test.acceptEncoding)