Files
tp/main_dc/yalarba/api_yal/internal/router/router.go
T
valitovgaziz 90a96b4125 Migrate easysite from api_es to api_yal
- Remove api_es service, Dockerfile, all Go source files
- Remove api_es from docker-compose.yml, nginx-ssl.conf, .env, Makefile
- Replace nginx /api/ proxy with /api/v1/ → api_yal:8787
- Add amenity/upload domains, AuthResponse, GET /auth/me, GET /objects/my to api_yal
- Rewrite easysite frontend: types, composables, and all 5 pages to use api_yal DTOs
- Wire nuxt.config public.apiBase, add useObjects CRUD composable
- Update docs references from api_es to api_yal
2026-06-12 10:14:38 +05:00

138 lines
4.8 KiB
Go

package router
import (
"api_yal/internal/config"
"api_yal/internal/domain/account"
"api_yal/internal/domain/amenity"
"api_yal/internal/domain/appeal"
"api_yal/internal/domain/auth"
"api_yal/internal/domain/comment"
"api_yal/internal/domain/feetback"
"api_yal/internal/domain/object"
"api_yal/internal/domain/rating"
"api_yal/internal/domain/upload"
"api_yal/internal/logger"
"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 инициализирует и настраивает основной маршрутизатор приложения
func SetupRouter(db *gorm.DB, config *config.Config) http.Handler {
zapLogger := logger.Get()
zapLogger.Info("Начало настройки маршрутов")
r := chi.NewRouter()
// ВСЕ middleware должны быть определены ДО маршрутов
// 1. Сначала добавляем production middleware
addProductionMiddleware(r, config)
// 2. Затем добавляем middleware аутентификации (он тоже применяется ко всем маршрутам)
zapLogger.Debug("Auth middleware применён")
// 3. И только потом регистрируем маршруты
// Health check (не требует аутентификации, поэтому должен быть выше AuthMiddleware)
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
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 маршрут зарегистрирован")
// Группируем API маршруты под /api/v1
r.Route("/api/v1", func(r chi.Router) {
// Регистрируем маршруты аутентификации
auth.RegisterRoutes(r, db, config.JWTSecret)
// Регистрируем маршруты аккаунтов
account.RegisterRoutes(r, db, config.JWTSecret)
// Регистрируем маршурты обьектов
object.RegisterRoutes(r, db, config.JWTSecret)
// Регистрируем маршруты отзывов
feetback.RegisterRoutes(r, db, config.JWTSecret)
// Регистрация маршрутов для комментариев
comment.RegisterRoutes(r, db, config.JWTSecret)
// Регистрация маршрутов для райтинга
rating.RegisterRoutes(r, db, config.JWTSecret)
// Регистрируем маршруты обращений
appeal.RegisterRoutes(r, db, config.JWTSecret)
// Регистрируем маршруты для удобств
amenity.RegisterRoutes(r, db, config.JWTSecret)
// Регистрируем маршруты для загрузки файлов
upload.RegisterRoutes(r, db, config.JWTSecret, config.UploadPath)
})
zapLogger.Info("Настройка маршрутов завершена")
// Логируем маршруты (опционально)
routeLogger := logger.NewRouteLogger(logger.NewWrapper(zapLogger))
routeLogger.LogRoutes(r)
return r
}
// addProductionMiddleware добавляет все middleware для production
func addProductionMiddleware(r *chi.Mux, config *config.Config) {
// Базовые middleware
r.Use(ChiMiddleware.RequestID)
r.Use(ChiMiddleware.RealIP)
r.Use(ChiMiddleware.Logger)
r.Use(ChiMiddleware.Recoverer)
r.Use(ChiMiddleware.Timeout(30 * time.Second))
r.Use(ChiMiddleware.Compress(5, "gzip"))
r.Use(ChiMiddleware.StripSlashes)
// CORS
r.Use(cors.Handler(cors.Options{
AllowedOrigins: config.CORS.AllowedOrigins,
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"},
AllowCredentials: true,
MaxAge: 300,
}))
// Rate limiting
if config.RateLimit.Enabled {
r.Use(ChiMiddleware.Throttle(config.RateLimit.RequestsPerSecond))
}
// Security headers
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-XSS-Protection", "1; mode=block")
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
if config.Environment == "production" {
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
}
next.ServeHTTP(w, r)
})
})
}