63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
|
//go:build !go1.16
|
||
|
// +build !go1.16
|
||
|
|
||
|
package echo
|
||
|
|
||
|
import (
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
)
|
||
|
|
||
|
type filesystem struct {
|
||
|
}
|
||
|
|
||
|
func createFilesystem() filesystem {
|
||
|
return filesystem{}
|
||
|
}
|
||
|
|
||
|
// Static registers a new route with path prefix to serve static files from the
|
||
|
// provided root directory.
|
||
|
func (e *Echo) Static(prefix, root string) *Route {
|
||
|
if root == "" {
|
||
|
root = "." // For security we want to restrict to CWD.
|
||
|
}
|
||
|
return e.static(prefix, root, e.GET)
|
||
|
}
|
||
|
|
||
|
func (common) static(prefix, root string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route) *Route {
|
||
|
h := func(c Context) error {
|
||
|
p, err := url.PathUnescape(c.Param("*"))
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
name := filepath.Join(root, filepath.Clean("/"+p)) // "/"+ for security
|
||
|
fi, err := os.Stat(name)
|
||
|
if err != nil {
|
||
|
// The access path does not exist
|
||
|
return NotFoundHandler(c)
|
||
|
}
|
||
|
|
||
|
// If the request is for a directory and does not end with "/"
|
||
|
p = c.Request().URL.Path // path must not be empty.
|
||
|
if fi.IsDir() && p[len(p)-1] != '/' {
|
||
|
// Redirect to ends with "/"
|
||
|
return c.Redirect(http.StatusMovedPermanently, p+"/")
|
||
|
}
|
||
|
return c.File(name)
|
||
|
}
|
||
|
// Handle added routes based on trailing slash:
|
||
|
// /prefix => exact route "/prefix" + any route "/prefix/*"
|
||
|
// /prefix/ => only any route "/prefix/*"
|
||
|
if prefix != "" {
|
||
|
if prefix[len(prefix)-1] == '/' {
|
||
|
// Only add any route for intentional trailing slash
|
||
|
return get(prefix+"*", h)
|
||
|
}
|
||
|
get(prefix, h)
|
||
|
}
|
||
|
return get(prefix+"/*", h)
|
||
|
}
|