package http_router import ( "errors" "log/slog" "net/http" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/cache" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database" dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/feed" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/integration" objectStorage "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/object_storage" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/agent" authinfra "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/auth_infrastructure" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/distributor" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth/keycloak" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/config" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants" filemanager "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/file_manager" urlShortener "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/url_shortener" ) type handler struct { env string logger *slog.Logger urlShortener urlShortener.Shortener authManager auth.Manager authInfraService authinfra.AuthInfrastructureService fileManager filemanager.UserFileManager dbClient database.Client agentService agent.AgentService distributorService distributor.DistributorService cacheClient cache.Client objectStorageClient objectStorage.Client jwtManager keycloak.TokenManager tempFileManager *TempFileManager emailVerificationServiceAPIKey string feed *feed.Handler integrationClient integration.Client buildConfig config.BuildInfo } type Config struct { env string logger *slog.Logger secretConfig *config.SecretConfig authManager auth.Manager authInfraService authinfra.AuthInfrastructureService fileManager filemanager.UserFileManager dbClient database.Client agentService agent.AgentService distributorService distributor.DistributorService emailVerificationServiceAPIKey string cacheClient cache.Client objectStorageClient objectStorage.Client feed *feed.Handler integrationClient integration.Client buildConfig config.BuildInfo } func newHandler(c *Config) *handler { tempManager, err := NewTempFileManager("") if err != nil { c.logger.Error("failed to create temp file manager", slog.String("error", err.Error())) return nil } return &handler{ env: c.env, logger: c.logger, urlShortener: &urlShortener.LinkEncryption{Key: c.secretConfig.Key}, authManager: c.authManager, authInfraService: c.authInfraService, fileManager: c.fileManager, dbClient: c.dbClient, agentService: c.agentService, distributorService: c.distributorService, emailVerificationServiceAPIKey: c.emailVerificationServiceAPIKey, cacheClient: c.cacheClient, objectStorageClient: c.objectStorageClient, jwtManager: keycloak.NewJWTManager(), tempFileManager: tempManager, feed: c.feed, integrationClient: c.integrationClient, buildConfig: c.buildConfig, } } func (h *handler) handleKeycloakError(w http.ResponseWriter, err error) { switch { case errors.Is(err, keycloak.ErrUnknownUserType): http.Error(w, keycloak.ErrUnknownUserType.Error(), http.StatusBadRequest) case errors.Is(err, keycloak.ErrInvalidToken): http.Error(w, keycloak.ErrInvalidToken.Error(), http.StatusUnauthorized) case errors.Is(err, keycloak.ErrRealmClientUnauthorized): http.Error(w, "internal server error", http.StatusInternalServerError) case errors.Is(err, keycloak.ErrRealmClientNotFound): http.Error(w, "internal server error", http.StatusInternalServerError) case errors.Is(err, keycloak.ErrInternal): http.Error(w, keycloak.ErrInternal.Error(), http.StatusInternalServerError) case errors.Is(err, keycloak.ErrAlreadyExists): http.Error(w, keycloak.ErrAlreadyExists.Error(), http.StatusBadRequest) case errors.Is(err, keycloak.ErrBadRequest): http.Error(w, keycloak.ErrBadRequest.Error(), http.StatusBadRequest) case errors.Is(err, keycloak.ErrNotFound): http.Error(w, keycloak.ErrNotFound.Error(), http.StatusNotFound) default: h.logger.Error("Unhandled keycloak error", slog.String("error", err.Error())) http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) } } func (h *handler) handleAuthInfraError(w http.ResponseWriter, err error, handlerName string) { switch { case errors.Is(err, authinfra.ErrBadRequest): http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest) case errors.Is(err, authinfra.ErrUnauthorized): http.Error(w, constants.ErrUnauthorized.Error(), http.StatusUnauthorized) case errors.Is(err, authinfra.ErrNotFound): http.Error(w, constants.ErrUnauthorized.Error(), http.StatusUnauthorized) case errors.Is(err, authinfra.ErrInternal): http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) h.logger.Error("auth infrastructure error", slog.String("error", err.Error()), slog.String("handler", handlerName)) default: h.logger.Error("Unhandled auth infrastructure error", slog.String("error", err.Error())) http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) } } func (h *handler) handleDBError(w http.ResponseWriter, err error) { switch { case errors.Is(err, dberrors.ErrBadRequest): http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest) case errors.Is(err, dberrors.ErrForbidden): http.Error(w, constants.ErrForbidden.Error(), http.StatusForbidden) case errors.Is(err, dberrors.ErrNotFound): http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound) case errors.Is(err, dberrors.ErrInternal): http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) default: h.logger.Error("Unhandled database error", slog.String("error", err.Error())) http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) } } func (h *handler) handleAgentError(w http.ResponseWriter, err error) { switch { case errors.Is(err, agent.ErrBadRequest): http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest) case errors.Is(err, agent.ErrForbidden): http.Error(w, constants.ErrForbidden.Error(), http.StatusForbidden) case errors.Is(err, agent.ErrNotFound): http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound) case errors.Is(err, agent.ErrInternal): http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) default: h.logger.Error("Unhandled agent error", slog.String("error", err.Error())) http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) } } func (h *handler) handleDistributorError(w http.ResponseWriter, err error) { switch { case errors.Is(err, distributor.ErrBadRequest): http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest) case errors.Is(err, distributor.ErrForbidden): http.Error(w, constants.ErrForbidden.Error(), http.StatusForbidden) case errors.Is(err, distributor.ErrNotFound): http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound) case errors.Is(err, distributor.ErrInternal): http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) default: h.logger.Error("Unhandled distributor error", slog.String("error", err.Error())) http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) } }