initital.
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
parent
b0491c78a9
commit
7232ea358a
|
@ -1,24 +1,5 @@
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
*/Godeps/*
|
||||||
*.o
|
!*/Godeps/Godeps.json
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
coverage.out
|
||||||
_obj
|
dump.rdb
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
||||||
*.prof
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
language: go
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.5.4
|
||||||
|
- 1.6.4
|
||||||
|
- 1.7.4
|
||||||
|
- tip
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -v -covermode=atomic -coverprofile=coverage.out
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/acc2c57482e94b44f557
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
|
on_start: false
|
24
README.md
24
README.md
|
@ -1,2 +1,24 @@
|
||||||
# static
|
# static middleware
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/gin-contrib/static.svg)](https://travis-ci.org/gin-contrib/static)
|
||||||
|
[![codecov](https://codecov.io/gh/gin-contrib/static/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-contrib/static)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/gin-contrib/static)](https://goreportcard.com/report/github.com/gin-contrib/static)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/gin-contrib/static?status.svg)](https://godoc.org/github.com/gin-contrib/static)
|
||||||
|
|
||||||
Static middleware
|
Static middleware
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Start using it
|
||||||
|
|
||||||
|
Download and install it:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ go get github.com/gin-contrib/static
|
||||||
|
```
|
||||||
|
|
||||||
|
Import it in your code:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/gin-contrib/static"
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func bindata_read(data []byte, name string) ([]byte, error) {
|
||||||
|
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
_, err = io.Copy(&buf, gz)
|
||||||
|
gz.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func data_index_html() ([]byte, error) {
|
||||||
|
return bindata_read([]byte{
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0x44, 0xce,
|
||||||
|
0xbd, 0xae, 0xc2, 0x30, 0x0c, 0x05, 0xe0, 0xbd, 0x4f, 0xe1, 0x9b, 0xbd,
|
||||||
|
0xaa, 0xba, 0xdd, 0x21, 0xcd, 0xc2, 0xef, 0x06, 0x43, 0x19, 0x18, 0x5d,
|
||||||
|
0x62, 0x35, 0x41, 0x4e, 0x22, 0x15, 0x4b, 0x88, 0xb7, 0x27, 0x21, 0x45,
|
||||||
|
0x4c, 0x39, 0xb1, 0xf5, 0x1d, 0x59, 0xff, 0x6d, 0x4f, 0x9b, 0xf1, 0x7a,
|
||||||
|
0xde, 0x81, 0x93, 0xc0, 0xa6, 0xd1, 0xe5, 0x01, 0xc6, 0x38, 0x0f, 0xea,
|
||||||
|
0x8e, 0xca, 0x34, 0x00, 0xda, 0x11, 0xda, 0x12, 0x72, 0x0c, 0x24, 0x08,
|
||||||
|
0x37, 0x87, 0xcb, 0x83, 0x64, 0x50, 0x97, 0x71, 0xdf, 0xfe, 0x2b, 0xe8,
|
||||||
|
0xd6, 0xa5, 0x78, 0x61, 0x32, 0x73, 0x6a, 0x27, 0x1f, 0x2d, 0x0a, 0xea,
|
||||||
|
0xae, 0x4e, 0x4a, 0x47, 0xf7, 0x2d, 0xd1, 0x53, 0xb2, 0xaf, 0x15, 0xb8,
|
||||||
|
0xde, 0x1c, 0x89, 0x39, 0xc1, 0xc1, 0x47, 0xf8, 0x39, 0x08, 0xde, 0x5a,
|
||||||
|
0xa6, 0x27, 0x2e, 0x94, 0x5d, 0x5f, 0x7d, 0x65, 0xf9, 0xff, 0x39, 0xf3,
|
||||||
|
0x1d, 0x00, 0x00, 0xff, 0xff, 0x51, 0x69, 0x85, 0x27, 0xb7, 0x00, 0x00,
|
||||||
|
0x00,
|
||||||
|
},
|
||||||
|
"data/index.html",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asset loads and returns the asset for the given name.
|
||||||
|
// It returns an error if the asset could not be found or
|
||||||
|
// could not be loaded.
|
||||||
|
func Asset(name string) ([]byte, error) {
|
||||||
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
|
if f, ok := _bindata[cannonicalName]; ok {
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Asset %s not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetNames returns the names of the assets.
|
||||||
|
func AssetNames() []string {
|
||||||
|
names := make([]string, 0, len(_bindata))
|
||||||
|
for name := range _bindata {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
|
var _bindata = map[string]func() ([]byte, error){
|
||||||
|
"data/index.html": data_index_html,
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetDir returns the file names below a certain
|
||||||
|
// directory embedded in the file by go-bindata.
|
||||||
|
// For example if you run go-bindata on data/... and data contains the
|
||||||
|
// following hierarchy:
|
||||||
|
// data/
|
||||||
|
// foo.txt
|
||||||
|
// img/
|
||||||
|
// a.png
|
||||||
|
// b.png
|
||||||
|
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||||
|
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||||
|
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||||
|
func AssetDir(name string) ([]string, error) {
|
||||||
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
|
pathList := strings.Split(cannonicalName, "/")
|
||||||
|
node := _bintree
|
||||||
|
for _, p := range pathList {
|
||||||
|
node = node.Children[p]
|
||||||
|
if node == nil {
|
||||||
|
return nil, fmt.Errorf("Asset %s not found", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.Func != nil {
|
||||||
|
return nil, fmt.Errorf("Asset %s not found", name)
|
||||||
|
}
|
||||||
|
rv := make([]string, 0, len(node.Children))
|
||||||
|
for name := range node.Children {
|
||||||
|
rv = append(rv, name)
|
||||||
|
}
|
||||||
|
return rv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type _bintree_t struct {
|
||||||
|
Func func() ([]byte, error)
|
||||||
|
Children map[string]*_bintree_t
|
||||||
|
}
|
||||||
|
|
||||||
|
var _bintree = &_bintree_t{nil, map[string]*_bintree_t{
|
||||||
|
"data": &_bintree_t{nil, map[string]*_bintree_t{
|
||||||
|
"index.html": &_bintree_t{data_index_html, map[string]*_bintree_t{}},
|
||||||
|
}},
|
||||||
|
}}
|
||||||
|
|
||||||
|
// AssetInfo returns file info of given path
|
||||||
|
func AssetInfo(path string) (os.FileInfo, error) {
|
||||||
|
return os.Stat(path)
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ja">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>go-bindata</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello Gin go-bindata middleware</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,51 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
assetfs "github.com/elazarl/go-bindata-assetfs"
|
||||||
|
"github.com/gin-gonic/contrib/static"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type binaryFileSystem struct {
|
||||||
|
fs http.FileSystem
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *binaryFileSystem) Open(name string) (http.File, error) {
|
||||||
|
return b.fs.Open(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *binaryFileSystem) Exists(prefix string, filepath string) bool {
|
||||||
|
|
||||||
|
if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
|
||||||
|
if _, err := b.fs.Open(p); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func BinaryFileSystem(root string) *binaryFileSystem {
|
||||||
|
fs := &assetfs.AssetFS{Asset, AssetDir, AssetInfo, root}
|
||||||
|
return &binaryFileSystem{
|
||||||
|
fs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
// $ go-bindata data/
|
||||||
|
// $ go build && ./bindata
|
||||||
|
//
|
||||||
|
func main() {
|
||||||
|
r := gin.Default()
|
||||||
|
|
||||||
|
r.Use(static.Serve("/static", BinaryFileSystem("data")))
|
||||||
|
r.GET("/ping", func(c *gin.Context) {
|
||||||
|
c.String(200, "test")
|
||||||
|
})
|
||||||
|
// Listen and Server in 0.0.0.0:8080
|
||||||
|
r.Run(":8080")
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/contrib/static"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := gin.Default()
|
||||||
|
|
||||||
|
// if Allow DirectoryIndex
|
||||||
|
//r.Use(static.Serve("/", static.LocalFile("/tmp", true)))
|
||||||
|
// set prefix
|
||||||
|
//r.Use(static.Serve("/static", static.LocalFile("/tmp", true)))
|
||||||
|
|
||||||
|
r.Use(static.Serve("/", static.LocalFile("/tmp", false)))
|
||||||
|
r.GET("/ping", func(c *gin.Context) {
|
||||||
|
c.String(200, "test")
|
||||||
|
})
|
||||||
|
// Listen and Server in 0.0.0.0:8080
|
||||||
|
r.Run(":8080")
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package static
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServeFileSystem interface {
|
||||||
|
http.FileSystem
|
||||||
|
Exists(prefix string, path string) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
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 !l.indexes && stats.IsDir() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package static
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
|
||||||
|
req, _ := http.NewRequest(method, path, nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r.ServeHTTP(w, req)
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyDirectory(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(ServeRoot("/", dir))
|
||||||
|
router.GET("/", func(c *gin.Context) {
|
||||||
|
c.String(200, "index")
|
||||||
|
})
|
||||||
|
router.GET("/a", func(c *gin.Context) {
|
||||||
|
c.String(200, "a")
|
||||||
|
})
|
||||||
|
router.GET("/"+filename, func(c *gin.Context) {
|
||||||
|
c.String(200, "this is not printed")
|
||||||
|
})
|
||||||
|
w := performRequest(router, "GET", "/")
|
||||||
|
assert.Equal(t, w.Code, 200)
|
||||||
|
assert.Equal(t, w.Body.String(), "index")
|
||||||
|
|
||||||
|
w = performRequest(router, "GET", "/"+filename)
|
||||||
|
assert.Equal(t, w.Code, 200)
|
||||||
|
assert.Equal(t, w.Body.String(), "Gin Web Framework")
|
||||||
|
|
||||||
|
w = performRequest(router, "GET", "/"+filename+"a")
|
||||||
|
assert.Equal(t, w.Code, 404)
|
||||||
|
|
||||||
|
w = performRequest(router, "GET", "/a")
|
||||||
|
assert.Equal(t, w.Code, 200)
|
||||||
|
assert.Equal(t, w.Body.String(), "a")
|
||||||
|
|
||||||
|
router2 := gin.New()
|
||||||
|
router2.Use(ServeRoot("/static", dir))
|
||||||
|
router2.GET("/"+filename, func(c *gin.Context) {
|
||||||
|
c.String(200, "this is printed")
|
||||||
|
})
|
||||||
|
|
||||||
|
w = performRequest(router2, "GET", "/")
|
||||||
|
assert.Equal(t, w.Code, 404)
|
||||||
|
|
||||||
|
w = performRequest(router2, "GET", "/static")
|
||||||
|
assert.Equal(t, w.Code, 404)
|
||||||
|
router2.GET("/static", func(c *gin.Context) {
|
||||||
|
c.String(200, "index")
|
||||||
|
})
|
||||||
|
|
||||||
|
w = performRequest(router2, "GET", "/static")
|
||||||
|
assert.Equal(t, w.Code, 200)
|
||||||
|
|
||||||
|
w = performRequest(router2, "GET", "/"+filename)
|
||||||
|
assert.Equal(t, w.Code, 200)
|
||||||
|
assert.Equal(t, w.Body.String(), "this is printed")
|
||||||
|
|
||||||
|
w = performRequest(router2, "GET", "/static/"+filename)
|
||||||
|
assert.Equal(t, w.Code, 200)
|
||||||
|
assert.Equal(t, w.Body.String(), "Gin Web Framework")
|
||||||
|
}
|
Loading…
Reference in New Issue