Static
Static middleware serves files from a root directory. The example below serves public/index.html at /.
From the echox checkout, run cd reference/static && go run ., then open http://localhost:1323/.
// SPDX-License-Identifier: MIT
// This complete example is the source for the Static middleware documentation.package main
import ( "github.com/labstack/echo/v5" "github.com/labstack/echo/v5/middleware")
func main() { e := echo.New() e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ Root: "public", EnablePathUnescaping: false, // Keep encoded slashes encoded when route guards protect files. }))
if err := e.Start(":1323"); err != nil { e.Logger.Error("server stopped", "error", err) }}The page imports the same file that documentation CI compiles. The example keeps EnablePathUnescaping false, the safe default for encoded slashes.
Custom configuration
Section titled “Custom configuration”Set Root to the directory to serve. Browse enables directory listings, HTML5 forwards missing paths to the index file for a single-page application, and Filesystem lets you provide an fs.FS. Use IgnoreBase when a group’s URL prefix should not become part of the file path.
In Echo v5.4.0, HTML5 mode serves the index for a router-level 404. A matched route’s own 404 passes through. This matters when an SPA and API routes share a server.
Example 1
Section titled “Example 1”When Static middleware is attached to a non-root group, Echo normally includes the group’s URL prefix in the filesystem path. Set IgnoreBase: true if your filesystem root already points inside that prefix. A group needs a matching route for its middleware to run.
Example 2
Section titled “Example 2”To serve an embedded filesystem, set Filesystem to your embed.FS and Root to the asset directory within it. See the embed resources cookbook for a complete program.
Configuration
Section titled “Configuration”The table comes from the exported fields in the recorded Echo revision. It identifies deprecated fields but does not infer defaults or security behavior.
StaticConfig · github.com/labstack/echo/v5@5196b9b
| Field | Type | Description | Source |
|---|---|---|---|
Skipper | Skipper | Skipper defines a function to skip middleware. | L26 |
Root | string | Root directory from where the static content is served (relative to given Filesystem). `Root: "."` means root folder from Filesystem. Required. | L31 |
Filesystem | fs.FS | Filesystem provides access to the static content. Optional. Defaults to echo.Filesystem (serves files from `.` folder where executable is started) | L35 |
Index | string | Index file for serving a directory. Optional. Default value "index.html". | L39 |
HTML5 | bool | 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. | L44 |
Browse | bool | Enable directory browsing. Optional. Default value false. | L48 |
IgnoreBase | bool | Enable ignoring of the base of the URL path. Example: when assigning a static middleware to a non root path group, the filesystem path is not doubled Optional. Default value false. | L54 |
DisablePathUnescapingDeprecated | bool | Deprecated: this field is ignored, use EnablePathUnescaping instead. DisablePathUnescaping will be removed in a future version. Note: previously the zero value (false) enabled unescaping, which was the unsafe default. | L58 |
EnablePathUnescaping | bool | EnablePathUnescaping enables unescaping of the request path (or of the wildcard param `*` when the middleware is used on a wildcard route) before the file is looked up. Default false (safe): the path is used in the same form as the router matched it, so encoded characters such as encoded slashes (%2f) are NOT decoded, preventing ACL bypass where /admin%2fprivate.txt bypasses a /admin/* route guard by not matching that route but being decoded to admin/private.txt. As a consequence, file names that the client sends with non-default escaping (e.g. `%2C`, `%40` or lowercase hex like `%c3%a9`) are not found. Set to true only when serving files whose names need such unescaping and you are not relying on route-based ACL guards to restrict access. Paths with ".", ".." or empty segments are never served, also after unescaping. Enabling echo.RouterConfig.UseEscapedPathForMatching makes this field irrelevant and can lead to security issues when using different Routes to exclude some of the files from being served. e.g. if you serve files from directory as such and use different route to exclude some of the files from being served. 0. given folder structure: public/ public/index.html public/admin/private.txt 1. share `public/` folder contents from the server root with `e.Static("/", "public")` 2. naively assume that everything under /admin folder is now forbidden e.GET("/admin/*", func(c *Context) error { return echo.ErrForbidden }) Then request to `/assets/../admin%2fprivate.txt` will be served as router does not match it to guarded route. | L80 |
DirectoryListTemplate | string | DirectoryListTemplate is template to list directory contents Optional. Default to `directoryListHTMLTemplate` constant below. | L84 |
Default configuration
Section titled “Default configuration”Index defaults to index.html. EnablePathUnescaping defaults to false, so
encoded slashes in the wildcard path stay encoded. DisablePathUnescaping is
deprecated and ignored by current Echo; use EnablePathUnescaping when you
explicitly need unescaping.
Security in Echo v5.4.0
Section titled “Security in Echo v5.4.0”By default, files are resolved from the same form of the path that the router
matched. File names requested with non-default escaping, such as %2C, %40, or
lowercase hex, need EnablePathUnescaping. Paths containing ., .., or empty
segments (for example /assets//app.js) return 404; HTML5 mode still serves the
index. Enabling path unescaping decodes encoded slashes too, so do not combine it
with route-based access control for subdirectories.