diff --git a/README.md b/README.md
index e5fc6aa..3fa26d2 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,8 @@ import "github.com/gin-contrib/static"
See the [example](_example)
+#### Serve local file
+
```go
package main
@@ -48,6 +50,39 @@ func main() {
c.String(200, "test")
})
// Listen and Server in 0.0.0.0:8080
+ r.Run(":8080")
+}
+```
+
+#### Serve embed folder
+
+```go
+package main
+
+import (
+ "embed"
+ "fmt"
+ "net/http"
+
+ "github.com/gin-contrib/static"
+ "github.com/gin-gonic/gin"
+)
+
+//go:embed data
+var server embed.FS
+
+func main() {
+ r := gin.Default()
+ r.Use(static.Serve("/", static.EmbedFolder(server, "data/server")))
+ r.GET("/ping", func(c *gin.Context) {
+ c.String(200, "test")
+ })
+ r.NoRoute(func(c *gin.Context) {
+ fmt.Printf("%s doesn't exists, redirect on /\n", c.Request.URL.Path)
+ c.Redirect(http.StatusMovedPermanently, "/")
+ })
+ // Listen and Server in 0.0.0.0:8080
+ r.Run(":8080")
if err := r.Run(":8080"); err != nil {
log.Fatal(err)
}
diff --git a/embed_folder.go b/embed_folder.go
new file mode 100644
index 0000000..15c211c
--- /dev/null
+++ b/embed_folder.go
@@ -0,0 +1,27 @@
+package static
+
+import (
+ "embed"
+ "io/fs"
+ "log"
+ "net/http"
+)
+
+type embedFileSystem struct {
+ http.FileSystem
+}
+
+func (e embedFileSystem) Exists(prefix string, path string) bool {
+ _, err := e.Open(path)
+ return err == nil
+}
+
+func EmbedFolder(fsEmbed embed.FS, targetPath string) ServeFileSystem {
+ fsys, err := fs.Sub(fsEmbed, targetPath)
+ if err != nil {
+ log.Fatalf("static.EmbedFolder - Invalid targetPath value - %s", err)
+ }
+ return embedFileSystem{
+ FileSystem: http.FS(fsys),
+ }
+}
diff --git a/embed_folder_test.go b/embed_folder_test.go
new file mode 100644
index 0000000..65ea122
--- /dev/null
+++ b/embed_folder_test.go
@@ -0,0 +1,40 @@
+package static
+
+import (
+ "embed"
+ "fmt"
+ "testing"
+
+ "github.com/gin-gonic/gin"
+ "github.com/stretchr/testify/assert"
+)
+
+//go:embed test/data/server
+var server embed.FS
+
+var embedTests = []struct {
+ targetURL string // input
+ httpCode int // expected http code
+ httpBody string // expected http body
+ name string // test name
+}{
+ {"/404.html", 301, "Moved Permanently.\n\n", "Unknown file"},
+ {"/", 200, "
Hello Embed
", "Root"},
+ {"/index.html", 301, "", "Root by file name automatic redirect"},
+ {"/static.html", 200, "Hello Gin Static
", "Other file"},
+}
+
+func TestEmbedFolder(t *testing.T) {
+ router := gin.New()
+ router.Use(Serve("/", EmbedFolder(server, "test/data/server")))
+ router.NoRoute(func(c *gin.Context) {
+ fmt.Printf("%s doesn't exists, redirect on /\n", c.Request.URL.Path)
+ c.Redirect(301, "/")
+ })
+
+ for _, tt := range embedTests {
+ w := PerformRequest(router, "GET", tt.targetURL)
+ assert.Equal(t, tt.httpCode, w.Code, tt.name)
+ assert.Equal(t, tt.httpBody, w.Body.String(), tt.name)
+ }
+}
diff --git a/example/embed/data/server/index.html b/example/embed/data/server/index.html
new file mode 100644
index 0000000..1d3fa49
--- /dev/null
+++ b/example/embed/data/server/index.html
@@ -0,0 +1 @@
+Hello Embed
\ No newline at end of file
diff --git a/example/embed/example.go b/example/embed/example.go
new file mode 100644
index 0000000..6df55ce
--- /dev/null
+++ b/example/embed/example.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "embed"
+ "fmt"
+ "net/http"
+
+ "github.com/gin-contrib/static"
+ "github.com/gin-gonic/gin"
+)
+
+//go:embed data
+var server embed.FS
+
+func main() {
+ r := gin.Default()
+ r.Use(static.Serve("/", static.EmbedFolder(server, "data/server")))
+ r.GET("/ping", func(c *gin.Context) {
+ c.String(200, "test")
+ })
+ r.NoRoute(func(c *gin.Context) {
+ fmt.Printf("%s doesn't exists, redirect on /\n", c.Request.URL.Path)
+ c.Redirect(http.StatusMovedPermanently, "/")
+ })
+ // Listen and Server in 0.0.0.0:8080
+ r.Run(":8080")
+}
diff --git a/static.go b/local_file.go
similarity index 56%
rename from static.go
rename to local_file.go
index ffa00ee..f67f08d 100644
--- a/static.go
+++ b/local_file.go
@@ -11,11 +11,6 @@ import (
const INDEX = "index.html"
-type ServeFileSystem interface {
- http.FileSystem
- Exists(prefix string, path string) bool
-}
-
type localFileSystem struct {
http.FileSystem
root string
@@ -50,21 +45,3 @@ func (l *localFileSystem) Exists(prefix string, filepath string) bool {
}
return false
}
-
-func ServeRoot(urlPrefix, root string) gin.HandlerFunc {
- return Serve(urlPrefix, LocalFile(root, false))
-}
-
-// Static returns a middleware handler that serves static files in the given directory.
-func Serve(urlPrefix string, fs ServeFileSystem) gin.HandlerFunc {
- fileserver := http.FileServer(fs)
- if urlPrefix != "" {
- fileserver = http.StripPrefix(urlPrefix, fileserver)
- }
- return func(c *gin.Context) {
- if fs.Exists(urlPrefix, c.Request.URL.Path) {
- fileserver.ServeHTTP(c.Writer, c.Request)
- c.Abort()
- }
- }
-}
diff --git a/local_file_test.go b/local_file_test.go
new file mode 100644
index 0000000..0ab922a
--- /dev/null
+++ b/local_file_test.go
@@ -0,0 +1,34 @@
+package static
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/gin-gonic/gin"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestLocalFile(t *testing.T) {
+ // SETUP file
+ testRoot, _ := os.Getwd()
+ f, err := ioutil.TempFile(testRoot, "")
+ if err != nil {
+ t.Error(err)
+ }
+ defer os.Remove(f.Name())
+ f.WriteString("Gin Web Framework")
+ f.Close()
+
+ dir, filename := filepath.Split(f.Name())
+ router := gin.New()
+ router.Use(Serve("/", LocalFile(dir, true)))
+
+ w := PerformRequest(router, "GET", "/"+filename)
+ assert.Equal(t, w.Code, 200)
+ assert.Equal(t, w.Body.String(), "Gin Web Framework")
+
+ w = PerformRequest(router, "GET", "/")
+ assert.Contains(t, w.Body.String(), `