Срок HTTP-запроса в Go
Долгое ожидание ответа лучше ограничивать сроком. Контекст из прошлого раздела для этого подходит: команда создания запроса с контекстом кладет ссылку на него в объект запроса, и клиент прекращает работу, когда контекст отменен.
Срок задают через контекст с таймером от
корня или от родителя. Функцию отмены вешают
на defer, как и для других дочерних
контекстов, даже если запрос уже завершился
раньше таймера.
Поставим короткий срок на запрос к учебному хосту:
package main
import (
"context"
"fmt"
"io"
"log"
"net/http"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(
context.Background(),
5*time.Second,
)
defer cancel()
req, err := http.NewRequestWithContext(
ctx,
"GET",
"https://example.com",
nil,
)
if err != nil {
log.Fatal(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.StatusCode, len(body))
}
При нормальной сети ответ успеет прийти за
пять секунд. Если срок короче задержки,
Do вернет ошибку, связанную с
отменой контекста, а не код состояния.
Тот же прием для локального адреса:
package main
import (
"context"
"log"
"net/http"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(
context.Background(),
100*time.Millisecond,
)
defer cancel()
req, err := http.NewRequestWithContext(
ctx,
"GET",
"http://127.0.0.1:8080/slow",
nil,
)
if err != nil {
log.Fatal(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Println("stopped:", err)
return
}
defer resp.Body.Close()
}
Дан адрес "https://example.com":
addr := "https://example.com"
Постройте контекст со сроком две секунды, создайте запрос с этим контекстом, отправьте его и выведите код состояния при успехе.
Дан следующий код:
ctx, cancel := context.WithTimeout(
context.Background(),
time.Second,
)
req, err := http.NewRequestWithContext(
ctx, "GET", addr, nil,
)
Допишите отложенный вызов cancel
и скажите, что произойдет, если его забыть.
Скажите, где появится ошибка срока: при создании запроса или при выполнении клиентом, если сервер отвечает дольше таймера.