Files

106 lines
3.9 KiB
Go
Raw Permalink Normal View History

2026-04-13 08:10:14 +03:00
package api
import (
"fmt"
"log/slog"
"net/http"
"time"
)
// UserService — интерфейс сервиса пользователей для хендлера.
type UserService interface {
GetProfile(token string) string
}
// AuthService — интерфейс сервиса авторизации для хендлера.
type AuthService interface {
// методы, которые хендлер использует из сервиса авторизации
}
// NotificationService — интерфейс сервиса уведомлений для хендлера.
type NotificationService interface {
// методы, которые хендлер использует из сервиса уведомлений
}
// Handler — интерфейс обработчика HTTP-запросов.
type Handler interface {
Routes() http.Handler
}
// handler — конкретная реализация, скрыта от внешних пакетов.
// Содержит только хендлеры и роутинг.
// Ничего не знает про http.Server, порт или lifecycle —
// это ответственность app-слоя.
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("GET /health", h.healthHandler)
mux.HandleFunc("GET /users/me", h.getUserProfile)
// /slow — эндпоинт для демонстрации graceful shutdown.
// Имитирует долгий запрос: обращение к БД, вызов внешнего API и т.д.
// Пять секунд — чтобы мы успели нажать Ctrl+C, пока запрос выполняется.
mux.HandleFunc("GET /slow", h.slowHandler)
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)
}
}
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)
}
}
// slowHandler — медленный эндпоинт для демонстрации graceful shutdown.
// Имитирует реальную работу: запрос в базу, вызов внешнего сервиса.
//
// Попробуйте:
// 1. curl localhost:8080/slow
// 2. Пока запрос висит — нажмите Ctrl+C в терминале сервера
// 3. Без graceful shutdown: curl получит "connection reset by peer"
// 4. С graceful shutdown: curl дождётся и получит "готово!" — 200 OK
func (h *handler) slowHandler(w http.ResponseWriter, _ *http.Request) {
slog.Info("обрабатываю медленный запрос...")
time.Sleep(5 * time.Second) // имитация: запрос в БД, внешний API
w.WriteHeader(http.StatusOK)
if _, err := fmt.Fprintln(w, "готово!"); err != nil {
slog.Error("ошибка записи ответа", "err", err)
}
}