diff --git a/.travis.yml b/.travis.yml
index 6899832..dd4af48 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,7 @@ jobs:
- go: 1.13.x
- go: 1.14.x
- go: 1.15.x
+ - go: 1.16.x
- go: master
install:
diff --git a/README.md b/README.md
index 75640ac..132f714 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,8 @@ import "github.com/gin-contrib/static"
See the [example](example)
[embedmd]:# (example/simple/example.go go)
+
+#### Serve local file
```go
package main
@@ -52,3 +54,34 @@ func main() {
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 tmp/server
+var server embed.FS
+
+func main() {
+ r := gin.Default()
+ r.Use(static.Serve("/", static.EmbedFolder(server, "tmp/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")
+}
+```
\ No newline at end of file
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/go.mod b/go.mod
index 1fb38e3..8881dcd 100644
--- a/go.mod
+++ b/go.mod
@@ -6,4 +6,4 @@ require (
github.com/stretchr/testify v1.4.0
)
-go 1.13
+go 1.16
diff --git a/local_file.go b/local_file.go
new file mode 100644
index 0000000..f67f08d
--- /dev/null
+++ b/local_file.go
@@ -0,0 +1,47 @@
+package static
+
+import (
+ "net/http"
+ "os"
+ "path"
+ "strings"
+
+ "github.com/gin-gonic/gin"
+)
+
+const INDEX = "index.html"
+
+type localFileSystem struct {
+ http.FileSystem
+ root string
+ indexes bool
+}
+
+func LocalFile(root string, indexes bool) *localFileSystem {
+ return &localFileSystem{
+ FileSystem: gin.Dir(root, indexes),
+ root: root,
+ indexes: indexes,
+ }
+}
+
+func (l *localFileSystem) Exists(prefix string, filepath string) bool {
+ if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
+ name := path.Join(l.root, p)
+ stats, err := os.Stat(name)
+ if err != nil {
+ return false
+ }
+ if stats.IsDir() {
+ if !l.indexes {
+ index := path.Join(name, INDEX)
+ _, err := os.Stat(index)
+ if err != nil {
+ return false
+ }
+ }
+ }
+ return true
+ }
+ return false
+}
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(), `