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

Issue

As the title says, consider a Gin router where I want to serve static files from all routes except one. Let’s say this one route is /api. A first attempt might look like this:

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")
}

The RouterGroup.StaticFS (and Static too) under the hood joins the relative path with a wildcard path param: path.Join(relativePath, "/*filepath"). When relativePath is the root path /, it will panic with:

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

This is due to Gin’s http router implementation: routing matches on the path prefix, so a wildcard on root will conflict with every other route. More details about this behavior can be found here — which is where this question was raised.

Another possible solution is to prefix the static file route, so that it doesn’t conflict with /api:

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

but this doesn’t allow me to serve assets from root too. How can I have a wildcard, or equivalent, on root and still match on one specific path?

Solution

There is a package called static for this.

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

just modify the example as follows

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")
}

Answered By – obarisk

Answer Checked By – Mildred Charles (GoLangFix Admin)

Leave a Reply

Your email address will not be published.