staticbin.go (1784B)
1 // Package staticbin based on https://github.com/martini-contrib/staticbin 2 package staticbin 3 4 import ( 5 "bytes" 6 "log" 7 "net/http" 8 "path" 9 "strings" 10 "time" 11 12 "github.com/labstack/echo" 13 ) 14 15 // Options ... 16 type Options struct { 17 // SkipLogging will disable [Static] log messages when a static file is served. 18 SkipLogging bool 19 // IndexFile defines which file to serve as index if it exists. 20 IndexFile string 21 // Path prefix 22 Dir string 23 } 24 25 func (o *Options) init() { 26 if o.IndexFile == "" { 27 o.IndexFile = "index.html" 28 } 29 } 30 31 // Static returns a middleware handler that serves static files in the given directory. 32 func Static(asset func(string) ([]byte, error), options ...Options) echo.MiddlewareFunc { 33 if asset == nil { 34 panic("asset is nil") 35 } 36 37 opt := Options{} 38 for _, o := range options { 39 opt = o 40 break 41 } 42 opt.init() 43 44 modtime := time.Now() 45 46 return func(next echo.HandlerFunc) echo.HandlerFunc { 47 48 return func(c echo.Context) error { 49 if c.Request().Method != http.MethodGet && c.Request().Method != http.MethodHead { 50 // Request is not correct. Go farther. 51 return next(c) 52 } 53 54 url := c.Request().URL.Path 55 if !strings.HasPrefix(url, opt.Dir) { 56 return next(c) 57 } 58 file := strings.TrimPrefix( 59 strings.TrimPrefix(url, opt.Dir), 60 "/", 61 ) 62 b, err := asset(file) 63 64 if err != nil { 65 // Try to serve the index file. 66 b, err = asset(path.Join(file, opt.IndexFile)) 67 68 if err != nil { 69 // Go farther if the asset could not be found. 70 return next(c) 71 } 72 } 73 74 if !opt.SkipLogging { 75 log.Println("[Static] Serving " + url) 76 } 77 78 c.Response().Writer.Header().Set("Cache-Control", "public, max-age=86400") 79 http.ServeContent(c.Response().Writer, c.Request(), url, modtime, bytes.NewReader(b)) 80 return nil 81 } 82 } 83 }