From 417b142703594c1a7dff030e67c38e1dfec9f1fc Mon Sep 17 00:00:00 2001 From: thinkgo <49174849+thinkgos@users.noreply.github.com> Date: Fri, 18 Mar 2022 09:52:23 +0800 Subject: [PATCH] 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 --- README.md | 3 ++- routergroup.go | 19 ++++++++++++++++--- routergroup_test.go | 12 ++++++++++++ routes_test.go | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2d113532..4b4d236b 100644 --- a/README.md +++ b/README.md @@ -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") } diff --git a/routergroup.go b/routergroup.go index b84fcca3..3fba3a91 100644 --- a/routergroup.go +++ b/routergroup.go @@ -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 } @@ -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() diff --git a/routergroup_test.go b/routergroup_test.go index 232f595b..c1fad3a9 100644 --- a/routergroup_test.go +++ b/routergroup_test.go @@ -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" @@ -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))) } diff --git a/routes_test.go b/routes_test.go index b3f0c47b..4a0cb493 100644 --- a/routes_test.go +++ b/routes_test.go @@ -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()