Fix mux URL sorting logic
This commit is contained in:
parent
744884127c
commit
5a07b49ef5
@ -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()
|
||||||
|
41
server.go
41
server.go
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user