使用Chi进行基于头部的路由

huangapple go评论84阅读模式
英文:

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
})

huangapple
  • 本文由 发表于 2022年7月13日 11:56:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/72960763.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定