伊藤  直子

伊藤 直子

1653479220

Goを使用したタイプセーフなHTTPリクエストの送信

Gopherの場合、基本的にクライアントが要求するコードを記述します。サードパーティが提供するRESTfulAPIをリクエストする必要がある場合があります。現時点では、リクエストをまとめるのは難しいと感じています。難しいことではありませんが、エラーが発生しやすいと感じています。

たとえば、このようなリクエストを送信したい場合、それは非常に単純に見えますが、それでも実際にそれを書くのは面倒です。

POST /articles/5/update?device=ios HTTP/1.1
Host: go-zero.dev
Authorization: Bearer <jwt-token>{"author": "kevin", "body": "this is not important!", "title": "my title", "type":6}

ネイティブな方法で行く

このAPIは実際には非常に単純であり、最初から直接作成できます。

func main() {
    var buf bytes.
    encoder := json.NewEncoder(&buf)
    params := map[string]interface{}{
        "title":  "my title",
        "body":   "this is not important!",
        "author": "kevin",
        "type":   6,
    }
    if err := encoder.Encode(params); err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    url := fmt.Sprintf("http://go-zero.dev/articles/%d/update?device=%s", 5, "ios")
    req, err := http.NewRequest(http.MethodPost, url, &buf)
    if err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    req.Header.Add("Authorization", "Bearer <jwt-token>")
    cli := http.Client{}
    resp, err := cli.Do(req)
    if err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    io.Copy(os.Stdout, resp.Body)
}

テストを実行したところ、パケットが取得されず、ダンプされなかったことがわかりました200 OK。リクエストは次のようになります。失敗の理由を考えられますか?

POST /articles/5/update?device=ios HTTP/1.1
Host: go-zero.dev
User-Agent: Go-http-client/1.1
Content-Length: 79
Authorization: Bearer <jwt-token>
Accept-Encoding: gzip{"author": "kevin", "body": "this is not important!", "title": "my title", "type":6}

失敗の具体的な理由については以下で説明しますので、最初にこのコードについて説明しましょう。がスプライシングパラメータに使用されていることがわかりmap[string]interface{}ます。各フィールドについて、タイプが一致するかどうかを確認することはできません。サーバーから送受信した場合にのみ、200 OK正しく通過したことを確認できます。たとえば、typeここではパラメータを型として使用していますが、誤って型intとして記述している可能性があります。stringただし、このパラメータが要求せずに正しく記述されていないことを確認するのは依然として困難です。

それでは、型の安全性のためにhttpcパッケージがどのように使用されるかを見てみましょう。go-zero

httpc実装

httpcパッケージでリクエストするためのコードがどのように書かれているか見てみましょう。

const url = "http://go-zero.dev/articles/:id/update"type UpdateArticle struct {
    ID            int    `path: "id"`
    Device        string `form: "device,options=ios,android,web,desktop"`
    Authorization string `header: "Authorization"`
    Title         string `json: "title"`
    Body          string `json: "body"`
    Author        string `json: "author"`
    Type          int    `json: "type"`
}func main() {
    data := &UpdateArticle{
        ID:            5,
        Device:        "ios",
        Authorization: "Bearer <jwt-token>",
        Title:         "my title",
        Body:          "this is not important!",
        Author:        "kevin",
        Type:          6,
    }    resp, err := httpc.Do(context.Background(), http.MethodPost, url, data)
    if err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    io.Copy(os.Stdout, resp.Body)
}

リクエストを送信してコードを確認しましょう。結果は期待どおりです。

POST /articles/5/update?device=ios HTTP/1.1
Host: go-zero.dev
User-Agent: Go-http-client/1.1
Content-Length: 79
Content-Type: application/json; charset=utf-8
Authorization: Bearer <jwt-token>
Accept-Encoding: gzip{"author": "kevin", "body": "this is not important!", "title": "my title", "type":6}

前のヘッダーとは対照的に、もう1つのヘッダーが設定されており、前のコードでContent-Type: application/json; charset=utf-8設定するのを忘れていることがわかりましたか。Content-Type

httpcリクエストのタイプを定義し、で送信することで、実装を非常に簡単に理解できDoます。、、のサポートによりpath、コードに示されているようにform、リクエストの送信は非常に簡単でタイプセーフです。headerjsonHTTP

その他の機能

上記の使いやすさとタイプセーフティに加えて、httpcパッケージには次の機能があります。

  1. によるタイムアウト制御context。あなたはリクエストに合格することができctxます。
  2. の自動統合OpenTelemetrytrace-idサーバーから返されたspan-id、は自動的にログに書き込まれるため、クライアントとサーバーは連携して問題を調査できます。
  3. httpc.Serviceサーキットブレーカーの能力を取得するために使用します。サーバー側で問題が発生すると、無駄なリクエストを回避し、サーバー側へのプレッシャーを軽減するために、リクエストの送信が自動的に停止されます。

ソース:https ://betterprogramming.pub/sending-type-safe-http-requests-with-go-eb5bd1f91558

#go 

What is GEEK

Buddha Community

Goを使用したタイプセーフなHTTPリクエストの送信
伊藤  直子

伊藤 直子

1653479220

Goを使用したタイプセーフなHTTPリクエストの送信

Gopherの場合、基本的にクライアントが要求するコードを記述します。サードパーティが提供するRESTfulAPIをリクエストする必要がある場合があります。現時点では、リクエストをまとめるのは難しいと感じています。難しいことではありませんが、エラーが発生しやすいと感じています。

たとえば、このようなリクエストを送信したい場合、それは非常に単純に見えますが、それでも実際にそれを書くのは面倒です。

POST /articles/5/update?device=ios HTTP/1.1
Host: go-zero.dev
Authorization: Bearer <jwt-token>{"author": "kevin", "body": "this is not important!", "title": "my title", "type":6}

ネイティブな方法で行く

このAPIは実際には非常に単純であり、最初から直接作成できます。

func main() {
    var buf bytes.
    encoder := json.NewEncoder(&buf)
    params := map[string]interface{}{
        "title":  "my title",
        "body":   "this is not important!",
        "author": "kevin",
        "type":   6,
    }
    if err := encoder.Encode(params); err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    url := fmt.Sprintf("http://go-zero.dev/articles/%d/update?device=%s", 5, "ios")
    req, err := http.NewRequest(http.MethodPost, url, &buf)
    if err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    req.Header.Add("Authorization", "Bearer <jwt-token>")
    cli := http.Client{}
    resp, err := cli.Do(req)
    if err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    io.Copy(os.Stdout, resp.Body)
}

テストを実行したところ、パケットが取得されず、ダンプされなかったことがわかりました200 OK。リクエストは次のようになります。失敗の理由を考えられますか?

POST /articles/5/update?device=ios HTTP/1.1
Host: go-zero.dev
User-Agent: Go-http-client/1.1
Content-Length: 79
Authorization: Bearer <jwt-token>
Accept-Encoding: gzip{"author": "kevin", "body": "this is not important!", "title": "my title", "type":6}

失敗の具体的な理由については以下で説明しますので、最初にこのコードについて説明しましょう。がスプライシングパラメータに使用されていることがわかりmap[string]interface{}ます。各フィールドについて、タイプが一致するかどうかを確認することはできません。サーバーから送受信した場合にのみ、200 OK正しく通過したことを確認できます。たとえば、typeここではパラメータを型として使用していますが、誤って型intとして記述している可能性があります。stringただし、このパラメータが要求せずに正しく記述されていないことを確認するのは依然として困難です。

それでは、型の安全性のためにhttpcパッケージがどのように使用されるかを見てみましょう。go-zero

httpc実装

httpcパッケージでリクエストするためのコードがどのように書かれているか見てみましょう。

const url = "http://go-zero.dev/articles/:id/update"type UpdateArticle struct {
    ID            int    `path: "id"`
    Device        string `form: "device,options=ios,android,web,desktop"`
    Authorization string `header: "Authorization"`
    Title         string `json: "title"`
    Body          string `json: "body"`
    Author        string `json: "author"`
    Type          int    `json: "type"`
}func main() {
    data := &UpdateArticle{
        ID:            5,
        Device:        "ios",
        Authorization: "Bearer <jwt-token>",
        Title:         "my title",
        Body:          "this is not important!",
        Author:        "kevin",
        Type:          6,
    }    resp, err := httpc.Do(context.Background(), http.MethodPost, url, data)
    if err ! = nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }    io.Copy(os.Stdout, resp.Body)
}

リクエストを送信してコードを確認しましょう。結果は期待どおりです。

POST /articles/5/update?device=ios HTTP/1.1
Host: go-zero.dev
User-Agent: Go-http-client/1.1
Content-Length: 79
Content-Type: application/json; charset=utf-8
Authorization: Bearer <jwt-token>
Accept-Encoding: gzip{"author": "kevin", "body": "this is not important!", "title": "my title", "type":6}

前のヘッダーとは対照的に、もう1つのヘッダーが設定されており、前のコードでContent-Type: application/json; charset=utf-8設定するのを忘れていることがわかりましたか。Content-Type

httpcリクエストのタイプを定義し、で送信することで、実装を非常に簡単に理解できDoます。、、のサポートによりpath、コードに示されているようにform、リクエストの送信は非常に簡単でタイプセーフです。headerjsonHTTP

その他の機能

上記の使いやすさとタイプセーフティに加えて、httpcパッケージには次の機能があります。

  1. によるタイムアウト制御context。あなたはリクエストに合格することができctxます。
  2. の自動統合OpenTelemetrytrace-idサーバーから返されたspan-id、は自動的にログに書き込まれるため、クライアントとサーバーは連携して問題を調査できます。
  3. httpc.Serviceサーキットブレーカーの能力を取得するために使用します。サーバー側で問題が発生すると、無駄なリクエストを回避し、サーバー側へのプレッシャーを軽減するために、リクエストの送信が自動的に停止されます。

ソース:https ://betterprogramming.pub/sending-type-safe-http-requests-with-go-eb5bd1f91558

#go