-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Description
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)
}