package http import ( "context" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/playground" "github.com/go-chi/chi/v5" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "log" "net/http" "os" "tailly_back_v2/internal/config" "tailly_back_v2/internal/http/graph" "tailly_back_v2/internal/http/handlers" "tailly_back_v2/internal/http/middleware" "tailly_back_v2/internal/service" "tailly_back_v2/pkg/auth" ) type Server struct { router *chi.Mux cfg *config.Config services *service.Services tokenAuth *auth.TokenAuth } func NewServer(cfg *config.Config, services *service.Services, tokenAuth *auth.TokenAuth) *Server { s := &Server{ router: chi.NewRouter(), cfg: cfg, services: services, tokenAuth: tokenAuth, } s.configureRouter() return s } func (s *Server) configureRouter() { allowedOrigins := []string{ "http://localhost:3000", // React dev server "https://your-production.app", // Продакшен домен } // Логирование logger := log.New(os.Stdout, "HTTP: ", log.LstdFlags) s.router.Use(middleware.LoggingMiddleware(logger)) // Регистрация middleware s.router.Use(middleware.AuditMiddleware(auditService, "http_request")) // Регистрация обработчиков handler.RegisterRecoveryHandlers(router, recoveryService) handler.RegisterAuditHandlers(router, auditService, authMiddleware) // Метрики s.router.Use(middleware.MetricsMiddleware) s.router.Use(middleware.CORS(allowedOrigins)) s.router.Use(middleware.AuthMiddleware(s.tokenAuth)) // GraphQL handler resolver := graph.NewResolver(s.services) srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{ Resolvers: resolver, })) // Routes s.router.Handle("/", playground.Handler("GraphQL playground", "/query")) s.router.Handle("/query", srv) } func (s *Server) Run() error { return http.ListenAndServe(s.cfg.Server.Host+":"+s.cfg.Server.Port, s.router) } func (s *Server) Shutdown(ctx context.Context) error { // Здесь можно добавить логику graceful shutdown return nil } func (s *Server) configureMetrics() { prometheus.MustRegister( middleware.httpRequestsTotal, middleware.httpRequestDuration, middleware.httpResponseSize, ) metricsRouter := chi.NewRouter() metricsRouter.Get("/metrics", promhttp.Handler().ServeHTTP) go func() { if err := http.ListenAndServe(":9100", metricsRouter); err != nil { log.Printf("Metrics server error: %v", err) } }() }