diff --git a/pkg/routes/static.go b/pkg/routes/static.go index 5c47061db0..9c9acfb947 100644 --- a/pkg/routes/static.go +++ b/pkg/routes/static.go @@ -9,6 +9,108 @@ import ( "github.com/labstack/echo/v4" ) +func staticWithConfig() 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 + } + if config.Filesystem == nil { + config.Filesystem = http.Dir(config.Root) + config.Root = "." + } + + // Index template + t, tErr := template.New("index").Parse(html) + if tErr != nil { + panic(fmt.Errorf("echo: %w", tErr)) + } + + 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 := path.Join(config.Root, path.Clean("/"+p)) // "/"+ for security + + if config.IgnoreBase { + routePath := path.Base(strings.TrimRight(c.Path(), "/*")) + baseURLPath := path.Base(p) + if baseURLPath == routePath { + i := strings.LastIndex(name, routePath) + name = name[:i] + strings.Replace(name[i:], routePath, "", 1) + } + } + + file, err := config.Filesystem.Open(name) + if err != nil { + if !isIgnorableOpenFileError(err) { + return err + } + + // file with that path did not exist, so we continue down in middleware/handler chain, hoping that we end up in + // handler that is meant to handle this request + if err = next(c); err == nil { + return err + } + + var he *echo.HTTPError + if !(errors.As(err, &he) && config.HTML5 && he.Code == http.StatusNotFound) { + return err + } + + file, err = config.Filesystem.Open(path.Join(config.Root, config.Index)) + if err != nil { + return err + } + } + + defer file.Close() + + info, err := file.Stat() + if err != nil { + return err + } + + if info.IsDir() { + index, err := config.Filesystem.Open(path.Join(name, config.Index)) + if err != nil { + if config.Browse { + return listDir(t, name, file, c.Response()) + } + + return next(c) + } + + defer index.Close() + + info, err = index.Stat() + if err != nil { + return err + } + + return serveFile(c, index, info) + } + + return serveFile(c, file, info) + } + } +} + func setupStaticFrontendFilesHandler(e *echo.Echo) { e.Use(middleware.GzipWithConfig(middleware.GzipConfig{ Level: 6,