HTTPクライアント #
注意事項 #
The Go Playground では外部のサイトへのアクセスを禁止しているのか HTTP クライアントが正常に動作しない。
他の章に合わせて The Go Playground での実行リンクを記載してはいるが、
動作確認したい場合は Go が実行可能な環境にファイルをコピーして go run
などで実行すること。
GET リクエストを送信する #
GET リクエストの送信には net/http
パッケージの func Get(url string) (resp *Response, err error)
関数を使う。
レスポンスは io.Reader
なので io.ReadAll
などでコンテンツを読み込む。
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
// リクエストの送信
res, err := http.Get("http://example.com")
if err != nil {
log.Fatal(err)
}
// レスポンスを読み込む
body, err := io.ReadAll(res.Body)
res.Body.Close()
// ステータスコードの判定
if res.StatusCode != http.StatusOK {
log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
}
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", body)
}
POST リクエストを送信する #
POST リクエストの送信には net/http
パッケージの func Post(url, contentType string, body io.Reader) (resp *Response, err error)
関数を使う。
リクエストのボディは io.Writer
なので bytes.Buffer
などを使う。
レスポンスは io.Reader
なので io.ReadAll
などでコンテンツを読み込む。
下記のコードは JSON を POST で送信する例。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
func main() {
// リクエストボディの作成
data, err := json.Marshal(map[string]string{
"key": "value",
})
if err != nil {
log.Fatal(err)
}
requestBody := bytes.NewBuffer(data)
// リクエストの送信
res, err := http.Post("http://example.com", "application/json", requestBody)
if err != nil {
log.Fatal(err)
}
// レスポンスを読み込む
body, err := io.ReadAll(res.Body)
res.Body.Close()
// ステータスコードの判定
if res.StatusCode != http.StatusOK {
log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
}
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", body)
}
POST で HTML フォームと同じ形式のデータを送信する #
POST リクエストで HTML のフォームと同じ形式のデータを送信するには net/http
パッケージの func PostForm(url string, data url.Values) (resp *Response, err error)
を使う。
リクエストのボディは url.Values
になる。
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/url"
)
func main() {
// リクエストボディの作成
values := url.Values{}
values.Set("name1", "value1")
values.Set("name2", "value2")
values.Set("name3", "value3")
// リクエストの送信
res, err := http.PostForm("http://example.com", values)
if err != nil {
log.Fatal(err)
}
// レスポンスを読み込む
body, err := io.ReadAll(res.Body)
res.Body.Close()
// ステータスコードの判定
if res.StatusCode != http.StatusOK {
log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
}
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", body)
}
GET リクエストのヘッダーをカスタマイズする #
リクエストのヘッダーをカスタマイズする場合は http.Request
を使ってヘッダーを設定し、http.Client
でリクエストの送信をする。
これは http.Get
の中で行なっているのと同じ処理である。
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
// リクエストの作成
// GET の場合はリクエストボディである第三引数を nil にする
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
log.Fatal(err)
}
// ヘッダーの設定
req.Header.Set("Accept-Encoding", "gzip, deflate")
req.Header.Set("Accept-Language", "en-us")
// リクエストの送信
c := &http.Client{}
res, err := c.Do(req)
if err != nil {
log.Fatal(err)
}
// レスポンスを読み込む
body, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", body)
}
POST リクエストのヘッダーをカスタマイズする #
リクエストのヘッダーをカスタマイズする場合は http.Request
を使ってヘッダーを設定し、http.Client
でリクエストの送信をする。
これは http.Post
の中で行なっているのと同じ処理である。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
func main() {
// リクエストボディの作成
data, err := json.Marshal(map[string]string{
"key": "value",
})
if err != nil {
log.Fatal(err)
}
requestBody := bytes.NewBuffer(data)
// リクエストの作成
req, err := http.NewRequest("POST", "http://example.com", requestBody)
if err != nil {
log.Fatal(err)
}
// ヘッダーの設定
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept-Language", "en-us")
// リクエストの送信
c := &http.Client{}
res, err := c.Do(req)
if err != nil {
log.Fatal(err)
}
// レスポンスを読み込む
body, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", body)
}
POST で HTML フォームの形式のファイルを送信する #
HTML のフォームでファイルを送っているのと同じ形式で POST リクエストを送信したい場合は、
mime/multipart
の multipart.Writer
を使ってリクエストボディを作る。
package main
import (
"bytes"
"io"
"log"
"mime/multipart"
"net/http"
"os"
)
func main() {
// アップロードするファイルを開く
filename := "hello.txt"
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
// リクエストボディの作成準備
body := &bytes.Buffer{}
mw := multipart.NewWriter(body)
fw, err := mw.CreateFormFile("file", filename)
// リクエストボディへファイルの内容を書き込む
_, err = io.Copy(fw, file)
if err != nil {
log.Fatal(err)
}
// リクエストボディの作成終了
err = mw.Close()
if err != nil {
log.Fatal(err)
}
// リクエストを送信
resp, err := http.Post("http://localhost:3000/upload", mw.FormDataContentType(), body)
if err != nil {
log.Fatal(err)
}
// レスポンスを閉じる
err = resp.Body.Close()
if err != nil {
log.Fatal(err)
}
}
参考ドキュメント: net/http , mime/multipart