Skip to content

Commit

Permalink
feat: add StaticFileFS (#2749)
Browse files Browse the repository at this point in the history
* RouterGroup.StaticFileFS added
add StaticFileFS ad README

* fix Static content mistake

* update README `tab`
improve StaticFile and StaticFileFS code, use staticFileHandler
  • Loading branch information
thinkgos committed Mar 18, 2022
1 parent 8860527 commit 417b142
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 4 deletions.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -1244,7 +1244,8 @@ func main() {
router.Static("/assets", "./assets")
router.StaticFS("/more_static", http.Dir("my_file_system"))
router.StaticFile("/favicon.ico", "./resources/favicon.ico")

router.StaticFileFS("/more_favicon.ico", "more_favicon.ico", http.Dir("my_file_system"))

// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
Expand Down
19 changes: 16 additions & 3 deletions routergroup.go
Expand Up @@ -44,6 +44,7 @@ type IRoutes interface {
HEAD(string, ...HandlerFunc) IRoutes

StaticFile(string, string) IRoutes
StaticFileFS(string, string, http.FileSystem) IRoutes
Static(string, string) IRoutes
StaticFS(string, http.FileSystem) IRoutes
}
Expand Down Expand Up @@ -153,12 +154,24 @@ func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRou
// StaticFile registers a single route in order to serve a single file of the local filesystem.
// router.StaticFile("favicon.ico", "./resources/favicon.ico")
func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes {
return group.staticFileHandler(relativePath, func(c *Context) {
c.File(filepath)
})
}

// StaticFileFS works just like `StaticFile` but a custom `http.FileSystem` can be used instead..
// router.StaticFileFS("favicon.ico", "./resources/favicon.ico", Dir{".", false})
// Gin by default user: gin.Dir()
func (group *RouterGroup) StaticFileFS(relativePath, filepath string, fs http.FileSystem) IRoutes {
return group.staticFileHandler(relativePath, func(c *Context) {
c.FileFromFS(filepath, fs)
})
}

func (group *RouterGroup) staticFileHandler(relativePath string, handler HandlerFunc) IRoutes {
if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") {
panic("URL parameters can not be used when serving a static file")
}
handler := func(c *Context) {
c.File(filepath)
}
group.GET(relativePath, handler)
group.HEAD(relativePath, handler)
return group.returnObj()
Expand Down
12 changes: 12 additions & 0 deletions routergroup_test.go
Expand Up @@ -111,6 +111,17 @@ func TestRouterGroupInvalidStaticFile(t *testing.T) {
})
}

func TestRouterGroupInvalidStaticFileFS(t *testing.T) {
router := New()
assert.Panics(t, func() {
router.StaticFileFS("/path/:param", "favicon.ico", Dir(".", false))
})

assert.Panics(t, func() {
router.StaticFileFS("/path/*param", "favicon.ico", Dir(".", false))
})
}

func TestRouterGroupTooManyHandlers(t *testing.T) {
const (
panicValue = "too many handlers"
Expand Down Expand Up @@ -177,6 +188,7 @@ func testRoutesInterface(t *testing.T, r IRoutes) {
assert.Equal(t, r, r.HEAD("/", handler))

assert.Equal(t, r, r.StaticFile("/file", "."))
assert.Equal(t, r, r.StaticFileFS("/static2", ".", Dir(".", false)))
assert.Equal(t, r, r.Static("/static", "."))
assert.Equal(t, r, r.StaticFS("/static2", Dir(".", false)))
}
34 changes: 34 additions & 0 deletions routes_test.go
Expand Up @@ -325,6 +325,40 @@ func TestRouteStaticFile(t *testing.T) {
assert.Equal(t, http.StatusOK, w3.Code)
}

// TestHandleStaticFile - ensure the static file handles properly
func TestRouteStaticFileFS(t *testing.T) {
// SETUP file
testRoot, _ := os.Getwd()
f, err := ioutil.TempFile(testRoot, "")
if err != nil {
t.Error(err)
}
defer os.Remove(f.Name())
_, err = f.WriteString("Gin Web Framework")
assert.NoError(t, err)
f.Close()

dir, filename := filepath.Split(f.Name())
// SETUP gin
router := New()
router.Static("/using_static", dir)
router.StaticFileFS("/result_fs", filename, Dir(dir, false))

w := performRequest(router, http.MethodGet, "/using_static/"+filename)
w2 := performRequest(router, http.MethodGet, "/result_fs")

assert.Equal(t, w, w2)
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "Gin Web Framework", w.Body.String())
assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))

w3 := performRequest(router, http.MethodHead, "/using_static/"+filename)
w4 := performRequest(router, http.MethodHead, "/result_fs")

assert.Equal(t, w3, w4)
assert.Equal(t, http.StatusOK, w3.Code)
}

// TestHandleStaticDir - ensure the root/sub dir handles properly
func TestRouteStaticListingDir(t *testing.T) {
router := New()
Expand Down

0 comments on commit 417b142

Please sign in to comment.