feat: add StaticFileFS (#2749)

* RouterGroup.StaticFileFS added
add StaticFileFS ad README

* fix Static content mistake

* update README `tab`
improve StaticFile and StaticFileFS code, use staticFileHandler
This commit is contained in:
thinkgo 2022-03-18 09:52:23 +08:00 committed by GitHub
parent 8860527de6
commit 417b142703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 4 deletions

View File

@ -1244,6 +1244,7 @@ func main() {
router.Static("/assets", "./assets") router.Static("/assets", "./assets")
router.StaticFS("/more_static", http.Dir("my_file_system")) router.StaticFS("/more_static", http.Dir("my_file_system"))
router.StaticFile("/favicon.ico", "./resources/favicon.ico") 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 // Listen and serve on 0.0.0.0:8080
router.Run(":8080") router.Run(":8080")

View File

@ -44,6 +44,7 @@ type IRoutes interface {
HEAD(string, ...HandlerFunc) IRoutes HEAD(string, ...HandlerFunc) IRoutes
StaticFile(string, string) IRoutes StaticFile(string, string) IRoutes
StaticFileFS(string, string, http.FileSystem) IRoutes
Static(string, string) IRoutes Static(string, string) IRoutes
StaticFS(string, http.FileSystem) IRoutes StaticFS(string, http.FileSystem) IRoutes
} }
@ -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. // StaticFile registers a single route in order to serve a single file of the local filesystem.
// router.StaticFile("favicon.ico", "./resources/favicon.ico") // router.StaticFile("favicon.ico", "./resources/favicon.ico")
func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes { 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, "*") { if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") {
panic("URL parameters can not be used when serving a static file") panic("URL parameters can not be used when serving a static file")
} }
handler := func(c *Context) {
c.File(filepath)
}
group.GET(relativePath, handler) group.GET(relativePath, handler)
group.HEAD(relativePath, handler) group.HEAD(relativePath, handler)
return group.returnObj() return group.returnObj()

View File

@ -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) { func TestRouterGroupTooManyHandlers(t *testing.T) {
const ( const (
panicValue = "too many handlers" panicValue = "too many handlers"
@ -177,6 +188,7 @@ func testRoutesInterface(t *testing.T, r IRoutes) {
assert.Equal(t, r, r.HEAD("/", handler)) assert.Equal(t, r, r.HEAD("/", handler))
assert.Equal(t, r, r.StaticFile("/file", ".")) 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.Static("/static", "."))
assert.Equal(t, r, r.StaticFS("/static2", Dir(".", false))) assert.Equal(t, r, r.StaticFS("/static2", Dir(".", false)))
} }

View File

@ -325,6 +325,40 @@ func TestRouteStaticFile(t *testing.T) {
assert.Equal(t, http.StatusOK, w3.Code) 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 // TestHandleStaticDir - ensure the root/sub dir handles properly
func TestRouteStaticListingDir(t *testing.T) { func TestRouteStaticListingDir(t *testing.T) {
router := New() router := New()