mirror of
https://github.com/golang/go
synced 2024-11-23 16:50:06 -07:00
net/http: make FileServer sort directory entries
Fixes #11879 Change-Id: If021f86b2764e01c69674e6a423699b822596f15 Reviewed-on: https://go-review.googlesource.com/14161 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
1ac84d4300
commit
25b00177af
@ -17,6 +17,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -68,24 +69,28 @@ type File interface {
|
||||
}
|
||||
|
||||
func dirList(w ResponseWriter, f File) {
|
||||
dirs, err := f.Readdir(-1)
|
||||
if err != nil {
|
||||
// TODO: log err.Error() to the Server.ErrorLog, once it's possible
|
||||
// for a handler to get at its Server via the ResponseWriter. See
|
||||
// Issue 12438.
|
||||
Error(w, "Error reading directory", StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
sort.Sort(byName(dirs))
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
fmt.Fprintf(w, "<pre>\n")
|
||||
for {
|
||||
dirs, err := f.Readdir(100)
|
||||
if err != nil || len(dirs) == 0 {
|
||||
break
|
||||
}
|
||||
for _, d := range dirs {
|
||||
name := d.Name()
|
||||
if d.IsDir() {
|
||||
name += "/"
|
||||
}
|
||||
// name may contain '?' or '#', which must be escaped to remain
|
||||
// part of the URL path, and not indicate the start of a query
|
||||
// string or fragment.
|
||||
url := url.URL{Path: name}
|
||||
fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
|
||||
for _, d := range dirs {
|
||||
name := d.Name()
|
||||
if d.IsDir() {
|
||||
name += "/"
|
||||
}
|
||||
// name may contain '?' or '#', which must be escaped to remain
|
||||
// part of the URL path, and not indicate the start of a query
|
||||
// string or fragment.
|
||||
url := url.URL{Path: name}
|
||||
fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
|
||||
}
|
||||
fmt.Fprintf(w, "</pre>\n")
|
||||
}
|
||||
@ -585,3 +590,9 @@ func sumRangesSize(ranges []httpRange) (size int64) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type byName []os.FileInfo
|
||||
|
||||
func (s byName) Len() int { return len(s) }
|
||||
func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
|
||||
func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
@ -283,6 +283,49 @@ func TestFileServerEscapesNames(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileServerSortsNames(t *testing.T) {
|
||||
defer afterTest(t)
|
||||
const contents = "I am a fake file"
|
||||
dirMod := time.Unix(123, 0).UTC()
|
||||
fileMod := time.Unix(1000000000, 0).UTC()
|
||||
fs := fakeFS{
|
||||
"/": &fakeFileInfo{
|
||||
dir: true,
|
||||
modtime: dirMod,
|
||||
ents: []*fakeFileInfo{
|
||||
{
|
||||
basename: "b",
|
||||
modtime: fileMod,
|
||||
contents: contents,
|
||||
},
|
||||
{
|
||||
basename: "a",
|
||||
modtime: fileMod,
|
||||
contents: contents,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ts := httptest.NewServer(FileServer(&fs))
|
||||
defer ts.Close()
|
||||
|
||||
res, err := Get(ts.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("Get: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("read Body: %v", err)
|
||||
}
|
||||
s := string(b)
|
||||
if !strings.Contains(s, "<a href=\"a\">a</a>\n<a href=\"b\">b</a>") {
|
||||
t.Errorf("output appears to be unsorted:\n%s", s)
|
||||
}
|
||||
}
|
||||
|
||||
func mustRemoveAll(dir string) {
|
||||
err := os.RemoveAll(dir)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user