如何在使用router.Any和通配符处理请求后保留路径参数?

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

How to preserve path params after handling a request with router.Any and wildcard

问题

在我的情况下,需要捕获请求并检查是否为内部请求。如果不是,则将这些请求重定向到其他处理程序函数。

URL示例:

1. URL: http://localhost/internal/dosomething1
2. URL: http://localhost/internal/dosomething2/:id
3. URL: http://localhost/overview
4. URL: http://localhost/xxx

只有以 internal 开头的 URI 应该在我的处理函数中处理(案例 1 和 2)。

其他任何请求方法的 URI 都将代理到另一个函数(案例 3 和 4)。

我尝试使用 router.Any("/*uri", handlerExternal),代码如下:

func handlerExternal(c *gin.Context) {
    path := c.Param("uri")
    if strings.HasPrefix(path, "/internal/") {

        uri := strings.Split(path, "/")
        switch uri[2] {
        case "dosomething1":
            doInternal(c)
        }
    } else {
        doExternal(c)
    }
}

但是,使用这种解决方案时,doInternal(c) 无法捕获像 http://localhost/internal/dosomething2/:id 中的路径参数 :id

在这种情况下,是否有更好的解决方案?

英文:

In my case need to catch request and check is internal request or not. If not, redirect these request to other handler function.

URL example:

1. URL: http://localhost/internal/dosomething1
2. URL: http://localhost/internal/dosomething2/:id
3. URL: http://localhost/overview
4. URL: http://localhost/xxx

Only the URIs that start with internal should be handled in my own handle function (cases 1 and 2).

Others with any request method will proxy to another function (cases 3 and 4).

I am trying to use router.Any("/*uri", handlerExternal) as such:

func handlerExternal(c *gin.Context) {
	path := c.Param("uri")
	if strings.HasPrefix(path, "/internal/") {

		uri := strings.Split(path, "/")
		switch uri[2] {
		case "dosomething1":
			doInternal(c)
		}
	} else {
		doExternal(c)
	}
}

But with this solution, the doInternal(c) cannot catch path parameters like :id as in http://localhost/internal/dosomething2/:id

Is there any better solution for this case?

答案1

得分: 0

使用子引擎。

您可以使用gin.New实例化一个引擎,仅用于内部路由,而不运行它。相反,您将上下文从您的Any路由传递给Engine.HandleContext

这将传递主引擎的上下文,并根据子路由中的占位符匹配路径参数。

您可以像往常一样在子引擎上声明路由:

func main() {
    internalEngine := gin.New()
	internalEngine.GET("/internal/dosomething1", func(c *gin.Context) { c.JSON(200, "ok") })
	internalEngine.GET("/internal/dosomething2/:id", func(c *gin.Context) { c.JSON(200, c.Param("id")) })

	mainEngine := gin.New()
	mainEngine.Any("/*uri", func(c *gin.Context) {
		path := c.Param("uri")
		if strings.HasPrefix(path, "/internal/") {
			uri := strings.Split(path, "/")
			switch uri[2] {
			case "dosomething1", "dosomething2":
				internalEngine.HandleContext(c)
			}
		} else {
			doExternal(c)
		}
	})
    mainEngine.Run(":8800")
}

您还可以在将上下文传递给子引擎之前修改c.Request.URL.Path,例如,通过删除internal前缀。

现在,如果您尝试向以下地址发送GET请求:

http://localhost:8855/internal/dosomething2/1234

它将返回以下输出:

"1234"
英文:

Use a sub-engine.

You can instantiate an engine with gin.New for internal routes only and not run it. Instead you pass the context from your Any route to Engine.HandleContext.

This will relay the context from the main engine, and it will match path params based on the placeholders in the sub-routes.

You can declare routes on the sub-engine as usual:

func main() {
    internalEngine := gin.New()
	internalEngine.GET("/internal/dosomething1", func(c *gin.Context) { c.JSON(200, "ok") })
	internalEngine.GET("/internal/dosomething2/:id", func(c *gin.Context) { c.JSON(200, c.Param("id")) })

	mainEngine := gin.New()
	mainEngine.Any("/*uri", func(c *gin.Context) {
		path := c.Param("uri")
		if strings.HasPrefix(path, "/internal/") {
			uri := strings.Split(path, "/")
			switch uri[2] {
			case "dosomething1", "dosomething2":
				internalEngine.HandleContext(c)
			}
		} else {
			doExternal(c)
		}
	})
    mainEngine.Run(":8800")
}

You can also modify c.Request.URL.Path before relaying the context to the sub-engine, e.g. by removing the internal prefix, if so you wish.

Now if you try a GET request to:

http://localhost:8855/internal/dosomething2/1234

it will echo the output:

"1234"

huangapple
  • 本文由 发表于 2022年2月15日 00:10:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/71114861.html
匿名

发表评论

匿名网友

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

确定