summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/labstack/echo/v4/middleware/static.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/labstack/echo/v4/middleware/static.go')
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/static.go229
1 files changed, 229 insertions, 0 deletions
diff --git a/vendor/github.com/labstack/echo/v4/middleware/static.go b/vendor/github.com/labstack/echo/v4/middleware/static.go
new file mode 100644
index 00000000..bc2087a7
--- /dev/null
+++ b/vendor/github.com/labstack/echo/v4/middleware/static.go
@@ -0,0 +1,229 @@
+package middleware
+
+import (
+ "fmt"
+ "html/template"
+ "net/http"
+ "net/url"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+
+ "github.com/labstack/echo/v4"
+ "github.com/labstack/gommon/bytes"
+)
+
+type (
+ // StaticConfig defines the config for Static middleware.
+ StaticConfig struct {
+ // Skipper defines a function to skip middleware.
+ Skipper Skipper
+
+ // Root directory from where the static content is served.
+ // Required.
+ Root string `yaml:"root"`
+
+ // Index file for serving a directory.
+ // Optional. Default value "index.html".
+ Index string `yaml:"index"`
+
+ // Enable HTML5 mode by forwarding all not-found requests to root so that
+ // SPA (single-page application) can handle the routing.
+ // Optional. Default value false.
+ HTML5 bool `yaml:"html5"`
+
+ // Enable directory browsing.
+ // Optional. Default value false.
+ Browse bool `yaml:"browse"`
+ }
+)
+
+const html = `
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <title>{{ .Name }}</title>
+ <style>
+ body {
+ font-family: Menlo, Consolas, monospace;
+ padding: 48px;
+ }
+ header {
+ padding: 4px 16px;
+ font-size: 24px;
+ }
+ ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 20px 0 0 0;
+ display: flex;
+ flex-wrap: wrap;
+ }
+ li {
+ width: 300px;
+ padding: 16px;
+ }
+ li a {
+ display: block;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ text-decoration: none;
+ transition: opacity 0.25s;
+ }
+ li span {
+ color: #707070;
+ font-size: 12px;
+ }
+ li a:hover {
+ opacity: 0.50;
+ }
+ .dir {
+ color: #E91E63;
+ }
+ .file {
+ color: #673AB7;
+ }
+ </style>
+</head>
+<body>
+ <header>
+ {{ .Name }}
+ </header>
+ <ul>
+ {{ range .Files }}
+ <li>
+ {{ if .Dir }}
+ {{ $name := print .Name "/" }}
+ <a class="dir" href="{{ $name }}">{{ $name }}</a>
+ {{ else }}
+ <a class="file" href="{{ .Name }}">{{ .Name }}</a>
+ <span>{{ .Size }}</span>
+ {{ end }}
+ </li>
+ {{ end }}
+ </ul>
+</body>
+</html>
+`
+
+var (
+ // DefaultStaticConfig is the default Static middleware config.
+ DefaultStaticConfig = StaticConfig{
+ Skipper: DefaultSkipper,
+ Index: "index.html",
+ }
+)
+
+// Static returns a Static middleware to serves static content from the provided
+// root directory.
+func Static(root string) echo.MiddlewareFunc {
+ c := DefaultStaticConfig
+ c.Root = root
+ return StaticWithConfig(c)
+}
+
+// StaticWithConfig returns a Static middleware with config.
+// See `Static()`.
+func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc {
+ // Defaults
+ if config.Root == "" {
+ config.Root = "." // For security we want to restrict to CWD.
+ }
+ if config.Skipper == nil {
+ config.Skipper = DefaultStaticConfig.Skipper
+ }
+ if config.Index == "" {
+ config.Index = DefaultStaticConfig.Index
+ }
+
+ // Index template
+ t, err := template.New("index").Parse(html)
+ if err != nil {
+ panic(fmt.Sprintf("echo: %v", err))
+ }
+
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) (err error) {
+ if config.Skipper(c) {
+ return next(c)
+ }
+
+ p := c.Request().URL.Path
+ if strings.HasSuffix(c.Path(), "*") { // When serving from a group, e.g. `/static*`.
+ p = c.Param("*")
+ }
+ p, err = url.PathUnescape(p)
+ if err != nil {
+ return
+ }
+ name := filepath.Join(config.Root, path.Clean("/"+p)) // "/"+ for security
+
+ fi, err := os.Stat(name)
+ if err != nil {
+ if os.IsNotExist(err) {
+ if err = next(c); err != nil {
+ if he, ok := err.(*echo.HTTPError); ok {
+ if config.HTML5 && he.Code == http.StatusNotFound {
+ return c.File(filepath.Join(config.Root, config.Index))
+ }
+ }
+ return
+ }
+ }
+ return
+ }
+
+ if fi.IsDir() {
+ index := filepath.Join(name, config.Index)
+ fi, err = os.Stat(index)
+
+ if err != nil {
+ if config.Browse {
+ return listDir(t, name, c.Response())
+ }
+ if os.IsNotExist(err) {
+ return next(c)
+ }
+ return
+ }
+
+ return c.File(index)
+ }
+
+ return c.File(name)
+ }
+ }
+}
+
+func listDir(t *template.Template, name string, res *echo.Response) (err error) {
+ file, err := os.Open(name)
+ if err != nil {
+ return
+ }
+ files, err := file.Readdir(-1)
+ if err != nil {
+ return
+ }
+
+ // Create directory index
+ res.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8)
+ data := struct {
+ Name string
+ Files []interface{}
+ }{
+ Name: name,
+ }
+ for _, f := range files {
+ data.Files = append(data.Files, struct {
+ Name string
+ Dir bool
+ Size string
+ }{f.Name(), f.IsDir(), bytes.Format(f.Size())})
+ }
+ return t.Execute(res, data)
+}