-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Middlewares register with chi by providing a func(next http.Handler) http.Handler function that returns a http.Handler that is expected to call the given next argument to pass the request on.
When using .Group(…), chi calls the given middleware function multiple times to create copies of the middleware stack for the group, the godoc says "Group creates a new inline-Mux with a copy of middleware stack."
Returning the same instance of http.Handler for each call results in all routing being broken and all requests being passed to the last group that was registered. The request is passed to a handler within the final group even if the path does not match.
Expected behaviour: The same instance of http.Handler can be returned and the routing will be correct.
Reproduction:
Run the following server and request http://localhost/, http://localhost/foo, and http://localhost/bar.
The expected responses would be Hello World!, Hello Foo!, and Hello Bar! but all responses are Hello Bar!.
package main
import (
"fmt"
"net/http"
"github.com/go-chi/chi/v5"
)
func hello(text string) func(http.ResponseWriter, *http.Request) {
output := fmt.Sprintf("Hello %s\n", text)
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println(output)
w.Header().Add("Content-Type", "text/plain")
w.WriteHeader(http.StatusOK)
w.Write([]byte(output))
}
}
type middleware struct {
next http.Handler
}
func (m *middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
m.next.ServeHTTP(w, r)
}
var singleton = middleware{}
func Middleware(next http.Handler) http.Handler {
singleton.next = next
return &singleton
}
func main() {
roothandler := chi.NewRouter()
roothandler.Group(func(topgroup chi.Router) {
topgroup.Use(Middleware)
topgroup.Get("/", hello("World!"))
topgroup.Group(func(foogroup chi.Router) {
foogroup.Get("/foo", hello("Foo!"))
})
topgroup.Group(func(bargroup chi.Router) {
bargroup.Get("/bar", hello("Bar!"))
})
})
server := http.Server{
Handler: roothandler,
}
server.ListenAndServe()
}