如何在Go的julienschmidt/httprouter中嵌套路由器?

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

How to nest routers in Go julienschmidt/httprouter?

问题

我想从我的服务中公开以下URL:

GET /api/foo
GET /api/bar

我还想将其结构化为嵌套在另一个路由器内部的路由器。顶级路由器将匹配所有对/api的请求,并使用嵌套路由器为其提供服务,该嵌套路由器将匹配对/foo/bar的请求。基本上,这是一种命名空间。

我可以只有一个路由器,并将/api前缀分别添加到这两个路由上:

router.GET("/api/foo", apiFoo)
router.GET("/api/bar", apiBar)

但是,我希望能够方便地在/api前缀下的所有路由上使用单个路由器,以便我可以通过单个函数调用为它们添加适当的中间件。

这是我尝试过的代码:

package main

import (
    "log"
    "net/http"

    "github.com/julienschmidt/httprouter"
)

func apiFoo(w http.ResponseWriter, r *http.Request) {}
func apiBar(w http.ResponseWriter, r *http.Request) {}

func main() {
    api := httprouter.New()
    api.HandlerFunc(http.MethodGet, "/foo", apiFoo)
    api.HandlerFunc(http.MethodGet, "/bar", apiBar)

    router := httprouter.New()
    router.Handler(http.MethodGet, "/api", api)

    log.Fatal(http.ListenAndServe(":8080", router))
}

然而,当我访问http://localhost:8080/api/foo或http://localhost:8080/api/bar时,出现404未找到的错误。

我原以为嵌套路由器会起作用,因为路由器实现了http.Handler接口。我漏掉了什么?

英文:

I want to expose the following URLs from my service:

GET /api/foo
GET /api/bar

I also want to structure it as a router nested inside another. The toplevel router will match all requests to /api and serve them with the nested router which will match requests to /foo and /bar. Basically, namespacing.

I could just have a single router and give the /api prefix to both the routes:

router.GET("/api/foo", apiFoo)
router.GET("/api/bar", apiBar)

But I would like the convenience of having a single router for all routes inside the /api prefix so that I can add appropriate middlewares to them all with a single function call.

Here's what I tried:

package main

import (
	"log"
	"net/http"

	"github.com/julienschmidt/httprouter"
)

func apiFoo(w http.ResponseWriter, r *http.Request) {}
func apiBar(w http.ResponseWriter, r *http.Request) {}

func main() {
	api := httprouter.New()
	api.HandlerFunc(http.MethodGet, "/foo", apiFoo)
	api.HandlerFunc(http.MethodGet, "/bar", apiBar)

	router := httprouter.New()
	router.Handler(http.MethodGet, "/api", api)

	log.Fatal(http.ListenAndServe(":8080", router))
}

However, getting 404 not found on going to http://localhost:8080/api/foo or http://localhost:8080/api/bar

I had thought that nested routers would work because routers implement the http.Handler interface. What am I missing?

答案1

得分: 2

httprouter不会连接路径,所以你不能这样做。两个路由器只会检查请求路径并相应地处理。

有一个开放的拉取请求已经存在了7年,它将实现这个功能。你可以去那里看看,并自己实现类似的逻辑,该拉取请求是基于连接路径的。也许你可以编写一个小的辅助函数来实现这个。

如果你愿意切换路由器包,你可以考虑其他选择,比如chi,它支持路由器组。

英文:

httprouter does not concatenate the path, so you can't do it that way. Both routers will just inspect the request path and act accordingly.

There is an open pull request for 7 years, that would implement it. You could have a look there and implement similar logic yourself, the PR is based on concatenating the path. Maybe you can write a small helper function for that.

If you are willing to switch the router package, you could look into alternatives such as chi, which support router groups.

huangapple
  • 本文由 发表于 2022年12月20日 03:54:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/74855390.html
匿名

发表评论

匿名网友

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

确定