This commit is contained in:
Alex Shevchuk
2025-08-18 17:12:04 +03:00
commit d84487d238
157 changed files with 160686 additions and 0 deletions

182
internal/http/client.go Normal file
View File

@@ -0,0 +1,182 @@
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)
}
}