# Echo

> Comprehensive guide for the Echo web framework. Use when building scalable, high-performance web applications and REST APIs in Go with features like flexible routing, middleware support, request/response binding, static file serving, and template rendering. Applies to installing Echo, defining routes, implementing middleware, handling requests/responses, and building web services.

- Skill: `majiayu000/echo-3` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add majiayu000/echo-3`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/echo-3/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/majiayu000/echo-3

---


# Echo Web Framework

Echo is a high-performance, minimalist Go web framework for building robust REST APIs and web applications with simplicity and efficiency.

## Installation

Initialize a Go module and install Echo v4:

```bash
mkdir myapp && cd myapp
go mod init myapp
go get github.com/labstack/echo/v4
```

For Go v1.14 or earlier, enable module mode explicitly:

```bash
GO111MODULE=on go get github.com/labstack/echo/v4
```

## Quick Start

### Hello World Server

```go
package main

import (
	"net/http"
	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}
```

Run with `go run server.go` and visit `http://localhost:1323`.

## Routing

### Basic Routes

Define routes using HTTP methods (GET, POST, PUT, DELETE, PATCH, etc.):

```go
e.POST("/users", saveUser)
e.GET("/users/:id", getUser)
e.PUT("/users/:id", updateUser)
e.DELETE("/users/:id", deleteUser)
```

### Path Parameters

Extract dynamic segments from URL paths:

```go
func getUser(c echo.Context) error {
	id := c.Param("id")
	return c.String(http.StatusOK, id)
}
```

### Query Parameters

Access query string parameters:

```go
func show(c echo.Context) error {
	team := c.QueryParam("team")
	member := c.QueryParam("member")
	return c.String(http.StatusOK, "team:" + team + ", member:" + member)
}
```

## Request Handling

### Bind Request Data

Echo supports automatic binding of JSON, XML, form, and query data into Go structs:

```go
type User struct {
	Name  string `json:"name" xml:"name" form:"name" query:"name"`
	Email string `json:"email" xml:"email" form:"email" query:"email"`
}

e.POST("/users", func(c echo.Context) error {
	u := new(User)
	if err := c.Bind(u); err != nil {
		return err
	}
	return c.JSON(http.StatusCreated, u)
})
```

### Form Data

Handle `application/x-www-form-urlencoded` requests:

```go
func save(c echo.Context) error {
	name := c.FormValue("name")
	email := c.FormValue("email")
	return c.String(http.StatusOK, "name:" + name + ", email:" + email)
}
```

### File Uploads

Handle multipart form data with file uploads:

```go
func save(c echo.Context) error {
	name := c.FormValue("name")
	avatar, err := c.FormFile("avatar")
	if err != nil {
		return err
	}

	src, err := avatar.Open()
	if err != nil {
		return err
	}
	defer src.Close()

	dst, err := os.Create(avatar.Filename)
	if err != nil {
		return err
	}
	defer dst.Close()

	if _, err = io.Copy(dst, src); err != nil {
		return err
	}

	return c.HTML(http.StatusOK, "<b>Thank you! " + name + "</b>")
}
```

## Response Handling

### JSON and XML Responses

Send structured data as JSON or XML:

```go
e.GET("/users", func(c echo.Context) error {
	u := &User{
		Name:  "Jon",
		Email: "[email protected]",
	}
	return c.JSON(http.StatusOK, u)
	// or
	// return c.XML(http.StatusOK, u)
})
```

### Pretty-Printed JSON

Format JSON responses for readability:

```go
return c.JSONPretty(http.StatusOK, u, "  ")
```

## Static Files

### Serve Directory

Map a URL path to a local directory:

```go
e.Static("/static", "assets")
e.Static("/", "public")  // serve from root
```

### Serve Single File

Serve individual files:

```go
e.File("/", "public/index.html")
e.File("/favicon.ico", "images/favicon.ico")
```

### Embedded Filesystem (SPA)

Serve Single Page Application assets from embedded Go filesystem:

```go
//go:embed web
var webAssets embed.FS

func main() {
	e := echo.New()

	e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
		HTML5:      true,
		Root:       "web",
		Filesystem: http.FS(webAssets),
	}))

	api := e.Group("/api")
	api.GET("/users", func(c echo.Context) error {
		return c.String(http.StatusOK, "users")
	})

	if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
		log.Fatal(err)
	}
}
```

## Middleware

Middleware intercepts requests at root, group, or route levels:

### Root-Level Middleware

Applied to all routes:

```go
e.Use(middleware.Logger())
e.Use(middleware.Recover())
```

### Group-Level Middleware

Applied to specific route groups:

```go
g := e.Group("/admin")
g.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
	if username == "joe" && password == "secret" {
		return true, nil
	}
	return false, nil
}))
```

### Route-Level Middleware

Applied to individual routes:

```go
track := func(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		println("request to /users")
		return next(c)
	}
}
e.GET("/users", func(c echo.Context) error {
	return c.String(http.StatusOK, "/users")
}, track)
```

## Server Startup

### HTTP Server

```go
func main() {
	e := echo.New()
	// add middleware and routes...
	if err := e.Start(":8080"); err != http.ErrServerClosed {
		log.Fatal(err)
	}
}
```

### HTTPS/TLS Server

```go
if err := e.StartTLS(":8443", "server.crt", "server.key"); err != http.ErrServerClosed {
	log.Fatal(err)
}
```

### HTTP/2 Server

```go
if err := e.StartTLS(":1323", "cert.pem", "key.pem"); err != http.ErrServerClosed {
	log.Fatal(err)
}
```

### HTTP/2 Cleartext (H2C)

```go
s := &http2.Server{
	MaxConcurrentStreams: 250,
	MaxReadFrameSize:     1048576,
	IdleTimeout:          10 * time.Second,
}
if err := e.StartH2CServer(":8080", s); err != http.ErrServerClosed {
	log.Fatal(err)
}
```

### Custom HTTP Server

For advanced configuration:

```go
s := http.Server{
	Addr:    ":8080",
	Handler: e,
	//ReadTimeout: 30 * time.Second,
}
if err := s.ListenAndServe(); err != http.ErrServerClosed {
	log.Fatal(err)
}
```

## Advanced Features

### Session Management

Use session middleware for maintaining user state:

```go
import "github.com/labstack/echo-contrib/session"
import "github.com/gorilla/sessions"

func main() {
	e := echo.New()
	e.Use(session.Middleware(sessions.NewCookieStore([]byte("secret"))))

	e.GET("/create-session", func(c echo.Context) error {
		sess, _ := session.Get("session", c)
		sess.Values["foo"] = "bar"
		sess.Save(c.Request(), c.Response())
		return c.NoContent(http.StatusOK)
	})

	e.GET("/read-session", func(c echo.Context) error {
		sess, _ := session.Get("session", c)
		return c.String(http.StatusOK, fmt.Sprintf("foo=%v", sess.Values["foo"]))
	})

	e.Start(":8080")
}
```

### Prometheus Metrics

Integrate Prometheus monitoring:

```go
import "github.com/labstack/echo-contrib/echoprometheus"

func main() {
	e := echo.New()
	e.Use(echoprometheus.NewMiddleware("myapp"))
	e.GET("/metrics", echoprometheus.NewHandler())

	e.GET("/hello", func(c echo.Context) error {
		return c.String(http.StatusOK, "hello")
	})

	e.Start(":8080")
}
```

### Request Logger with Zap

Configure structured logging:

```go
import "go.uber.org/zap"

logger, _ := zap.NewProduction()
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
	LogURI:    true,
	LogStatus: true,
	LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
		logger.Info("request",
			zap.String("URI", v.URI),
			zap.Int("status", v.Status),
		)
		return nil
	},
}))
```

### Route Export

Export all registered routes as JSON:

```go
routes := e.Routes()
// Each route contains Method, Path, and Name
```

## Key Echo Methods

**Context Methods**: `c.Param()`, `c.QueryParam()`, `c.FormValue()`, `c.FormFile()`, `c.Bind()`, `c.String()`, `c.JSON()`, `c.XML()`, `c.HTML()`, `c.File()`, `c.Redirect()`, `c.NoContent()`

**Echo Methods**: `e.GET()`, `e.POST()`, `e.PUT()`, `e.DELETE()`, `e.Static()`, `e.File()`, `e.Group()`, `e.Use()`, `e.Start()`, `e.StartTLS()`, `e.Routes()`

## Best Practices

- Use middleware for cross-cutting concerns (logging, auth, CORS)
- Bind request data to typed structs for safety
- Return appropriate HTTP status codes
- Group related routes for shared middleware
- Use `echo.Context` for request/response manipulation
- Handle errors explicitly and return meaningful responses
- Leverage middleware ecosystem for common features (JWT, CORS, compression, etc.)

