1. Основы HTTP в Go: net/http, Handler и Server
Основы HTTP в Go: net/http, Handler и Server
В этом курсе мы будем разрабатывать REST API на Go, используя стандартный пакет net/http и роутер chi. Эта статья — фундамент: вы разберётесь, как Go принимает HTTP-запрос, как устроены обработчики (handlers), и как правильно запускать HTTP-сервер.
Полезные источники для справки:
Что такое HTTP-запрос и HTTP-ответ
HTTP — протокол запрос-ответ. Клиент (например, браузер или мобильное приложение) отправляет запрос, сервер возвращает ответ.
Запрос обычно состоит из:
GET, POST, PUT, DELETE)/users/42)Content-TypePOST/PUT (например, JSON)Ответ обычно состоит из:
200, 404, 500)В REST API мы чаще всего:
Как net/http обрабатывает запрос
Пакет net/http строится вокруг идеи: на каждый запрос вызывается обработчик.
!Схема жизненного цикла запроса: от клиента до handler и обратно
Ключевые роли:
http.Server: принимает соединения, читает запросы, управляет таймаутами.Handler: ваш код, который формирует ответ.Mux (маршрутизатор): выбирает, какой обработчик вызвать по пути и методу.Интерфейс http.Handler и функция http.HandlerFunc
В Go обработчик — это объект, который реализует интерфейс http.Handler:
Здесь:
http.ResponseWriter — то, во что вы пишете ответ (статус, заголовки, тело)*http.Request — входящий запрос (метод, путь, заголовки, тело, контекст)Чаще всего удобнее использовать http.HandlerFunc — это адаптер, позволяющий писать обработчик обычной функцией:
Обратите внимание:
http.HandleFunc регистрирует путь и функциюhttp.ListenAndServe запускает серверnil означает: использовать стандартный DefaultServeMuxДокументация по обработчикам:
ResponseWriter: статус, заголовки, тело
http.ResponseWriter позволяет управлять ответом.
Статус-код
Write, статус станет 200 OK.WriteHeader до Write.Заголовки
Заголовки задаются через Header():
Важно: заголовки нужно выставить до WriteHeader и до записи тела, иначе они могут не примениться.
Тело ответа
Запись тела — через Write:
Request: метод, путь, query, тело
*http.Request содержит данные запроса.
Метод и путь
Query-параметры
Для URL /search?q=go&page=2:
Тело запроса
Тело доступно как поток r.Body. Его нужно читать (и обычно закрывать) аккуратно. В следующих статьях мы будем разбирать JSON, а пока важный принцип: тело может быть большим, поэтому чтение должно быть контролируемым.
Маршрутизация: ServeMux как базовый роутер
В net/http есть простой роутер — http.ServeMux. Он сопоставляет путь с обработчиком.
Пример с несколькими маршрутами:
Ограничения ServeMux (почему позже нужен chi):
GET /users, POST /users)/users/{id}chi решает эти задачи, но понимание Handler и Server остаётся основой.
http.Server: зачем он нужен поверх ListenAndServe
http.ListenAndServe(":8080", handler) — это удобный шорткат. Под капотом он создаёт http.Server.
Явный http.Server нужен, чтобы управлять:
Рекомендуемые таймауты
Пример безопасной конфигурации для API:
Смысл таймаутов:
ReadHeaderTimeout: ограничивает время на чтение заголовковReadTimeout: ограничивает время на чтение всего запросаWriteTimeout: ограничивает время на запись ответаIdleTimeout: сколько держать keep-alive соединение без активностиДокументация:
Частые ошибки новичков
w.Write до установки нужных заголовков и статус-кода.r.Method в обработчиках при использовании ServeMux.Как это связано с REST API и следующими темами
Дальше в курсе мы будем строить REST API поверх этих базовых примитивов:
chi для маршрутизации по методам и параметрам путиФундамент остаётся тем же: сервер вызывает handler, handler читает *http.Request и пишет в http.ResponseWriter.