Sort ServeMux entries by length
This commit is contained in:
parent
eb8c9e0c03
commit
99b50e6caf
@ -30,14 +30,20 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mux := &gemini.ServeMux{}
|
mux := &gemini.ServeMux{}
|
||||||
mux.HandleFunc("/cert", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
// mux.HandleFunc("/", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
||||||
rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required")
|
// 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")
|
||||||
mux.HandleFunc("/", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
// rw.Write([]byte("You requested " + req.URL.String()))
|
||||||
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")
|
// mux.HandleFunc("/cert", func(rw *gemini.ResponseWriter, req *gemini.Request) {
|
||||||
rw.Write([]byte("You requested " + req.URL.String()))
|
// 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{
|
server := gemini.Server{
|
||||||
TLSConfig: config,
|
TLSConfig: config,
|
||||||
|
47
gemini.go
47
gemini.go
@ -9,6 +9,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -437,12 +438,14 @@ func (m *ServeMux) Handle(pattern string, handler Handler) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
m.entries = append(m.entries, muxEntry{
|
e := muxEntry{
|
||||||
url.Scheme,
|
url.Scheme,
|
||||||
url.Host,
|
url.Host,
|
||||||
url.Path,
|
url.Path,
|
||||||
handler,
|
handler,
|
||||||
})
|
}
|
||||||
|
m.entries = appendSorted(m.entries, e)
|
||||||
|
log.Print(m.entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleFunc registers a HandlerFunc for the given pattern.
|
// HandleFunc registers a HandlerFunc for the given pattern.
|
||||||
@ -461,6 +464,46 @@ func (m *ServeMux) Serve(rw *ResponseWriter, req *Request) {
|
|||||||
h.Serve(rw, req)
|
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.
|
// A wrapper around a bare function that implements Handler.
|
||||||
type HandlerFunc func(*ResponseWriter, *Request)
|
type HandlerFunc func(*ResponseWriter, *Request)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user