如何从除 Gin 中的一个路由之外的所有路由提供静态文件?

How to serve static files from all routes except one in Gin?

正如标题所说,考虑一个 Gin 路由器,我想在其中提供来自所有路由 除了一个 的静态文件。假设这条路线是 /api。第一次尝试可能如下所示:

package main

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

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

    r.StaticFS("/", gin.Dir("static", false))
    r.GET("/api/v1/foo", func(c *gin.Context) { c.JSON(200, gin.H{"foo": true}) })

    r.Run(":9955")
}

引擎盖下的RouterGroup.StaticFS(以及Static)使用通配符路径参数加入相对路径:path.Join(relativePath, "/*filepath")。当 relativePath 是根路径 / 时,它会 panic with:

panic: '/api/v1/foo' in new path '/api/v1/foo' conflicts with existing wildcard '/*filepath' in existing prefix '/*filepath'

这是由于 Gin 的 http 路由器实现:路径前缀 上的路由匹配,因此根上的通配符将与所有其他路由冲突。可以找到有关此行为的更多详细信息 here — 这是提出此问题的地方。

另一种可能的解决方案是在静态文件路由前添加前缀,这样它就不会与 /api:

冲突
r.StaticFS("/static", gin.Dir("static", false))

但这也不允许我从 root 提供资产。我怎样才能在 root 上使用通配符或等效符并仍然匹配一个特定路径?

为此有一个名为 static 的包。

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

修改示例如下

package main

import (
  "github.com/gin-contrib/static"
  "github.com/gin-gonic/gin"
)

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

  // server a directory called static
  r.Use(static.Serve("/", static.LocalFile("static", false)))
  
  // And any route as usual   
  r.GET("/api/ping", func(c *gin.Context) {
    c.String(200, "ping")
  })

  r.Run(":9955")
}