HTTP-сервер на net/http: регистрация обработчиков и формирование ответа
Содержание курса
r.Method, r.URL.Path и порядок Header → WriteHeader → Write при формировании ответа
Внутри обработчика r *http.Request содержит всё о входящем запросе. Два самых частых поля:
r.Method— строка с HTTP-методом:"GET","POST","DELETE"и т.д.r.URL.Path— строка с путём запроса, например"/hello".
Пример использования:
func helloHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(http.StatusMethodNotAllowed)
fmt.Fprintln(w, "only GET allowed")
return
}
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Hello from %s\n", r.URL.Path)
}
Порядок вызовов строго обязателен: сначала w.Header().Set(...), затем w.WriteHeader(code), затем запись тела через w.Write(...) или fmt.Fprintf(w, ...).
Почему порядок нельзя нарушать? HTTP-ответ устроен так: сначала идёт статусная строка и заголовки, потом тело. Как только вы начинаете писать тело, заголовки уже уходят клиенту — изменить их невозможно. net/http реализует это жёстко: первый вызов Write или Fprintf автоматически отправляет статус 200 и все текущие заголовки, если WriteHeader ещё не был вызван.
Что будет, если нарушить порядок:
// Неправильно!
func badHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "oops") // ← здесь неявно уходит статус 200
w.WriteHeader(http.StatusTeapot) // ← этот вызов игнорируется, уже поздно
}
Клиент получит статус 200, а в логах Go напишет что-то вроде:
http: superfluous response.WriteHeader call from ...
Это предупреждение в stderr, но ответ уже отправлен с неверным статусом.
Одно исключение: если вы отвечаете с кодом 200 и не устанавливаете специальных заголовков, WriteHeader(200) можно не вызывать — первый Write сделает это сам. Но как только нужен другой статус или любой заголовок — следуйте порядку явно.
