杜松子酒路由器路径冲突

时间:2016-04-01 13:37:10

标签: go go-gin

我想让我的应用程序在下面提供服务。

  • a.com =>将/ www发送到浏览器,以便浏览器可以搜索/www/index.html)
  • a.com/js/mylib.js =>将/www/js/mylib.js发送到浏览器
  • a.com/api/v1/disk =>返回JSON的典型REST API
  • a.com/api/v1/memory =>另一个API

我制作了如下代码:

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()

    r.Static("/", "/www")

    apiv1 := r.Group("api/v1")
    {
        apiv1.GET("/disk", diskSpaceHandler)
        apiv1.GET("/memory", memoryHandler)
        apiv1.GET("/cpu", cpuHandler)
    }

    r.Run(":80")
}

当我运行代码时,它会发生恐慌:

panic: path segment '/api/v1/disk' conflicts with existing wildcard '/*filepath' in path '/api/v1/disk'

我理解为什么会发生恐慌,但我不知道如何解决。

我脑海里浮现出两件事:

  1. 使用NoRoute()函数处理/ api / v1组路径以外的其他路径(不知道我是如何实现的)
  2. 使用中间件。静态中间位置https://github.com/gin-gonic/contrib但代码不适用于Windows(https://github.com/gin-gonic/contrib/issues/91
  3. 提前谢谢。

2 个答案:

答案 0 :(得分:0)

您应该使用静态中间件,请参见其示例:

https://github.com/gin-contrib/static#canonical-example

r.Use(static.Serve("/", static.LocalFile("/tmp", false)))

答案 1 :(得分:0)

为静态文件路径添加唯一前缀:r.Static("/static", "/www")

正如@chespinoza 的评论所提到的,这是 Gin 底层路由器实现 github.com/julienschmidt/httprouter 的一个 feature(不是错误)。路由是基于前缀而不是整个路由来匹配的,因此任何路径参数和通配符在同一位置与另一个路径段都会导致冲突。

例如下面会发生冲突,因为两个路径参数都是root之后的第一个路径段:

/:foo/something
/:bar/blah

给定路线 /myroute/something,第一段 /myroute/:foo/:bar 均匹配,而与第二段无关。

现在,方法 RouterGroup.Static从给定的文件系统根目录提供文件”,特别是它的实现使用了 path.Join(relativePath, "/*filepath")

在您的代码 r.Static("/", "/www") 中,relativePath/,因此静态文件路由变成了 /*filepath。这是一个从 root 开始的路径通配符,因此它将与所有路由冲突,除非它是您服务器中的唯一路由。

解决这个问题的方法是给你的静态文件路径添加一个唯一的前缀,这样就不会在相同的位置出现路径参数或通配符,例如:

r.Static("/static", "/www")

导致以下路由(省略处理程序),通配符仅出现在 /static 之后:

[GIN-debug] GET    /static/*filepath
[GIN-debug] HEAD   /static/*filepath
[GIN-debug] GET    /api/v1/disk
[GIN-debug] GET    /api/v1/memory
[GIN-debug] GET    /api/v1/cpu