Fix mux URL sorting logic

This commit is contained in:
adnano 2020-09-28 15:33:15 -04:00
parent 744884127c
commit 5a07b49ef5
2 changed files with 34 additions and 16 deletions

View File

@ -24,13 +24,18 @@ func TestServeMuxEntryOrder(t *testing.T) {
// Shuffle input // Shuffle input
a := make([]string, len(expected)) a := make([]string, len(expected))
copy(expected, a) copy(a, expected)
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] }) rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
mux := &ServeMux{} mux := &ServeMux{}
for _, s := range a { for _, s := range a {
mux.Handle(s, nil) mux.Handle(s, NotFoundHandler())
var es string
for i := range mux.es {
es += mux.es[i].u.String() + " "
}
t.Logf(es)
} }
for i, e := range mux.es { for i, e := range mux.es {
s := e.u.String() s := e.u.String()

View File

@ -454,10 +454,9 @@ func isSlashRune(r rune) bool { return r == '/' || r == '\\' }
// header, stripping the port number and redirecting any request containing . or // header, stripping the port number and redirecting any request containing . or
// .. elements or repeated slashes to an equivalent, cleaner URL. // .. elements or repeated slashes to an equivalent, cleaner URL.
type ServeMux struct { type ServeMux struct {
mu sync.RWMutex mu sync.RWMutex
m map[string]muxEntry m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest. es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
} }
type muxEntry struct { type muxEntry struct {
@ -646,13 +645,9 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
} }
e := muxEntry{h: handler, pattern: pattern, u: url} e := muxEntry{h: handler, pattern: pattern, u: url}
mux.m[pattern] = e mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' { // if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e) mux.es = appendSorted(mux.es, e)
} // }
if pattern[0] != '/' {
mux.hosts = true
}
} }
func appendSorted(es []muxEntry, e muxEntry) []muxEntry { func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
@ -662,9 +657,27 @@ func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
// - Entries with a scheme take preference over entries without. // - Entries with a scheme take preference over entries without.
// - Entries with a host take preference over entries without. // - Entries with a host take preference over entries without.
// - Longer paths take preference over shorter paths. // - Longer paths take preference over shorter paths.
return (es[i].u.Scheme == "" || (e.u.Scheme != "" && len(es[i].u.Scheme) < len(e.u.Scheme))) && if e.u.Scheme != "" {
(es[i].u.Host == "" || (e.u.Host != "" && len(es[i].u.Host) < len(e.u.Host))) && if es[i].u.Scheme == "" {
len(es[i].u.Path) < len(e.u.Path) return true
}
if es[i].u.Scheme != e.u.Scheme {
return len(es[i].u.Scheme) < len(e.u.Scheme)
}
} else if es[i].u.Scheme != "" {
return false
}
if e.u.Host != "" {
if es[i].u.Host == "" {
return true
}
if es[i].u.Host != e.u.Host {
return len(es[i].u.Scheme) < len(e.u.Scheme)
}
} else if es[i].u.Host != "" {
return false
}
return len(es[i].u.Path) < len(e.u.Path)
}) })
if i == n { if i == n {
return append(es, e) return append(es, e)