initital.

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
Bo-Yi Wu 2016-12-13 10:03:34 +08:00
parent b0491c78a9
commit 7232ea358a
9 changed files with 401 additions and 24 deletions

27
.gitignore vendored
View File

@ -1,24 +1,5 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
*/Godeps/*
!*/Godeps/Godeps.json
# Folders
_obj
_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
coverage.out
dump.rdb

22
.travis.yml Normal file
View File

@ -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

View File

@ -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
## 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"
```

121
example/bindata/bindata.go Normal file
View File

@ -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)
}

View File

@ -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>

View File

@ -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")
}

22
example/simple/example.go Normal file
View File

@ -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")
}

62
static.go Normal file
View File

@ -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()
}
}
}

86
static_test.go Normal file
View File

@ -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")
}