]> Cypherpunks repositories - gostls13.git/commitdiff
http: make serveFile redirects relative to work with StripPrefix
authorAndrew Balholm <andybalholm@gmail.com>
Thu, 28 Jul 2011 18:43:16 +0000 (11:43 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 28 Jul 2011 18:43:16 +0000 (11:43 -0700)
serveFile was using absolute redirects, which didn't work under StripPrefix.
Now it uses relative redirects.

R=golang-dev, rsc, bradfitz
CC=golang-dev, kevlar
https://golang.org/cl/4789042

src/pkg/http/fs.go
src/pkg/http/fs_test.go

index bd5ff8bc68c2da7e949b054a625f11e4f549fb61..26d9311370d9c467081d47051457af4baecdb8b6 100644 (file)
@@ -102,8 +102,10 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
        const indexPage = "/index.html"
 
        // redirect .../index.html to .../
+       // can't use Redirect() because that would make the path absolute,
+       // which would be a problem running under StripPrefix
        if strings.HasSuffix(r.URL.Path, indexPage) {
-               Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len(indexPage)+1], StatusMovedPermanently)
+               localRedirect(w, r, "./")
                return
        }
 
@@ -128,12 +130,12 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
                url := r.URL.Path
                if d.IsDirectory() {
                        if url[len(url)-1] != '/' {
-                               Redirect(w, r, url+"/", StatusMovedPermanently)
+                               localRedirect(w, r, path.Base(url)+"/")
                                return
                        }
                } else {
                        if url[len(url)-1] == '/' {
-                               Redirect(w, r, url[0:len(url)-1], StatusMovedPermanently)
+                               localRedirect(w, r, "../"+path.Base(url))
                                return
                        }
                }
@@ -221,6 +223,16 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
        }
 }
 
+// localRedirect gives a Moved Permanently response.
+// It does not convert relative paths to absolute paths like Redirect does.
+func localRedirect(w ResponseWriter, r *Request, newPath string) {
+       if q := r.URL.RawQuery; q != "" {
+               newPath += "?" + q
+       }
+       w.Header().Set("Location", newPath)
+       w.WriteHeader(StatusMovedPermanently)
+}
+
 // ServeFile replies to the request with the contents of the named file or directory.
 func ServeFile(w ResponseWriter, r *Request, name string) {
        dir, file := filepath.Split(name)
index c714795dcfa800d25115a092ea5c443b9ce6f7e0..4d465d89a675b8e5ac9e695371b33a63fce7bb88 100644 (file)
@@ -87,6 +87,30 @@ func TestServeFile(t *testing.T) {
        }
 }
 
+var fsRedirectTestData = []struct {
+       original, redirect string
+}{
+       {"/test/index.html", "/test/"},
+       {"/test/testdata", "/test/testdata/"},
+       {"/test/testdata/file/", "/test/testdata/file"},
+}
+
+func TestFSRedirect(t *testing.T) {
+       ts := httptest.NewServer(StripPrefix("/test", FileServer(Dir("."))))
+       defer ts.Close()
+
+       for _, data := range fsRedirectTestData {
+               res, err := Get(ts.URL + data.original)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               res.Body.Close()
+               if g, e := res.Request.URL.Path, data.redirect; g != e {
+                       t.Errorf("redirect from %s: got %s, want %s", data.original, g, e)
+               }
+       }
+}
+
 type testFileSystem struct {
        open func(name string) (File, os.Error)
 }