Proposal Details
right now it's very inefficient to have wrappers that uses Handler
because for some reason it refuses to set the pattern matches and items on the request itself
we should change it so ServeHTTP calls handler, and for people who want to use Handler
directly for their own middleware building, they don't need to basically force the server to run pathmatching twice
e.g. Example code that adds a top level middleware around requests (where m
is a ServeMux`)
h, matchedPattern := m.ServeMux.Handler(r)
if m.notFoundHandler != nil && (h == nil || matchedPattern == "") {
m.notFoundHandler.ServeHTTP(w, r)
} else {
if m.httpHandler != nil {
h = m.httpHandler(h)
}
h.ServeHTTP(w, r)
}
This will fail because r
doesn't have any of the pattern match data and we can't call it or set it ourselves because findMatch
is private, and even if findMatch
wasn't private r.pat
and r.matches
are private.
Honestly I don't see why any of these are private. if it's about foot-guns, my response would be it's not the packages responsibility to stop me from breaking things if I want to touch the low levels.
IMO we should have a public method that calls findMatch
and does exactly what ServeHTTP
does for assigning request data.
if changing Handler
is out of the question because it would break something to assign the data, then maybe a new function PrepareHandler
that does and ServeHTTP can also use that method so it's DRY
// PrepareHandler finds the handler that most closely matches
// the request and prepares the request with PathData
// then returns the handler
func (mux *ServeMux) PrepareHandler(r *Request) h Handler {
if use121 {
h, _ = mux.mux121.findHandler(r)
} else {
h, r.Pattern, r.pat, r.matches = mux.findHandler(r)
}
return h
}
// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(StatusBadRequest)
return
}
h := PrepareHandler(r)
h.ServeHTTP(w, r)
}
Comment From: gabyhelp
Related Issues
- net/http: expose matched pattern in Request #66405 (closed)
- net/http: avoid casting and extra function calling (http.HandleFunc, http.DefaultServeMux.HandleFunc) #25706 (closed)
- net/http: ServeMux.Handler does not populate named path wildcards #69623 (closed)
- http.ServeMux could allow a user specified default handler #263 (closed)
- net/http: enhanced ServeMux routing #61410 (closed)
- net/http: cannot register ServeMux handler for all CONNECT requests regardless of host or path #9561 (closed)
Related Documentation
- Package http > type ServeMux > func (*ServeMux) Handle
- Package http > type ServeMux > func (*ServeMux) Handler 1.1
- Package http > func HandleFunc
Related Discussions
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)