mirror of
https://github.com/labstack/echo.git
synced 2024-11-28 08:38:39 +02:00
- Static back as middleware Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
parent
2f8639b7e6
commit
130c548826
@ -238,6 +238,7 @@ Middleware | Description
|
|||||||
[Gzip](https://labstack.com/echo/guide/middleware/#gzip-middleware:37ab2f15ff048f67959bcac0a6032f32) | Send gzip HTTP response
|
[Gzip](https://labstack.com/echo/guide/middleware/#gzip-middleware:37ab2f15ff048f67959bcac0a6032f32) | Send gzip HTTP response
|
||||||
[BasicAuth](https://labstack.com/echo/guide/middleware/#basicauth-middleware:37ab2f15ff048f67959bcac0a6032f32) | HTTP basic authentication
|
[BasicAuth](https://labstack.com/echo/guide/middleware/#basicauth-middleware:37ab2f15ff048f67959bcac0a6032f32) | HTTP basic authentication
|
||||||
[CORS](https://labstack.com/echo/guide/middleware/#cors-middleware:37ab2f15ff048f67959bcac0a6032f32) | Cross-Origin Resource Sharing
|
[CORS](https://labstack.com/echo/guide/middleware/#cors-middleware:37ab2f15ff048f67959bcac0a6032f32) | Cross-Origin Resource Sharing
|
||||||
|
[Static](https://labstack.com/echo/guide/static-files/#using-static-middleware:123f9d1043075fe4874616541b409e4d) | Serve static files
|
||||||
[AddTrailingSlash](https://labstack.com/echo/guide/middleware/#addtrailingslash-middleware:37ab2f15ff048f67959bcac0a6032f32) | Add trailing slash to the request URI
|
[AddTrailingSlash](https://labstack.com/echo/guide/middleware/#addtrailingslash-middleware:37ab2f15ff048f67959bcac0a6032f32) | Add trailing slash to the request URI
|
||||||
[RemoveTrailingSlash](https://labstack.com/echo/guide/middleware/#removetrailingslash-middleware:37ab2f15ff048f67959bcac0a6032f32) | Remove trailing slash from the request URI
|
[RemoveTrailingSlash](https://labstack.com/echo/guide/middleware/#removetrailingslash-middleware:37ab2f15ff048f67959bcac0a6032f32) | Remove trailing slash from the request URI
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -367,12 +366,14 @@ func (c *context) File(file string) error {
|
|||||||
|
|
||||||
fi, _ := f.Stat()
|
fi, _ := f.Stat()
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
file = path.Join(file, "index.html")
|
file = filepath.Join(file, "index.html")
|
||||||
f, err = os.Open(file)
|
f, err = os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrNotFound
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
fi, _ = f.Stat()
|
if fi, err = f.Stat(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return c.ServeContent(f, fi.Name(), fi.ModTime())
|
return c.ServeContent(f, fi.Name(), fi.ModTime())
|
||||||
}
|
}
|
||||||
|
16
echo.go
16
echo.go
@ -45,6 +45,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -374,19 +375,14 @@ func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middlew
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static serves static files from provided `root` directory for `/<path>*` URL.
|
// Static serves static files from provided root directory with URL path prefix.
|
||||||
func (e *Echo) Static(path, root string) {
|
func (e *Echo) Static(prefix, root string) {
|
||||||
e.StaticWithConfig(path, StaticConfig{
|
e.Get(prefix+"*", func(c Context) error {
|
||||||
Root: root,
|
return c.File(path.Join(root, c.P(0)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticWithConfig serves static files with provided config for `/<path>*` URL.
|
// File serves provided file for URL path.
|
||||||
func (e *Echo) StaticWithConfig(path string, config StaticConfig) {
|
|
||||||
e.Get(path+"*", StaticWithConfig(config))
|
|
||||||
}
|
|
||||||
|
|
||||||
// File serve provided file for `/<path>` HTTP path.
|
|
||||||
func (e *Echo) File(path, file string) {
|
func (e *Echo) File(path, file string) {
|
||||||
e.Get(path, func(c Context) error {
|
e.Get(path, func(c Context) error {
|
||||||
return c.File(file)
|
return c.File(file)
|
||||||
|
25
group.go
25
group.go
@ -7,6 +7,7 @@ type (
|
|||||||
Group struct {
|
Group struct {
|
||||||
prefix string
|
prefix string
|
||||||
middleware []MiddlewareFunc
|
middleware []MiddlewareFunc
|
||||||
|
initialized bool
|
||||||
echo *Echo
|
echo *Echo
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -82,26 +83,24 @@ func (g *Group) Group(prefix string, m ...MiddlewareFunc) *Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Static implements `Echo#Static()` for sub-routes within the Group.
|
// Static implements `Echo#Static()` for sub-routes within the Group.
|
||||||
func (g *Group) Static(path, root string) {
|
func (g *Group) Static(prefix, root string) {
|
||||||
g.StaticWithConfig(path, StaticConfig{
|
g.echo.Static(g.prefix+prefix, root)
|
||||||
Root: root,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticWithConfig implements `Echo#StaticWithConfig()` for sub-routes within the
|
|
||||||
// Group.
|
|
||||||
func (g *Group) StaticWithConfig(path string, config StaticConfig) {
|
|
||||||
g.Get(path+"*", StaticWithConfig(config))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// File implements `Echo#File()` for sub-routes within the Group.
|
// File implements `Echo#File()` for sub-routes within the Group.
|
||||||
func (g *Group) File(path, file string) {
|
func (g *Group) File(path, file string) {
|
||||||
g.Get(path, func(c Context) error {
|
g.echo.File(g.prefix+path, file)
|
||||||
return c.File(file)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
|
func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
|
||||||
middleware = append(g.middleware, middleware...)
|
middleware = append(g.middleware, middleware...)
|
||||||
|
if !g.initialized {
|
||||||
|
// Allow all requests to reach the group as they might get dropped if router
|
||||||
|
// doesn't find a match, making none of the group middleware process.
|
||||||
|
g.echo.Any(g.prefix+"*", func(c Context) error {
|
||||||
|
return ErrNotFound
|
||||||
|
}, middleware...)
|
||||||
|
g.initialized = true
|
||||||
|
}
|
||||||
g.echo.add(method, g.prefix+path, handler, middleware...)
|
g.echo.add(method, g.prefix+path, handler, middleware...)
|
||||||
}
|
}
|
||||||
|
119
middleware/static.go
Normal file
119
middleware/static.go
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// StaticConfig defines the config for static middleware.
|
||||||
|
StaticConfig struct {
|
||||||
|
// Root is the directory from where the static content is served.
|
||||||
|
// Required.
|
||||||
|
Root string `json:"root"`
|
||||||
|
|
||||||
|
// Index is the list of index files to be searched and used when serving
|
||||||
|
// a directory.
|
||||||
|
// Optional with default value as []string{"index.html"}.
|
||||||
|
Index []string `json:"index"`
|
||||||
|
|
||||||
|
// Browse is a flag to enable/disable directory browsing.
|
||||||
|
// Optional with default value as false.
|
||||||
|
Browse bool `json:"browse"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultStaticConfig is the default static middleware config.
|
||||||
|
DefaultStaticConfig = StaticConfig{
|
||||||
|
Index: []string{"index.html"},
|
||||||
|
Browse: false,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 from config.
|
||||||
|
// See `Static()`.
|
||||||
|
func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc {
|
||||||
|
// Defaults
|
||||||
|
if config.Index == nil {
|
||||||
|
config.Index = DefaultStaticConfig.Index
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
fs := http.Dir(config.Root)
|
||||||
|
p := c.Request().URL().Path()
|
||||||
|
if strings.Contains(c.Path(), "*") { // If serving from a group, e.g. `/static*`.
|
||||||
|
p = c.P(0)
|
||||||
|
}
|
||||||
|
file := path.Clean(p)
|
||||||
|
f, err := fs.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
fi, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.IsDir() {
|
||||||
|
/* NOTE:
|
||||||
|
Not checking the Last-Modified header as it caches the response `304` when
|
||||||
|
changing different directories for the same path.
|
||||||
|
*/
|
||||||
|
d := f
|
||||||
|
|
||||||
|
// Index file
|
||||||
|
// TODO: search all files
|
||||||
|
file = path.Join(file, config.Index[0])
|
||||||
|
f, err = fs.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
if config.Browse {
|
||||||
|
dirs, err := d.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a directory index
|
||||||
|
rs := c.Response()
|
||||||
|
rs.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8)
|
||||||
|
if _, err = fmt.Fprintf(rs, "<pre>\n"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, d := range dirs {
|
||||||
|
name := d.Name()
|
||||||
|
color := "#212121"
|
||||||
|
if d.IsDir() {
|
||||||
|
color = "#e91e63"
|
||||||
|
name += "/"
|
||||||
|
}
|
||||||
|
if _, err = fmt.Fprintf(rs, "<a href=\"%s\" style=\"color: %s;\">%s</a>\n", name, color, name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = fmt.Fprintf(rs, "</pre>\n")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if fi, err = f.Stat(); err != nil { // Index file
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c.ServeContent(f, fi.Name(), fi.ModTime())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
static.go
110
static.go
@ -1,110 +0,0 @@
|
|||||||
package echo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
// StaticConfig defines the config for static handler.
|
|
||||||
StaticConfig struct {
|
|
||||||
// Root is the directory from where the static content is served.
|
|
||||||
// Required.
|
|
||||||
Root string `json:"root"`
|
|
||||||
|
|
||||||
// Index is the list of index files to be searched and used when serving
|
|
||||||
// a directory.
|
|
||||||
// Optional with default value as []string{"index.html"}.
|
|
||||||
Index []string `json:"index"`
|
|
||||||
|
|
||||||
// Browse is a flag to enable/disable directory browsing.
|
|
||||||
// Optional with default value as false.
|
|
||||||
Browse bool `json:"browse"`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultStaticConfig is the default static handler config.
|
|
||||||
DefaultStaticConfig = StaticConfig{
|
|
||||||
Index: []string{"index.html"},
|
|
||||||
Browse: false,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Static returns a static handler to serves static content from the provided
|
|
||||||
// root directory.
|
|
||||||
func Static(root string) HandlerFunc {
|
|
||||||
c := DefaultStaticConfig
|
|
||||||
c.Root = root
|
|
||||||
return StaticWithConfig(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticWithConfig returns a static handler from config.
|
|
||||||
// See `Static()`.
|
|
||||||
func StaticWithConfig(config StaticConfig) HandlerFunc {
|
|
||||||
// Defaults
|
|
||||||
if config.Index == nil {
|
|
||||||
config.Index = DefaultStaticConfig.Index
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(c Context) error {
|
|
||||||
fs := http.Dir(config.Root)
|
|
||||||
file := path.Clean(c.P(0))
|
|
||||||
f, err := fs.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
fi, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.IsDir() {
|
|
||||||
/* NOTE:
|
|
||||||
Not checking the Last-Modified header as it caches the response `304` when
|
|
||||||
changing different directories for the same path.
|
|
||||||
*/
|
|
||||||
d := f
|
|
||||||
|
|
||||||
// Index file
|
|
||||||
// TODO: search all files
|
|
||||||
file = path.Join(file, config.Index[0])
|
|
||||||
f, err = fs.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
||||||
if config.Browse {
|
|
||||||
dirs, err := d.Readdir(-1)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a directory index
|
|
||||||
rs := c.Response()
|
|
||||||
rs.Header().Set(HeaderContentType, MIMETextHTMLCharsetUTF8)
|
|
||||||
if _, err = fmt.Fprintf(rs, "<pre>\n"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, d := range dirs {
|
|
||||||
name := d.Name()
|
|
||||||
color := "#212121"
|
|
||||||
if d.IsDir() {
|
|
||||||
color = "#e91e63"
|
|
||||||
name += "/"
|
|
||||||
}
|
|
||||||
if _, err = fmt.Fprintf(rs, "<a href=\"%s\" style=\"color: %s;\">%s</a>\n", name, color, name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err = fmt.Fprintf(rs, "</pre>\n")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if fi, err = f.Stat(); err != nil { // Index file
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c.ServeContent(f, fi.Name(), fi.ModTime())
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user