From b8c4e766da75402a3c753fd1f53162e59c5a1d8f Mon Sep 17 00:00:00 2001 From: thinkgo Date: Tue, 8 Jun 2021 19:31:15 +0800 Subject: [PATCH 1/3] RouterGroup.StaticFileFS added add StaticFileFS ad README --- README.md | 3 ++- routergroup.go | 18 +++++++++++++++++- routergroup_test.go | 12 ++++++++++++ routes_test.go | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 38c674870f..48c030fba5 100644 --- a/README.md +++ b/README.md @@ -1241,7 +1241,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 6f14bf5935..f146ab56c1 100644 --- a/routergroup.go +++ b/routergroup.go @@ -37,6 +37,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 } @@ -162,12 +163,27 @@ func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes { return group.returnObj() } +// 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 { + if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") { + panic("URL parameters can not be used when serving a static file") + } + handler := func(c *Context) { + c.FileFromFS(filepath, fs) + } + group.GET(relativePath, handler) + group.HEAD(relativePath, handler) + return group.returnObj() +} + // Static serves files from the given file system root. // Internally a http.FileServer is used, therefore http.NotFound is used instead // of the Router's NotFound handler. // To use the operating system's file system implementation, // use : -// router.Static("/static", "/var/www") +// router.Static("/static", "/var/www", http) func (group *RouterGroup) Static(relativePath, root string) IRoutes { return group.StaticFS(relativePath, Dir(root, false)) } diff --git a/routergroup_test.go b/routergroup_test.go index 0e49d65b14..a94593ddac 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) { router := New() handlers1 := make([]HandlerFunc, 40) @@ -173,6 +184,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 036fa1c349..a02ecca3ee 100644 --- a/routes_test.go +++ b/routes_test.go @@ -324,6 +324,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() From 243adec8072804329b7712c2ea4930a02a3e5277 Mon Sep 17 00:00:00 2001 From: thinkgo Date: Tue, 8 Jun 2021 19:37:49 +0800 Subject: [PATCH 2/3] fix Static content mistake --- routergroup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routergroup.go b/routergroup.go index f146ab56c1..df94b3209c 100644 --- a/routergroup.go +++ b/routergroup.go @@ -183,7 +183,7 @@ func (group *RouterGroup) StaticFileFS(relativePath, filepath string, fs http.Fi // of the Router's NotFound handler. // To use the operating system's file system implementation, // use : -// router.Static("/static", "/var/www", http) +// router.Static("/static", "/var/www") func (group *RouterGroup) Static(relativePath, root string) IRoutes { return group.StaticFS(relativePath, Dir(root, false)) } From 2a2458152c9a9d7b20259b9e2f337b694a1996ac Mon Sep 17 00:00:00 2001 From: thinkgo Date: Sun, 22 Aug 2021 22:31:48 +0800 Subject: [PATCH 3/3] update README `tab` improve StaticFile and StaticFileFS code, use staticFileHandler --- README.md | 2 +- routergroup.go | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 48c030fba5..303c6a7c10 100644 --- a/README.md +++ b/README.md @@ -1241,7 +1241,7 @@ 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")) + 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 df94b3209c..5f955f0443 100644 --- a/routergroup.go +++ b/routergroup.go @@ -152,27 +152,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 { - if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") { - panic("URL parameters can not be used when serving a static file") - } - handler := func(c *Context) { + return group.staticFileHandler(relativePath, func(c *Context) { c.File(filepath) - } - group.GET(relativePath, handler) - group.HEAD(relativePath, handler) - return group.returnObj() + }) } // 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.FileFromFS(filepath, fs) - } group.GET(relativePath, handler) group.HEAD(relativePath, handler) return group.returnObj()