Sort ServeMux entries by length
This commit is contained in:
parent
eb8c9e0c03
commit
99b50e6caf
@ -30,14 +30,20 @@ func main() {
|
||||
}
|
||||
|
||||
mux := &gemini.ServeMux{}
|
||||
mux.HandleFunc("/cert", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
||||
rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required")
|
||||
})
|
||||
mux.HandleFunc("/", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
||||
log.Printf("Request from %s for %s with certificates %v", req.RemoteAddr.String(), req.URL.String(), req.TLS.PeerCertificates)
|
||||
rw.WriteHeader(gemini.StatusSuccess, "text/gemini")
|
||||
rw.Write([]byte("You requested " + req.URL.String()))
|
||||
})
|
||||
// mux.HandleFunc("/", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
||||
// log.Printf("Request from %s for %s with certificates %v", req.RemoteAddr.String(), req.URL.String(), req.TLS.PeerCertificates)
|
||||
// rw.WriteHeader(gemini.StatusSuccess, "text/gemini")
|
||||
// rw.Write([]byte("You requested " + req.URL.String()))
|
||||
// })
|
||||
// mux.HandleFunc("/cert", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
||||
// rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required")
|
||||
// })
|
||||
|
||||
mux.HandleFunc("https://example.com/path", nil)
|
||||
mux.HandleFunc("http://example.com/path", nil)
|
||||
mux.HandleFunc("example.com/path", nil)
|
||||
mux.HandleFunc("/path", nil)
|
||||
mux.HandleFunc("/longpath", nil)
|
||||
|
||||
server := gemini.Server{
|
||||
TLSConfig: config,
|
||||
|
47
gemini.go
47
gemini.go
@ -9,6 +9,7 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -437,12 +438,14 @@ func (m *ServeMux) Handle(pattern string, handler Handler) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.entries = append(m.entries, muxEntry{
|
||||
e := muxEntry{
|
||||
url.Scheme,
|
||||
url.Host,
|
||||
url.Path,
|
||||
handler,
|
||||
})
|
||||
}
|
||||
m.entries = appendSorted(m.entries, e)
|
||||
log.Print(m.entries)
|
||||
}
|
||||
|
||||
// HandleFunc registers a HandlerFunc for the given pattern.
|
||||
@ -461,6 +464,46 @@ func (m *ServeMux) Serve(rw *ResponseWriter, req *Request) {
|
||||
h.Serve(rw, req)
|
||||
}
|
||||
|
||||
// appendSorted appends the entry e in the proper place in entries.
|
||||
func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
|
||||
n := len(es)
|
||||
// sort by length
|
||||
i := sort.Search(n, func(i int) bool {
|
||||
// Sort entries by length.
|
||||
// - 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.
|
||||
//
|
||||
// Long version:
|
||||
// if es[i].scheme != "" {
|
||||
// if e.scheme == "" {
|
||||
// return false
|
||||
// }
|
||||
// return len(es[i].scheme) < len(e.scheme)
|
||||
// }
|
||||
// if es[i].host != "" {
|
||||
// if e.host == "" {
|
||||
// return false
|
||||
// }
|
||||
// return len(es[i].host) < len(e.host)
|
||||
// }
|
||||
// return len(es[i].path) < len(e.path)
|
||||
|
||||
// Condensed version:
|
||||
return (es[i].scheme == "" || (e.scheme != "" && len(es[i].scheme) < len(e.scheme))) &&
|
||||
(es[i].host == "" || (e.host != "" && len(es[i].host) < len(e.host))) &&
|
||||
len(es[i].path) < len(e.path)
|
||||
})
|
||||
if i == n {
|
||||
return append(es, e)
|
||||
}
|
||||
// we now know that i points at where we want to insert
|
||||
es = append(es, muxEntry{}) // try to grow the slice in place, any entry works.
|
||||
copy(es[i+1:], es[i:]) // Move shorter entries down
|
||||
es[i] = e
|
||||
return es
|
||||
}
|
||||
|
||||
// A wrapper around a bare function that implements Handler.
|
||||
type HandlerFunc func(*ResponseWriter, *Request)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user