Documentation
¶
Overview ¶
Example (ErrorHandlerBasic) ¶
e := echo.New()
e.HTTPErrorHandler = middleware.ErrorHandler(e.HTTPErrorHandler)
e.GET("/users/:id", func(_ *echo.Context) error {
return echo.NewHTTPError(http.StatusNotFound, "User not found")
})
_ = e.Start(":8080")
Example (ErrorHandlerCustomResponse) ¶
e := echo.New()
config := &middleware.ErrorHandlerConfig{ //nolint:exhaustruct
CustomErrorResponse: func(ctx *echo.Context, err error, code int) map[string]any {
return map[string]any{
"success": false,
"error": map[string]any{
"code": code,
"message": err.Error(),
},
"path": ctx.Request().URL.Path,
"timestamp": "2024-01-01T00:00:00Z",
}
},
}
e.HTTPErrorHandler = middleware.ErrorHandler(e.HTTPErrorHandler, config)
e.GET("/users/:id", func(_ *echo.Context) error {
return echo.NewHTTPError(http.StatusNotFound, "User not found")
})
_ = e.Start(":8080")
Example (ErrorHandlerProduction) ¶
e := echo.New()
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
config := &middleware.ErrorHandlerConfig{ //nolint:exhaustruct
Logger: &logger,
LogErrors: true,
IncludeInternalErrors: false,
}
e.HTTPErrorHandler = middleware.ErrorHandler(e.HTTPErrorHandler, config)
e.GET("/users/:id", func(_ *echo.Context) error {
dbErr := errors.New("database connection timeout") //nolint:err113
baseErr := echo.NewHTTPError(http.StatusServiceUnavailable, "Service temporarily unavailable")
return baseErr.Wrap(dbErr)
})
_ = e.Start(":8080")
Example (ErrorHandlerWithInternalErrors) ¶
e := echo.New()
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
config := &middleware.ErrorHandlerConfig{ //nolint:exhaustruct
Logger: &logger,
LogErrors: true,
IncludeInternalErrors: true, // WARNING: Only use in development!
}
e.HTTPErrorHandler = middleware.ErrorHandler(e.HTTPErrorHandler, config)
e.GET("/users/:id", func(_ *echo.Context) error {
dbErr := errors.New("database connection timeout") //nolint:err113
baseErr := echo.NewHTTPError(http.StatusServiceUnavailable, "Service temporarily unavailable")
return baseErr.Wrap(dbErr)
})
_ = e.Start(":8080")
Example (ErrorHandlerWithLogging) ¶
e := echo.New()
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
config := &middleware.ErrorHandlerConfig{ //nolint:exhaustruct
Logger: &logger,
LogErrors: true,
}
e.HTTPErrorHandler = middleware.ErrorHandler(e.HTTPErrorHandler, config)
e.GET("/users/:id", func(_ *echo.Context) error {
return echo.NewHTTPError(http.StatusNotFound, "User not found")
})
_ = e.Start(":8080")
Index ¶
- Constants
- Variables
- func ErrorHandler(next echo.HTTPErrorHandler, config ...*ErrorHandlerConfig) echo.HTTPErrorHandler
- func GetAPIKey(c *echo.Context) string
- func GetHandler(c *echo.Context) string
- func GetRateLimitRequests(c *echo.Context) int
- func GetRateLimitWindow(c *echo.Context) int
- func GetRequestID(c *echo.Context) string
- func GetTenantID(c *echo.Context) string
- func GetToken(c *echo.Context) string
- func JWT(kf keyfunc.Keyfunc) echo.MiddlewareFunc
- func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc
- func RequestID(skipper middleware.Skipper) echo.MiddlewareFunc
- func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc
- func RequestLogger(log zerolog.Logger, extraLogFieldExtractor ...LogFieldExtractor) echo.MiddlewareFunc
- type ErrorHandlerConfig
- type ExtendedClaims
- type JWTConfig
- type LogFieldExtractor
- type RequestIDConfig
Examples ¶
Constants ¶
View Source
const ( ContextKeyTenantID string = "tenantID" ContextKeyRateLimitReqs string = "rateLimitRequests" ContextKeyRateLimitWin string = "rateLimitWindow" ContextKeyAPIKey string = "apiKey" ContextKeyRequestID string = "requestID" ContextKeyBody string = "body" ContextKeyToken string = "token" ContextKeyClaims string = "claims" ContextKeyHandler string = "handler" )
View Source
const ( HeaderXAPIKey = "X-Api-Key" //nolint:gosec HeaderXRequestID = "X-Request-ID" HeaderXSignature = "X-Signature" HeaderXTimestamp = "X-Timestamp" )
View Source
const ( HeaderRateLimitLimit = "X-Ratelimit-Limit" HeaderRateLimitRemaining = "X-Ratelimit-Remaining" HeaderRateLimitReset = "X-Ratelimit-Reset" )
Variables ¶
View Source
var ( ErrTokenRequired = echo.NewHTTPError(http.StatusUnauthorized, "Authorization header is required") ErrJWKSFetchFailed = echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch JWKS") ErrInvalidToken = echo.NewHTTPError(http.StatusUnauthorized, "Invalid token") )
View Source
var ( ErrClaimsNotFound = errors.New("jwt claims: not found in context") ErrClaimsTypeAssertionFailed = errors.New("jwt claims: type assertion failed") )
Functions ¶
func ErrorHandler ¶
func ErrorHandler(next echo.HTTPErrorHandler, config ...*ErrorHandlerConfig) echo.HTTPErrorHandler
func GetHandler ¶ added in v1.3.0
func GetRateLimitRequests ¶
func GetRateLimitWindow ¶
func GetRequestID ¶
func GetTenantID ¶
func JWTWithConfig ¶ added in v1.3.4
func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc
func RequestID ¶
func RequestID(skipper middleware.Skipper) echo.MiddlewareFunc
Example ¶
e := echo.New()
e.Use(middleware.RequestID(echomiddleware.DefaultSkipper))
e.GET("/api/users", func(c *echo.Context) error {
requestID := middleware.GetRequestID(c)
return c.JSON(http.StatusOK, map[string]string{
"request_id": requestID,
"message": "User list",
})
})
req := httptest.NewRequest(http.MethodGet, "/api/users", nil)
req.Header.Set(middleware.HeaderXRequestID, uuid.New().String())
rec := httptest.NewRecorder()
e.ServeHTTP(rec, req)
fmt.Println("Status:", rec.Code)
Output: Status: 200
func RequestIDWithConfig ¶
func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc
Example (AutoGenerate) ¶
e := echo.New()
config := middleware.RequestIDConfig{
Skipper: echomiddleware.DefaultSkipper,
AutoGenerate: true,
Generator: uuid.NewString,
Validator: uuid.Validate,
}
e.Use(middleware.RequestIDWithConfig(config))
e.GET("/api/users", func(c *echo.Context) error {
requestID := middleware.GetRequestID(c)
return c.JSON(http.StatusOK, map[string]string{
"request_id": requestID,
"message": "User list",
})
})
req := httptest.NewRequest(http.MethodGet, "/api/users", nil)
rec := httptest.NewRecorder()
e.ServeHTTP(rec, req)
fmt.Println("Status:", rec.Code)
fmt.Println("Has Request ID in response:", rec.Header().Get(middleware.HeaderXRequestID) != "")
Output: Status: 200 Has Request ID in response: true
Example (Custom) ¶
e := echo.New()
config := middleware.RequestIDConfig{
Skipper: echomiddleware.DefaultSkipper,
AutoGenerate: true,
Generator: func() string {
return fmt.Sprintf("REQ-%d-%s", 1234567890, uuid.New().String()[:8])
},
Validator: func(id string) error {
if len(id) == 0 {
return errors.New("request ID cannot be empty") //nolint:err113
}
return nil
},
}
e.Use(middleware.RequestIDWithConfig(config))
e.GET("/api/users", func(c *echo.Context) error {
requestID := middleware.GetRequestID(c)
return c.JSON(http.StatusOK, map[string]string{
"request_id": requestID,
"message": "User list",
})
})
req := httptest.NewRequest(http.MethodGet, "/api/users", nil)
req.Header.Set(middleware.HeaderXRequestID, "CUSTOM-123-ABC")
rec := httptest.NewRecorder()
e.ServeHTTP(rec, req)
fmt.Println("Status:", rec.Code)
Output: Status: 200
func RequestLogger ¶
func RequestLogger(log zerolog.Logger, extraLogFieldExtractor ...LogFieldExtractor) echo.MiddlewareFunc
Types ¶
type ErrorHandlerConfig ¶
type ExtendedClaims ¶
type ExtendedClaims struct {
Azp string `json:"azp"`
jwt.RegisteredClaims
}
func GetExtendedClaimsFromContext ¶
func GetExtendedClaimsFromContext(c *echo.Context) (*ExtendedClaims, error)
func (*ExtendedClaims) GetAzp ¶ added in v1.3.4
func (c *ExtendedClaims) GetAzp() string
type JWTConfig ¶ added in v1.3.4
type JWTConfig struct {
Skipper middleware.Skipper
Logger *zerolog.Logger
Keyfunc keyfunc.Keyfunc
NewClaimsFunc func(*echo.Context) jwt.Claims
ContextKey string
TokenLookup string
}
func DefaultJWTConfig ¶ added in v1.3.4
func DefaultJWTConfig() JWTConfig
type RequestIDConfig ¶
type RequestIDConfig struct {
Skipper middleware.Skipper
Generator func() string
AutoGenerate bool
Validator func(string) error
}
func DefaultRequestIDConfig ¶
func DefaultRequestIDConfig() RequestIDConfig
Click to show internal directories.
Click to hide internal directories.