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
a := make([]string, len(expected))
copy(expected, a)
copy(a, expected)
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
mux := &ServeMux{}
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 {
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
// .. elements or repeated slashes to an equivalent, cleaner URL.
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest.
hosts bool // whether any patterns contain hostnames
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry // slice of entries sorted from longest to shortest.
}
type muxEntry struct {
@ -646,13 +645,9 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
}
e := muxEntry{h: handler, pattern: pattern, u: url}
mux.m[pattern] = e
if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
}
if pattern[0] != '/' {
mux.hosts = true
}
// if pattern[len(pattern)-1] == '/' {
mux.es = appendSorted(mux.es, e)
// }
}
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 host take preference over entries without.
// - Longer paths take preference over shorter paths.
return (es[i].u.Scheme == "" || (e.u.Scheme != "" && len(es[i].u.Scheme) < len(e.u.Scheme))) &&
(es[i].u.Host == "" || (e.u.Host != "" && len(es[i].u.Host) < len(e.u.Host))) &&
len(es[i].u.Path) < len(e.u.Path)
if e.u.Scheme != "" {
if es[i].u.Scheme == "" {
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 {
return append(es, e)