英文:
Header based routing with Chi
问题
我正在尝试使用Chi路由器实现两个路由。其中一个只有在"host"头设置为example.com时才会被调用。但是只有最后添加的路由会被调用。
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())
以上是你提供的代码。
英文:
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())
答案1
得分: 1
如评论中所提到的:你不能为一个路由分配多个处理程序。
RouteHeaders
是一个很好的基于请求头的路由器,它允许你通过一个请求头将请求流量引导到一个中间件堆栈。
RouteHeaders
用于将请求通过特定的中间件堆栈,而不是改变路由。你仍然可以使用它,但中间件必须重定向到其他路由。
选项:
1. 创建第二个路由并在中间件中进行重定向。
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)
})
}
}
然后在所需的路由上调用中间件
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. 使用第二个路由器和 RouteHeaders
如文档中的示例所示。
请注意,你需要两个路由器才能有两个 "/"
路由。
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. 在一个 HandlerFunc 中实现两个逻辑
func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get(header) == value {
// 做一些事情
return
}
// 做其他事情
})
英文:
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
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论