Отправка тела запроса в Go
Метод с телом передает байты вместе с адресом.
Для коротких учебных примеров подойдет команда
отправки из пакета net/http: ей передают
адрес, тип содержимого и поток байтов через
bytes.NewReader.
Тот же результат дает создание запроса с методом
отправки и телом в виде io.Reader,
заголовок типа содержимого ставят вручную,
затем вызывают выполнение у клиента. Оба
пути проверяют ошибку и закрывают тело ответа
отложенно.
Отправим JSON на локальный сервис короткой командой:
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
)
func main() {
payload := []byte(`{"name":"ann"}`)
resp, err := http.Post(
"http://127.0.0.1:8080/users",
"application/json",
bytes.NewReader(payload),
)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
fmt.Println(resp.StatusCode)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
Тип "application/json" попадет в заголовок
Content-Type автоматически. Тело ответа
читают так же, как после запроса без тела.
Соберем тот же запрос через создание объекта запроса:
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
)
func main() {
payload := []byte("note=hello")
req, err := http.NewRequest(
"POST",
"http://127.0.0.1:8080/notes",
bytes.NewReader(payload),
)
if err != nil {
log.Fatal(err)
}
req.Header.Set(
"Content-Type",
"application/x-www-form-urlencoded",
)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
_, err = io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.StatusCode)
}
Даны адрес и тело:
addr := "http://127.0.0.1:8080/log"
data := []byte("ping")
Отправьте текст "text/plain" как тип
содержимого, прочитайте код состояния ответа
и закройте тело ответа.
Дан следующий код:
body := bytes.NewReader([]byte("ok"))
req, err := http.NewRequest("POST", addr, body)
Допишите установку Content-Type и
отправку через клиент по умолчанию.
Скажите, зачем для тела используют
bytes.NewReader, а не срез байт
напрямую там, где ждут io.Reader.