EchoMiddleCoding
Как определить и зарегистрировать middleware в Echo?
Middleware в Echo — функция (echo.HandlerFunc) echo.HandlerFunc; регистрируется глобально через e.Use(), на группу через group.Use() или на конкретный маршрут третьим аргументом.
Middleware в Echo: определение и регистрация
Middleware в Echo — это функция с сигнатурой func(echo.HandlerFunc) echo.HandlerFunc. Она получает следующий хендлер в цепочке и возвращает новый хендлер, оборачивающий его логикой до/после.
Написание своего middleware
package middleware
import (
"time"
"github.com/labstack/echo/v4"
)
// RequestTimer измеряет время выполнения запроса
func RequestTimer() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
start := time.Now()
// Логика "до"
err := next(c) // вызов следующего хендлера
// Логика "после"
c.Logger().Infof("%s %s — %v",
c.Request().Method,
c.Request().URL.Path,
time.Since(start),
)
return err
}
}
}
Уровни регистрации
1. Глобальный middleware — e.Use()
e := echo.New()
// Применяется ко ВСЕМ маршрутам
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.CORS())
e.Use(RequestTimer())
2. Middleware на группе маршрутов
// Только для /api/* маршрутов
api := e.Group("/api")
api.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
return key == os.Getenv("API_KEY"), nil
}))
api.GET("/users", listUsers)
api.POST("/users", createUser)
// Вложенная группа с дополнительным middleware
admin := api.Group("/admin")
admin.Use(requireAdminRole)
admin.DELETE("/users/:id", deleteUser)
3. Middleware на конкретном маршруте
// Middleware передаётся после хендлера как дополнительные аргументы
e.GET("/secret", secretHandler,
middleware.BasicAuth(func(user, pass string, c echo.Context) (bool, error) {
return user == "admin" && pass == "pass", nil
}),
)
Встроенные middleware из echo/middleware
middleware.Logger()— структурированный лог запросов.middleware.Recover()— перехват паник, возврат 500.middleware.CORS()— заголовки CORS с конфигомmiddleware.CORSConfig.middleware.JWT(secret)— проверка Bearer-токена, claims вc.Get("user").middleware.RateLimiter()— ограничение RPS через in-memory store.middleware.Gzip()— сжатие ответов.middleware.RequestID()— генерация X-Request-ID.middleware.BodyLimit("2M")— ограничение размера тела.
Middleware с конфигурацией
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"https://talento.work", "https://app.talento.work"},
AllowMethods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete},
AllowHeaders: []string{echo.HeaderContentType, echo.HeaderAuthorization},
AllowCredentials: true,
}))
Передача данных между middleware и хендлером
// Middleware записывает данные
func SetUserID() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Set("userID", "123") // ключ-значение в контексте
return next(c)
}
}
}
// Хендлер читает данные
func handler(c echo.Context) error {
userID := c.Get("userID").(string)
return c.JSON(http.StatusOK, map[string]string{"user": userID})
}
Подводные камни
- Порядок регистрации = порядок выполнения: первый
e.Use()— самый внешний. Logger должен идти до Recover, чтобы логировать даже паникующие запросы. - Middleware на группе не наследуется: middleware добавленный к
e.Group("/api")не действует на маршруты, зарегистрированные прямо наe. - Middleware до регистрации маршрутов:
e.Use()должен вызываться доe.GET/POST— иначе существующие маршруты не увидят middleware в некоторых сценариях. - c.Set() не потокобезопасен: запись и чтение из горутин без синхронизации вызывает гонку данных.
- Middleware пропускает ошибку: если middleware не вызывает
next(c), хендлер не выполняется — легко случайно заблокировать все запросы. - RateLimiter in-memory: встроенный RateLimiter не работает в multi-instance деплое — нужен Redis-бэкенд или внешний rate limiter.
- CORS и Preflight: CORSWithConfig должен быть зарегистрирован до аутентификационного middleware, иначе OPTIONS-запросы будут отклоняться до проверки CORS-заголовков.
- Паника в middleware: если Recover не первый в цепочке, паника в предшествующем middleware не будет перехвачена.
Common mistakes
- Давать ответ про регистрация middleware в Echo только на уровне определения, не показывая поведение в реальном приложении.
- Игнорировать границы ответственности вокруг темы «регистрация middleware в Echo»: кто отменяет работу, кто владеет ресурсом и где формируется ответ клиенту.
- Не связывать регистрация middleware в Echo с observability, тестированием или безопасностью, когда это влияет на продакшен-поведение.
What the interviewer is testing
- Точно объясняет, что именно делает регистрация middleware в Echo и где это используется в Go-коде.
- Связывает регистрация middleware в Echo с корректным lifecycle запроса, отменой, конкурентностью или конфигурацией сервера там, где это уместно.
- Не изобретает API и опирается на реальные контракты официальной документации.