Echo Framework Reference
Echo v4 Go framework: routing, groups, middleware, data binding, validation, error handling, and graceful shutdown.
1. Setup & Routing
package main
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
e.HideBanner = true
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.RequestID())
// Routes
e.GET("/", func(c echo.Context) error {
return c.JSON(http.StatusOK, echo.Map{"message": "hello"})
})
// Route groups
api := e.Group("/api")
api.Use(middleware.JWT([]byte("secret")))
{
api.GET("/articles", listArticles)
api.POST("/articles", createArticle)
api.GET("/articles/:id", getArticle)
api.PUT("/articles/:id", updateArticle)
api.DELETE("/articles/:id", deleteArticle)
}
e.Logger.Fatal(e.Start(":8080"))
}
2. Binding & Validation
import "github.com/go-playground/validator/v10"
type CreateArticleRequest struct {
Title string `json:"title" validate:"required,min=5,max=300"`
Content string `json:"content" validate:"required,min=50"`
Status string `json:"status" validate:"omitempty,oneof=draft published"`
}
// Custom validator
type CustomValidator struct {
validator *validator.Validate
}
func (cv *CustomValidator) Validate(i interface{}) error {
if err := cv.validator.Struct(i); err != nil {
return echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}
return nil
}
// Register
e.Validator = &CustomValidator{validator: validator.New()}
// Handler
func createArticle(c echo.Context) error {
req := new(CreateArticleRequest)
if err := c.Bind(req); err != nil {
return err
}
if err := c.Validate(req); err != nil {
return err
}
// process...
return c.JSON(http.StatusCreated, req)
}
3. Context Methods
func handler(c echo.Context) error {
// Path parameters
id := c.Param("id")
// Query parameters
page := c.QueryParam("page")
page = c.QueryParamWithDefault("page", "1") // Echo v5
// Headers
auth := c.Request().Header.Get("Authorization")
// Set / Get values
c.Set("user", currentUser)
user := c.Get("user").(*User)
// Response helpers
return c.JSON(200, map[string]any{"id": id})
return c.String(200, "hello")
return c.HTML(200, "<h1>Hello</h1>")
return c.Redirect(301, "/new-path")
return c.File("./static/index.html")
return c.Stream(200, "text/event-stream", reader)
return c.Blob(200, "image/png", bytes)
// Error helpers
return echo.NewHTTPError(404, "Not found")
return echo.NewHTTPError(422, map[string]any{"errors": errs})
}
4. Custom Middleware
// Middleware factory
func RateLimiter(rps int) echo.MiddlewareFunc {
limiter := rate.NewLimiter(rate.Limit(rps), rps)
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if !limiter.Allow() {
return echo.NewHTTPError(http.StatusTooManyRequests, "rate limit exceeded")
}
return next(c)
}
}
}
// CORS
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"https://app.example.com"},
AllowMethods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete},
AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentType},
AllowCredentials: true,
}))
// JWT
e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
SigningKey: []byte(os.Getenv("JWT_SECRET")),
ContextKey: "jwt_claims",
TokenLookup: "header:Authorization:Bearer ",
}))
5. Error Handling
// Custom HTTP error handler
e.HTTPErrorHandler = func(err error, c echo.Context) {
var he *echo.HTTPError
if errors.As(err, &he) {
c.JSON(he.Code, echo.Map{
"error": he.Message,
})
return
}
c.Logger().Error(err)
c.JSON(http.StatusInternalServerError, echo.Map{
"error": "Internal server error",
})
}
// Graceful shutdown
go func() {
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
e.Logger.Fatal("shutting down the server")
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := e.Shutdown(ctx); err != nil {
e.Logger.Fatal(err)
}
6. Built-in Middleware Reference
| Middleware | Package | Purpose |
|---|---|---|
| Logger() | middleware | Request logging |
| Recover() | middleware | Panic recovery |
| CORS() | middleware | Cross-origin headers |
| JWT(key) | middleware | JWT authentication |
| BasicAuth(fn) | middleware | HTTP Basic Auth |
| KeyAuth(fn) | middleware | API key auth |
| RateLimiter | middleware | Rate limiting |
| Gzip() | middleware | Gzip compression |
| Secure() | middleware | Security headers |
| RequestID() | middleware | X-Request-ID header |
| BodyLimit(size) | middleware | Limit request size |