如何在Go的julienschmidt/httprouter中实现嵌套路由?
httprouter嵌套路由404问题解决
你的代码出现404的原因有两个核心问题:
1. 顶层路由匹配规则不匹配请求路径
httprouter的路由默认是精确匹配,你定义的顶层路由/api只会匹配路径完全等于/api的请求,不会匹配/api/foo或/api/bar这类带后缀的路径。
2. 子路由收到的请求路径未去除前缀
即使顶层路由能转发请求,子router收到的请求URL是完整的/api/foo,但你在子router里定义的是/foo,两者路径不匹配,导致子router也找不到对应的处理函数。
修复方案
你需要修改顶层路由的匹配规则,同时去除请求路径中的/api前缀,再交给子router处理。示例代码如下:
package main import ( "log" "net/http" "github.com/julienschmidt/httprouter" ) func apiFoo(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Success: /api/foo")) } func apiBar(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Success: /api/bar")) } func main() { // 子router:处理/api前缀下的具体路由 apiRouter := httprouter.New() apiRouter.HandlerFunc(http.MethodGet, "/foo", apiFoo) apiRouter.HandlerFunc(http.MethodGet, "/bar", apiBar) // 顶层router:匹配所有/api开头的请求 rootRouter := httprouter.New() // 使用/api/*匹配所有/api开头的路径,并用http.StripPrefix去除/api前缀后交给子router rootRouter.Handler(http.MethodGet, "/api/*", http.StripPrefix("/api", apiRouter)) // 如果需要给所有API路由加中间件,只需包装子router即可 // 示例中间件: // apiMiddleware := func(next http.Handler) http.Handler { // return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // log.Println("API请求中间件触发") // next.ServeHTTP(w, r) // }) // } // rootRouter.Handler(http.MethodGet, "/api/*", apiMiddleware(http.StripPrefix("/api", apiRouter))) log.Fatal(http.ListenAndServe(":8080", rootRouter)) }
关键说明
- 用
/api/*作为顶层路由规则,*是httprouter的通配符,会匹配/api之后的所有路径。 http.StripPrefix("/api", apiRouter)会将请求路径中的/api前缀去掉,比如把/api/foo变成/foo,这样子router里定义的/foo就能正确匹配。- 若要给所有API路由统一添加中间件,只需将中间件包装在
http.StripPrefix返回的Handler外层即可,无需逐个修改子router的路由。
内容的提问来源于stack exchange,提问作者Yawar
相关产品推荐
相关产品推荐

