// Package server собирает HTTP-роутер сервиса api из модулей. package server import ( "log/slog" "net/http" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "pipu/api/internal/api/gen" "pipu/api/internal/auth" "pipu/api/internal/library" "pipu/api/internal/platform/httpx" "pipu/api/internal/system" ) // Deps — модули, реализующие части контракта API. type Deps struct { Log *slog.Logger System *system.Handler Auth *auth.Handler // Library — хранилища, сканы и каталог. Library *library.Handler // AuthService проверяет access-токены в middleware. nil — только для тестов служебных эндпоинтов. AuthService *auth.Service } // handlers объединяет модули в единую реализацию gen.StrictServerInterface. // По мере появления модулей (catalog, ...) они встраиваются сюда. // Алиасы дают встроенным полям разные имена: у модулей одинаковое имя типа Handler. type ( systemHandler = system.Handler authHandler = auth.Handler libraryHandler = library.Handler ) type handlers struct { *systemHandler *authHandler *libraryHandler } var _ gen.StrictServerInterface = handlers{} // NewRouter возвращает корневой http.Handler. func NewRouter(d Deps) http.Handler { log := d.Log if log == nil { log = slog.New(slog.DiscardHandler) } r := chi.NewRouter() r.Use(middleware.RequestID, httpx.RealIP, httpx.AccessLog(log), middleware.Recoverer) if d.AuthService != nil { r.Use(auth.Middleware(d.AuthService, log)) } r.NotFound(httpx.NotFound) r.MethodNotAllowed(httpx.MethodNotAllowed) strict := gen.NewStrictHandlerWithOptions(handlers{systemHandler: d.System, authHandler: d.Auth, libraryHandler: d.Library}, nil, gen.StrictHTTPServerOptions{ RequestErrorHandlerFunc: httpx.RequestError, ResponseErrorHandlerFunc: httpx.ResponseError(log), }) return gen.HandlerWithOptions(strict, gen.ChiServerOptions{ BaseRouter: r, // Ошибки разбора path- и query-параметров — тоже problem+json, а не текст по умолчанию. ErrorHandlerFunc: httpx.RequestError, }) }