在go-chi中为子路由/application/health配置免认证代理
解决方案
当然可以通过单独的路由组实现这个需求,核心是利用Chi路由顺序匹配优先的特性,先定义不需要安全验证的/application/health路径,再处理需要验证的其他路由。
修改后的完整代码
router := chi.NewRouter() router.Route("/", func(r chi.Router) { r.Use(chimw.Recoverer) // 修正原代码笔误:这里应该用当前路由组的r.Use而非全局router.Use r.Use(hlog.NewHandler(log.Logger)) // 单独路由组:处理/application/health,跳过安全验证但应用代理逻辑 r.Group(func(r chi.Router) { // 注入代理目标上下文(和setProxy里的逻辑一致) r.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 修正原代码笔误:http:locahost → http://localhost ctx := context.WithValue(r.Context(), "target", "http://localhost:9999") r = r.WithContext(ctx) next.ServeHTTP(w, r) }) }) // 代理/application/health请求 r.HandleFunc("/application/health", httputil.ReverseProxy{}.ServeHTTP) }) // 对剩余所有路径应用安全验证(如果启用) if mustBeSecure() { r.Use(keycloak.MustStandardKeycloakAuth("url")) } // 设置其他代理路径(自动排除已匹配的/application/health) setProxy(r) // 本地健康检查路由 r.Group(func(r chi.Router) { r.Get("/health", handleHealth()) }) }) // 补充端口,避免默认端口冲突 return http.ListenAndServe("0.0.0.0:8080", router)
调整后的setProxy函数
func setProxy(r chi.Router) { r.Route("/application", func(r chi.Router) { r.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := context.WithValue(r.Context(), "target", "http://localhost:9999") r = r.WithContext(ctx) next.ServeHTTP(w, r) }) }) // 处理/application下除/health外的所有路径 r.HandleFunc("/*", httputil.ReverseProxy{}.ServeHTTP) }) }
关键说明
- 路由匹配顺序:Chi会按代码定义的顺序匹配路由,因此先定义的
/application/health会被优先命中,不会进入后续带安全验证的路由组。 - 独立路由组隔离逻辑:给
/application/health单独创建路由组,只注入代理所需的上下文中间件,完全跳过Keycloak安全验证。 - 修正原代码笔误:原代码中存在
router.Use(hlog.NewHandler(log.Logger))(应该用当前路由组的r.Use)和http:locahost(缺少斜杠且拼写错误)的问题,已同步修正。
内容的提问来源于stack exchange,提问作者Gabriel Carrera
相关产品推荐
相关产品推荐

