Функция http.NewRequestWithContext

Функция http.NewRequestWithContext создает новый HTTP-запрос с привязкой к контексту. В первый параметр мы передаем контекст, во второй параметр - HTTP-метод (например, "GET" или "POST"), в третий параметр - URL-адрес в виде строки, а в четвертый - тело запроса (может быть nil). Функция возвращает указатель на структуру http.Request и ошибку, если URL не удалось распарсить.

Синтаксис

gofunc NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error)

Пример 1

Давайте создадим GET-запрос с контекстом и выполним его:

gopackage main

import (
  "context"
  "fmt"
  "io"
  "net/http"
  "time"
)

func main() {
  ctx := context.Background()
  req, err := http.NewRequestWithContext(ctx, "GET", "https://example.com", nil)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  defer resp.Body.Close()

  body, err := io.ReadAll(resp.Body)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Printf("Status: %s\n", resp.Status)
  fmt.Printf("Body length: %d\n", len(body))
}

Результат выполнения кода:

go"Status: 200 OK"
"Body length: 1256"

Пример 2

Давайте создадим запрос с контекстом, который автоматически отменится через 1 секунду:

gopackage main

import (
  "context"
  "fmt"
  "net/http"
  "time"
)

func main() {
  ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
  defer cancel()

  req, err := http.NewRequestWithContext(ctx, "GET", "https://example.com", nil)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  client := &http.Client{}
  _, err = client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Println("Request completed successfully")
}

Результат выполнения кода:

go"Error: Get https://example.com: context deadline exceeded"

Пример 3

Давайте создадим POST-запрос с телом и контекстом:

gopackage main

import (
  "bytes"
  "context"
  "fmt"
  "io"
  "net/http"
)

func main() {
  jsonBody := []byte(`{"key": "value"}`)
  body := bytes.NewReader(jsonBody)

  ctx := context.Background()
  req, err := http.NewRequestWithContext(ctx, "POST", "https://httpbin.org/post", body)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  req.Header.Set("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  defer resp.Body.Close()

  resBody, err := io.ReadAll(resp.Body)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Println("Status:", resp.Status)
  fmt.Println("Response body length:", len(resBody))
}

Результат выполнения кода:

go"Status: 200 OK"
"Response body length: 456"

Смотрите также

  • функцию http.NewRequest,
    которая создает HTTP-запрос без контекста
  • метод Request.WithContext,
    который создает копию запроса с новым контекстом
  • метод Request.Context,
    который возвращает контекст запроса
  • функцию Client.Do,
    которая выполняет HTTP-запрос