Посмотрите, как пакет httpc в go-zero используется для безопасности типов.

Для Gophers мы в основном пишем код для запросов клиентов. Иногда нам нужно запрашивать RESTful API, предоставляемые третьими лицами. В настоящее время мы чувствуем, что собирать запросы сложно, не сложно, но подвержено ошибкам.

Например, если мы хотим отправить такой запрос, он выглядит очень просто, но на самом деле писать его все равно утомительно.

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}

Вы заметили, что, в отличие от предыдущего, был установлен еще один заголовок, Content-Type: application/json; charset=utf-8, и мы забыли установить Content-Type в предыдущем коде.

Реализация httpc очень проста для понимания путем определения типа запроса и отправки с помощью Do. Благодаря поддержке path, form, header и json, как показано в нашем коде, очень легко и безопасно отправлять запросы HTTP.

Дополнительные возможности

В дополнение к простоте использования и безопасности типов, показанным выше, пакет httpc имеет следующие особенности.

  1. управление тайм-аутом с помощью context. Вы можете передать ctx для запросов.
  2. автоматическая интеграция OpenTelemetry. trace-id, span-id, возвращенные сервером, будут автоматически записаны в журнал, чтобы клиент и сервер могли совместно исследовать проблемы.
  3. используйте httpc.Service, чтобы получить способность автоматического выключателя. Когда на стороне сервера возникают проблемы, он автоматически прекращает отправку запросов, чтобы избежать бесполезных запросов и снизить нагрузку на серверную сторону.
Want to Connect?
You're welcome to use go-zero and star to support us!