labstack/echo
 Watch   
 Star   
 Fork   
1 hours ago
echo

v5.0.4 small fixes and improvements

What's Changed

New Contributors

Full Changelog: https://github.com/labstack/echo/compare/v5.0.3...v5.0.4

9 days ago
echo

v5.0.3 security (static middleware directory traversal under Windows)

Fix directory traversal vulnerability under Windows in Static middleware when default Echo filesystem is used. Reported by @shblue21 (https://github.com/labstack/echo/pull/2891).

This applies to cases when:

  • Windows is used as OS
  • middleware.StaticConfig.Filesystem is nil (default)
  • echo.Filesystem is has not been set explicitly (default)

Exposure is restricted to the active process working directory and its subfolders.

Full Changelog: https://github.com/labstack/echo/compare/v5.0.2...v5.0.3

12 days ago
echo

v5.0.2 security (static middleware folder browsing)

Security

Full Changelog: https://github.com/labstack/echo/compare/v5.0.1...v5.0.2

17 days ago
echo

v5.0.1 small fixes

What's Changed

New Contributors

Full Changelog: https://github.com/labstack/echo/compare/v5.0.0...v5.0.1

28 days ago
echo

V5 is out

Echo v5 is maintenance release with major breaking changes

  • Context is now struct instead of interface and we can add method to it in the future in minor versions.
  • Adds new Router interface for possible new routing implementations.
  • Drops old logging interface and uses moderm log/slog instead.
  • Rearranges alot of methods/function signatures to make them more consistent.

Upgrade notes and v4 support:

  • Echo v4 is supported with security* updates and bug fixes until 2026-12-31
  • If you are using Echo in a production environment, it is recommended to wait until after 2026-03-31 before upgrading.
  • Until 2026-03-31, any critical issues requiring breaking v5 API changes will be addressed, even if this violates semantic versioning.

See API_CHANGES_V5.md for public API changes between v4 and v5, notes on upgrading.

Upgrading TLDR:

If you are using Linux you can migrate easier parts like that:

find . -type f -name "*.go" -exec sed -i 's/ echo.Context/ *echo.Context/g' {} +
find . -type f -name "*.go" -exec sed -i 's/echo\/v4/echo\/v5/g' {} +

macOS

find . -type f -name "*.go" -exec sed -i '' 's/ echo.Context/ *echo.Context/g' {} +
find . -type f -name "*.go" -exec sed -i '' 's/echo\/v4/echo\/v5/g' {} +

or in your favorite IDE

Replace all:

  1. echo.Context -> *echo.Context
  2. echo/v4 -> echo/v5

This should solve most of the issues. Probably the hardest part is updating all the tests.

2026-01-01 18:57:24
echo

v4.15.0

Security

WARNING: If your application relies on cross-origin or same-site (same subdomain) requests do not blindly push this version to production

The CSRF middleware now supports the Sec-Fetch-Site header as a modern, defense-in-depth approach to CSRF protection, implementing the OWASP-recommended Fetch Metadata API alongside the traditional token-based mechanism.

How it works:

Modern browsers automatically send the Sec-Fetch-Site header with all requests, indicating the relationship between the request origin and the target. The middleware uses this to make security decisions:

  • same-origin or none: Requests are allowed (exact origin match or direct user navigation)
  • same-site: Falls back to token validation (e.g., subdomain to main domain)
  • cross-site: Blocked by default with 403 error for unsafe methods (POST, PUT, DELETE, PATCH)

For browsers that don't send this header (older browsers), the middleware seamlessly falls back to traditional token-based CSRF protection.

New Configuration Options:

  • TrustedOrigins []string: Allowlist specific origins for cross-site requests (useful for OAuth callbacks, webhooks)
  • AllowSecFetchSiteFunc func(echo.Context) (bool, error): Custom logic for same-site/cross-site request validation

Example:

e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
    // Allow OAuth callbacks from trusted provider
    TrustedOrigins: []string{"https://oauth-provider.com"},

    // Custom validation for same-site requests
    AllowSecFetchSiteFunc: func(c echo.Context) (bool, error) {
        // Your custom authorization logic here
        return validateCustomAuth(c), nil
        // return true, err  // blocks request with error
        // return true, nil  // allows CSRF request through
        // return false, nil // falls back to legacy token logic
    },
}))

PR: https://github.com/labstack/echo/pull/2858

Type-Safe Generic Parameter Binding

  • Added generic functions for type-safe parameter extraction and context access by @aldas in https://github.com/labstack/echo/pull/2856

    Echo now provides generic functions for extracting path, query, and form parameters with automatic type conversion, eliminating manual string parsing and type assertions.

    New Functions:

    • Path parameters: PathParam[T], PathParamOr[T]
    • Query parameters: QueryParam[T], QueryParamOr[T], QueryParams[T], QueryParamsOr[T]
    • Form values: FormParam[T], FormParamOr[T], FormParams[T], FormParamsOr[T]
    • Context store: ContextGet[T], ContextGetOr[T]

    Supported Types: Primitives (bool, string, int/uint variants, float32/float64), time.Duration, time.Time (with custom layouts and Unix timestamp support), and custom types implementing BindUnmarshaler, TextUnmarshaler, or JSONUnmarshaler.

    Example:

    // Before: Manual parsing
    idStr := c.Param("id")
    id, err := strconv.Atoi(idStr)
    
    // After: Type-safe with automatic parsing
    id, err := echo.PathParam[int](c, "id")
    
    // With default values
    page, err := echo.QueryParamOr[int](c, "page", 1)
    limit, err := echo.QueryParamOr[int](c, "limit", 20)
    
    // Type-safe context access (no more panics from type assertions)
    user, err := echo.ContextGet[*User](c, "user")

PR: https://github.com/labstack/echo/pull/2856

DEPRECATION NOTICE Timeout Middleware Deprecated - Use ContextTimeout Instead

The middleware.Timeout middleware has been deprecated due to fundamental architectural issues that cause data races. Use middleware.ContextTimeout or middleware.ContextTimeoutWithConfig instead.

Why is this being deprecated?

The Timeout middleware manipulates response writers across goroutine boundaries, which causes data races that cannot be reliably fixed without a complete architectural redesign. The middleware:

  • Swaps the response writer using http.TimeoutHandler
  • Must be the first middleware in the chain (fragile constraint)
  • Can cause races with other middleware (Logger, metrics, custom middleware)
  • Has been the source of multiple race condition fixes over the years

What should you use instead?

The ContextTimeout middleware (available since v4.12.0) provides timeout functionality using Go's standard context mechanism. It is:

  • Race-free by design
  • Can be placed anywhere in the middleware chain
  • Simpler and more maintainable
  • Compatible with all other middleware

Migration Guide:

// Before (deprecated):
e.Use(middleware.Timeout())

// After (recommended):
e.Use(middleware.ContextTimeout(30 * time.Second))

Important Behavioral Differences:

  1. Handler cooperation required: With ContextTimeout, your handlers must check context.Done() for cooperative cancellation. The old Timeout middleware would send a 503 response regardless of handler cooperation, but had data race issues.

  2. Error handling: ContextTimeout returns errors through the standard error handling flow. Handlers that receive context.DeadlineExceeded should handle it appropriately:

e.GET("/long-task", func(c echo.Context) error {
    ctx := c.Request().Context()

    // Example: database query with context
    result, err := db.QueryContext(ctx, "SELECT * FROM large_table")
    if err != nil {
        if errors.Is(err, context.DeadlineExceeded) {
            // Handle timeout
            return echo.NewHTTPError(http.StatusServiceUnavailable, "Request timeout")
        }
        return err
    }

    return c.JSON(http.StatusOK, result)
})
  1. Background tasks: For long-running background tasks, use goroutines with context:
e.GET("/async-task", func(c echo.Context) error {
    ctx := c.Request().Context()

    resultCh := make(chan Result, 1)
    errCh := make(chan error, 1)

    go func() {
        result, err := performLongTask(ctx)
        if err != nil {
            errCh <- err
            return
        }
        resultCh <- result
    }()

    select {
    case result := <-resultCh:
        return c.JSON(http.StatusOK, result)
    case err := <-errCh:
        return err
    case <-ctx.Done():
        return echo.NewHTTPError(http.StatusServiceUnavailable, "Request timeout")
    }
})

Full Changelog: https://github.com/labstack/echo/compare/v4.14.0...v4.15.0

2025-12-12 04:49:38
echo

v4.14.0

middleware.Logger() has been deprecated. For request logging, use middleware.RequestLogger() or middleware.RequestLoggerWithConfig().

middleware.RequestLogger() replaces middleware.Logger(), offering comparable configuration while relying on the Go standard library’s new slog logger.

The previous default output format was JSON. The new default follows the standard slog logger settings. To continue emitting request logs in JSON, configure slog accordingly:

slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))
e.Use(middleware.RequestLogger())

If you are developing anything more substantial than a demo, use middleware.RequestLoggerWithConfig()

Security

What's Changed

New Contributors

Full Changelog: https://github.com/labstack/echo/compare/v4.13.4...v4.14.0

2025-05-22 19:18:29
echo

v4.13.4

What's Changed

Security

New Contributors

Full Changelog: https://github.com/labstack/echo/compare/v4.13.3...v4.13.4

2024-12-19 12:51:34
echo