Files
tp/main_dc/yalarba/api_yal/internal/router/router.go
T
2026-03-09 02:36:21 +05:00

175 lines
9.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package router
import (
"api_yal/internal/config"
"api_yal/internal/logger"
CastomMiddleware "api_yal/internal/middleware"
"time"
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
ChiMiddleware "github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"go.uber.org/zap"
"gorm.io/gorm"
)
// SetupRouter инициализирует и настраивает основной маршрутизатор приложения
// Параметры:
// - db: подключение к базе данных GORM
// - config: конфигурация приложения
//
// Возвращает:
// - http.Handler: настроенный маршрутизатор с применёнными middleware и маршрутами
func SetupRouter(db *gorm.DB, config *config.Config) http.Handler {
// Получаем экземпляр логгера для записи событий
zapLogger := logger.Get()
zapLogger.Info("Начало настройки маршрутов")
// Создаём новый экземпляр маршрутизатора chi
r := chi.NewRouter()
// Добавляем все production middleware для обработки входящих запросов
addProductionMiddleware(r, config)
zapLogger.Debug("Production middleware успешно добавлены")
// Эндпоинт для проверки работоспособности сервиса (health check)
// Используется мониторингом и системами оркестрации для проверки статуса приложения
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
// Формируем и отправляем JSON-ответ со статусом healthy
if err := json.NewEncoder(w).Encode(map[string]string{"status": "healthy"}); err != nil {
// Логируем ошибку при невозможности отправить ответ
zapLogger.Error("Ошибка при отправке health check ответа",
zap.String("path", r.URL.Path),
zap.Error(err),
)
}
})
zapLogger.Debug("Health check маршрут зарегистрирован")
// Добавляем middleware для аутентификации ко всем последующим маршрутам
// Все маршруты после этого middleware будут требовать валидный контекст аутентификации
r.Use(CastomMiddleware.AuthMiddlewareWithContext)
zapLogger.Debug("Auth middleware применён ко всем маршрутам")
// TODO: Здесь можно добавить регистрацию дополнительных маршрутов
// Например: r.Mount("/api/v1", apiRoutes(db, config))
zapLogger.Info("Настройка маршрутов завершена успешно")
// Логируем все зарегистрированные маршруты для отладки и мониторинга
routeLogger := logger.NewRouteLogger(logger.NewWrapper(zapLogger))
routeLogger.LogRoutes(r)
zapLogger.Debug("Все маршруты залогированы")
return r
}
// addProductionMiddleware добавляет все необходимые middleware для production окружения
// Функция применяет стандартный набор middleware для обработки запросов:
// - Идентификация запросов
// - Логирование
// - Безопасность
// - Сжатие ответов
// - CORS настройки
//
// Параметры:
// - r: экземпляр маршрутизатора chi
// - config: конфигурация приложения для настройки middleware под окружение
func addProductionMiddleware(r *chi.Mux, config *config.Config) {
// Request ID middleware - добавляет уникальный ID к каждому запросу
// Позволяет отслеживать запрос на протяжении всего жизненного цикла
r.Use(ChiMiddleware.RequestID)
// Real IP middleware - корректно определяет реальный IP клиента (за прокси)
// Важно для правильного логирования и rate limiting'а
r.Use(ChiMiddleware.RealIP)
// Logger middleware - логирует все запросы в формате Apache
// Предоставляет базовую информацию о входящих запросах
r.Use(ChiMiddleware.Logger)
// Recoverer middleware - восстанавливает после паники и возвращает 500
// Предотвращает падение всего приложения из-за паники в обработчиках
r.Use(ChiMiddleware.Recoverer)
// Timeout middleware - устанавливает таймаут на запросы (30 секунд)
// Защищает от "висящих" запросов, которые могут занять слишком много времени
r.Use(ChiMiddleware.Timeout(30 * time.Second))
// Compress middleware - сжимает ответы (gzip)
// Уменьшает размер передаваемых данных, улучшает производительность
// Уровень сжатия 5 (среднее между скоростью и степенью сжатия)
r.Use(ChiMiddleware.Compress(5, "gzip"))
// StripSlashes middleware - удаляет слеши в конце URL или редиректит
// Нормализует URL'ы для единообразия маршрутизации
r.Use(ChiMiddleware.StripSlashes)
// CORS middleware - настройка CORS для production
// Позволяет контролировать доступ к API из браузерных приложений
r.Use(cors.Handler(cors.Options{
// Разрешённые источники (origins) из конфигурации
AllowedOrigins: config.CORS.AllowedOrigins,
// Разрешённые HTTP методы
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"},
// Разрешённые заголовки запросов
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token", "X-Request-ID"},
// Заголовки, доступные клиенту при чтении ответа
ExposedHeaders: []string{"Link", "X-Request-ID"},
// Разрешить передачу cookies и HTTP-аутентификацию
AllowCredentials: true,
// Время кэширования preflight запросов (в секундах)
MaxAge: 300,
}))
// Content-Type middleware - проверяет Content-Type для POST/PUT запросов
// Гарантирует, что клиенты отправляют данные в ожидаемом формате
r.Use(ChiMiddleware.AllowContentType("application/json", "application/xml"))
// Дополнительные middleware в зависимости от конфигурации
if config.Environment == "development" {
// Добавляем дополнительное логирование для разработки
// В dev-режиме полезно иметь более подробную информацию о запросах
r.Use(ChiMiddleware.Logger)
}
if config.RateLimit.Enabled {
// Добавляем rate limiting если включено в конфиге
// Защищает от DDoS атак и чрезмерного использования ресурсов
r.Use(ChiMiddleware.Throttle(config.RateLimit.RequestsPerSecond))
}
// Security headers middleware - добавляет заголовки безопасности к каждому ответу
// Защищает от распространённых веб-уязвимостей
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Защита от MIME-снiffing атак
w.Header().Set("X-Content-Type-Options", "nosniff")
// Защита от clickjacking атак
w.Header().Set("X-Frame-Options", "DENY")
// Включает защиту от XSS в браузерах
w.Header().Set("X-XSS-Protection", "1; mode=block")
// Контролирует, сколько информации о реферере передаётся при переходах
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
// Для production окружения включаем HSTS (HTTP Strict Transport Security)
// Заставляет браузер использовать только HTTPS соединения
if config.Environment == "production" {
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
}
// Передаём управление следующему middleware или обработчику
next.ServeHTTP(w, r)
})
})
}