package api import ( "fmt" "log/slog" "net/http" ) // UserService — интерфейс сервиса пользователей для хендлера. type UserService interface { GetProfile(token string) string } // AuthService — интерфейс сервиса авторизации для хендлера. type AuthService interface { // методы, которые хендлер использует из сервиса авторизации } // NotificationService — интерфейс сервиса уведомлений для хендлера. type NotificationService interface { // методы, которые хендлер использует из сервиса уведомлений } // Handler — интерфейс HTTP-обработчика. // Содержит только хендлеры и роутинг. // Ничего не знает про http.Server, порт или lifecycle — // это ответственность app-слоя. // Структура неэкспортируемая — создать объект можно только через NewHandler. type Handler interface { Routes() http.Handler } // handler — обработчик HTTP-запросов. type handler struct { userService UserService authService AuthService notificationService NotificationService } // NewHandler создаёт обработчик HTTP-запросов. func NewHandler( userService UserService, authService AuthService, notificationService NotificationService, ) Handler { return &handler{ userService: userService, authService: authService, notificationService: notificationService, } } // Routes возвращает маршрутизатор со всеми зарегистрированными хендлерами. // App-слой использует этот http.Handler при создании http.Server. func (h *handler) Routes() http.Handler { mux := http.NewServeMux() mux.HandleFunc("/health", h.healthHandler) mux.HandleFunc("/users/me", h.getUserProfile) return mux } func (h *handler) healthHandler(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) if _, err := fmt.Fprintln(w, "ok"); err != nil { slog.Error("ошибка записи ответа", "err", err) } } // getUserProfile — хендлер профиля пользователя. // Вызывает userService.GetProfile(), который внутри дёрнет authService.ValidateToken(). // Если authService == nil (как в antipattern-broken) — тут будет nil pointer dereference. func (h *handler) getUserProfile(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") profile := h.userService.GetProfile(token) w.WriteHeader(http.StatusOK) if _, err := fmt.Fprintln(w, profile); err != nil { slog.Error("ошибка записи ответа", "err", err) } }