[Go] GET リクエスト & レスポンスの取り扱い方


サーバー側の実装例をよくみかけますがk、GO ではクライアント側の実装もできます。

基本的な GET リクエスト

まずは、基本から。

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func main() {
    url := "http://localhost:8080"
    resp, err := http.Get(url)
    if err != nil {
        log.Fatalln("Failed to get response")
    }

    content, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatalln("Failed to read content")
    }
    defer resp.Body.Close()

    fmt.Println(string(content))
}

netcat を使ってリクエスト内容を確認 (= nc -l 8080)。

GET / HTTP/1.1
Host: localhost:8080
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip

標準では User-Agent: Go-http-client/1.1 ですね。

リクエストヘッダーにカスタムの情報を追加・編集

User-Agent を別の情報で表示する場合は、ヘッダーの編集が必要

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func main() {
    url := "http://localhost:8080"

    // Client 型を取得
    client := http.DefaultClient

    // Request 型 (ポインタ) を取得
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Fatalln("Failed to create reqeust")
    }

    // 任意の Header を作る。ここでは、Agent 名を変更
    req.Header.Add("User-Agent", "Custom Agent")

    // リクエストを送信、レスポンスを resp に入れる
    resp, err := client.Do(req)
    if err != nil {
        log.Fatalln("Failed to get response")
    }

    content, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatalln("Failed to read content")
    }
    defer resp.Body.Close()

    fmt.Println(string(content))
}

netcat を使ってリクエスト内容を確認 (= nc -l 8080)。

GET / HTTP/1.1
Host: localhost:8080
User-Agent: Custom Agent # ちゃんと変わってる
Accept-Encoding: gzip

Basic 認証

Basic 認証の仕組みを理解するついでに調べました。

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func main() {
    url := "http://localhost:8080"

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Fatalln("Failed to create request")
    }

    // Basic 認証用の ID & Password
    req.SetBasicAuth("user", "passw0rd")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatalln("Failed to get response")
    }

    content, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatalln("Failed to read content")
    }
    defer resp.Body.Close()

    fmt.Println(string(content))
    fmt.Println(resp.StatusCode)
}

netcat を使ってリクエスト内容を確認 (= nc -l 8080)。

GET / HTTP/1.1
Host: localhost:8080
User-Agent: Go-http-client/1.1
Authorization: Basic dXNlcjpwYXNzdzByZA==  # base64 デコードすると user:passw0rd
Accept-Encoding: gzip

ヘッダーに base64 エンコードされた ID & パスワードを入れるとなると、確かに安全ではないですね。。