I'm trying to implement two routes using the Chi router. One should be invoked only if the "host" header is set to example.com. But only the lastly added route is invoked.
r := chi.NewRouter()
r.Use(middleware.Logger)
middlewareHeader := middleware.RouteHeaders().Route("Host", "example.com", middleware.New(r)).Handler
r.With(middlewareHeader).MethodFunc("get", "/", func(w http.ResponseWriter, r *http.Request) {
log.Println("Host: example.com")
echo(w, r)
})
middlewareNone := middleware.RouteHeaders().Handler
r.With(middlewareNone).MethodFunc("get", "/", func(w http.ResponseWriter, r *http.Request) {
echo(w, r)
})
srv := &http.Server{
Handler: r,
Addr: "127.0.0.1:8080",
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(srv.ListenAndServe())
CodePudding user response:
As mentioned on comment: you cannot assign multiple handlers to one route.
RouteHeaders is a neat little header-based router that allows you to direct the flow of a request through a middleware stack based on a request header.
RouteHeaders
is used to put your request through specific middleware stack, not to change routes. You can still use it but middleware has to redirect to other route.
Options:
1. Create second route and redirect in middleware.
func redirectOnHeader(header, value string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get(header) == value {
http.Redirect(w, r, "/with-header", http.StatusMovedPermanently)
return
}
next.ServeHTTP(w, r)
})
}
}
then call the middleware on desired route
r := chi.NewRouter()
r.With(redirectOnHeader("Host", "example.com")).Get("/", func(w http.ResponseWriter, r *http.Request) {
echo(w, r)
})
r.Get("/with-headers", func(w http.ResponseWriter, r *http.Request) {
echo(w, r)
})
2. Use second router and RouteHeaders
As in example in docs.
Note that you need 2 routers on order to have 2 "/"
routes.
r := chi.NewRouter()
anotherR := chi.NewRouter()
r.Use(middleware.RouteHeaders().
Route("Host", "example.com", middleware.New(r)).
RouteDefault(middleware.New(anotherR)).
Handler)
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
echo(w, r)
})
anotherR.Get("/", func(w http.ResponseWriter, r *http.Request) {
echo(w, r)
})
3. Implement two logic in one HandlerFunc
func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get(header) == value {
// do something
return
}
// do something else
})