Функция http.TimeoutHandler
Функция http.TimeoutHandler оборачивает переданный HTTP-обработчик и возвращает новый обработчик, который автоматически прерывает выполнение запроса, если оно превышает указанный таймаут. В первый параметр мы передаем исходный обработчик (http.Handler), во второй параметр мы передаем длительность таймаута (time.Duration), а в третий параметр мы передаем строку сообщения, которое будет отправлено клиенту при превышении времени выполнения.
Синтаксис
http.TimeoutHandler(handler http.Handler, timeout time.Duration, message string) http.Handler
Пример
Давайте создадим обработчик, который искусственно задерживает выполнение запроса, и обернем его в http.TimeoutHandler с таймаутом 1 секунду:
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
slowHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second)
fmt.Fprintln(w, "Request completed")
})
timeoutHandler := http.TimeoutHandler(slowHandler, 1*time.Second, "Request timeout")
http.Handle("/slow", timeoutHandler)
http.ListenAndServe(":8080", nil)
}
Если обратиться к эндпоинту /slow, то через 1 секунду клиент получит ответ с сообщением "Request timeout".
Пример
Давайте рассмотрим пример, где обработчик успевает завершиться до истечения таймаута:
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
fastHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(500 * time.Millisecond)
fmt.Fprintln(w, "Request completed successfully")
})
timeoutHandler := http.TimeoutHandler(fastHandler, 1*time.Second, "Request timeout")
http.Handle("/fast", timeoutHandler)
http.ListenAndServe(":8080", nil)
}
Результат выполнения кода при обращении к эндпоинту /fast:
"Request completed successfully"
Пример
Давайте создадим обработчик, который читает тело запроса и возвращает ответ, используя http.TimeoutHandler для защиты от долгих операций:
package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
processHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read body", http.StatusBadRequest)
return
}
defer r.Body.Close()
time.Sleep(2 * time.Second)
fmt.Fprintf(w, "Processed: %s", string(body))
})
timeoutHandler := http.TimeoutHandler(processHandler, 500*time.Millisecond, "Processing timeout")
http.Handle("/process", timeoutHandler)
http.ListenAndServe(":8080", nil)
}
При обращении к эндпоинту /process с таймаутом 500 миллисекунд обработчик не успеет выполнить операцию и вернет сообщение "Processing timeout".
Смотрите также
-
функцию
http.Server,
которая предоставляет структуру для настройки HTTP-сервера с поддержкой таймаутов -
метод
http.Server.ListenAndServe,
который запускает HTTP-сервер с указанными настройками -
функцию
http.NewRequestWithContext,
которая создает HTTP-запрос с контекстом для управления таймаутами -
константу
http.ErrHandlerTimeout,
которая представляет ошибку превышения времени обработки