111 lines
3.0 KiB
Go
111 lines
3.0 KiB
Go
package http
|
||
|
||
import (
|
||
"context"
|
||
"database/sql"
|
||
"github.com/99designs/gqlgen/graphql/handler"
|
||
"github.com/99designs/gqlgen/graphql/playground"
|
||
"github.com/go-chi/chi/v5"
|
||
"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/repository"
|
||
"tailly_back_v2/internal/service"
|
||
"tailly_back_v2/internal/ws"
|
||
"tailly_back_v2/pkg/auth"
|
||
)
|
||
|
||
type Server struct {
|
||
router *chi.Mux
|
||
cfg *config.Config
|
||
services *service.Services
|
||
tokenAuth *auth.TokenAuth
|
||
db *sql.DB // Добавляем подключение к БД
|
||
}
|
||
|
||
func NewServer(
|
||
cfg *config.Config,
|
||
services *service.Services,
|
||
tokenAuth *auth.TokenAuth,
|
||
db *sql.DB, // Добавляем параметр БД
|
||
) *Server {
|
||
s := &Server{
|
||
router: chi.NewRouter(),
|
||
cfg: cfg,
|
||
services: services,
|
||
tokenAuth: tokenAuth,
|
||
db: db,
|
||
}
|
||
|
||
s.configureRouter()
|
||
s.configureMetrics()
|
||
|
||
return s
|
||
}
|
||
|
||
func (s *Server) configureRouter() {
|
||
allowedOrigins := []string{
|
||
"http://localhost:3000", // React dev server
|
||
"https://tailly.ru", // Продакшен домен
|
||
}
|
||
// Инициализация WebSocket хаба
|
||
hub := ws.NewHub()
|
||
go hub.Run()
|
||
|
||
// Инициализация сервиса чата
|
||
chatService := service.NewChatService(
|
||
repository.NewChatRepository(s.db),
|
||
repository.NewUserRepository(s.db),
|
||
hub,
|
||
)
|
||
|
||
// Обновляем сервис чата в services
|
||
s.services.Chat = chatService
|
||
|
||
// Добавляем обработчик WebSocket
|
||
|
||
// Логирование
|
||
logger := log.New(os.Stdout, "HTTP: ", log.LstdFlags)
|
||
s.router.Use(middleware.LoggingMiddleware(logger))
|
||
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, s.db) // Теперь передаем оба аргумента
|
||
srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{
|
||
Resolvers: resolver,
|
||
}))
|
||
|
||
// Routes
|
||
s.router.Handle("/", playground.Handler("GraphQL playground", "/query"))
|
||
s.router.Handle("/query", srv)
|
||
s.router.Handle("/uploads/*", http.StripPrefix("/uploads/", http.FileServer(http.Dir("./uploads"))))
|
||
chatHandler := handlers.NewChatHandler(chatService, hub, s.tokenAuth)
|
||
s.router.HandleFunc("/ws", chatHandler.HandleWebSocket)
|
||
}
|
||
|
||
func (s *Server) configureMetrics() {
|
||
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)
|
||
}
|
||
}()
|
||
}
|
||
|
||
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
|
||
}
|