import
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user