Heim >Backend-Entwicklung >Golang >Golang kapselt HTTP-Anfragen

Golang kapselt HTTP-Anfragen

PHPz
PHPzOriginal
2023-05-11 12:00:07637Durchsuche

Mit der Entwicklung des Internets sind HTTP-Anfragen zum Standard für die Back-End-Entwicklung geworden und dienen auch dem Front-End dazu, Netzwerkanfragen zu initiieren. In Golang verfügt die Standardbibliothek über ein integriertes Net/http-Paket, das einen vollständigen HTTP-Client und -Server bereitstellt. Durch die Kapselung einer HTTP-Anfragebibliothek können wir jedoch HTTP-Anfragen während des Entwicklungsprozesses effizienter und bequemer initiieren. In diesem Artikel besprechen wir, wie man eine Golang-HTTP-Anforderungsbibliothek kapselt.

1. Anforderungsanalyse

Bevor wir eine HTTP-Anforderungsbibliothek packen, müssen wir einige Anforderungen und Funktionen klären, um unsere Bibliothek besser entwerfen und entwickeln zu können. Hier glauben wir, dass eine vollständige HTTP-Anforderungsbibliothek die folgenden Funktionen haben muss:

  1. Unterstützt HTTP-Methoden wie GET, POST, PUT und DELETE.
  2. Unterstützt das Festlegen von Anforderungsheadern, Anforderungstexten und Anforderungsparametern.
  3. Unterstützt das Festlegen von Zeitüberschreitungen und Wiederholungsversuchen.
  4. Unterstützt die Formatierung von Rückgabewerten in verschiedene Datentypen.

Basierend auf den oben genannten Anforderungen und Funktionen können wir mit dem Entwurf und der Entwicklung unserer HTTP-Anforderungsbibliothek beginnen.

2. Design und Implementierung

2.1 Designpunkte

Beim Design unserer HTTP-Anforderungsbibliothek müssen wir einige wichtige Punkte berücksichtigen, um eine hochverfügbare, skalierbare und benutzerfreundliche Anforderungsbibliothek zu erreichen. Konkret sollten wir folgende Aspekte berücksichtigen:

  1. Netzwerkprobleme.

Beim Senden einer HTTP-Anfrage müssen wir Netzwerkprobleme wie Verbindungs-Timeout, Anforderungs-Timeout usw. berücksichtigen. Daher muss unsere HTTP-Anforderungsbibliothek das Festlegen des Verbindungszeitlimits und des Anforderungszeitlimits unterstützen.

  1. Ausnahmebehandlung.

Wenn wir eine HTTP-Anfrage initiieren, können verschiedene unvorhersehbare Ausnahmen auftreten, z. B. Netzwerkausnahmen, Rückgabewertausnahmen usw. Um unsere HTTP-Anforderungsbibliothek robuster zu machen, müssen diese Ausnahmen behandelt werden, beispielsweise basierend auf http-Statuscodes, Ausnahmeinformationen usw.

  1. RESTful API-Unterstützung.

In der RESTful API ist es oft notwendig, JSON-Daten oder Formulardaten usw. zu übermitteln. Daher müssen wir in unserer HTTP-Anforderungsbibliothek die Übermittlung und Analyse dieser Daten unterstützen.

  1. Umgang mit Rückgabewerten.

Nachdem wir die HTTP-Anfrage initiiert haben, müssen wir den Rückgabewert verarbeiten. Normalerweise kann das Format des Rückgabewerts verschiedener API-Schnittstellen unterschiedlich sein. Daher müssen wir die entsprechende Verarbeitung entsprechend dem Rückgabewertformat der API-Schnittstelle unterstützen.

2.2 Implementierungsprozess

Basierend auf den oben genannten Entwurfspunkten können wir zu Beginn der Implementierung der HTTP-Anforderungsbibliothek die folgenden Schritte ausführen:

  1. Definieren Sie die Struktur der HTTP-Anforderung.

Beim Kapseln einer HTTP-Anforderungsbibliothek müssen wir die HTTP-Anforderungsinformationen kapseln. Konkret können wir eine Struktur einer HTTP-Anfrage definieren, um die für die HTTP-Anfrage erforderlichen Informationen zu speichern und zu übertragen. Das Folgende ist ein Beispiel für den Aufbau einer HTTP-Anfrage:

type Request struct {
    URL        string
    Method     string
    Headers    map[string]string
    Body       []byte
    Params     map[string]string
    Timeout    int
    RetryTimes int
}
  1. initiiert eine HTTP-Anfrage.

Nachdem wir die HTTP-Anfragestruktur definiert haben, können wir HTTP-Anfragen über die Standardbibliothek von Golang senden.

Zum Beispiel können wir die Methode http.NewRequest() verwenden, um eine HTTP-Anfrage zu erstellen:

req, err := http.NewRequest(req.Method, req.URL, bytes.NewBuffer(req.Body))
if err != nil {
    return nil, err
}

Verwenden Sie die Methode DialContext() in http.Transport, um das Verbindungszeitlimit und das Anforderungszeitlimit festzulegen:

client := &http.Client{
        Transport: &http.Transport{
            DialContext: (&net.Dialer{
                Timeout:   time.Duration(req.Timeout) * time.Second,
                KeepAlive: time.Duration(req.Timeout) * time.Second,
            }).DialContext,
            MaxIdleConns:        100,              // http.ConnectionPool数量
            IdleConnTimeout:     90 * time.Second, // http.ConnectionPool中连接的空闲超时时间
            TLSHandshakeTimeout: 10 * time.Second,
            ExpectContinueTimeout: 1 * time.Second,
        }
    }

Als nächstes können wir Die Verwendung der Do( )-Methode initiiert eine HTTP-Anfrage und erhält den Rückgabewert:

resp, err := client.Do(req)
if err != nil {
    return nil, err
}

Nach erfolgreicher Initiierung einer HTTP-Anfrage müssen wir Ressourcen freigeben, um Speicherverluste durch böswillige Anfragen zu vermeiden:

defer resp.Body.Close()
  1. Ausnahmebehandlung.

Beim Initiieren einer HTTP-Anfrage können verschiedene unvorhersehbare Ausnahmen auftreten, z. B. Netzwerkausnahmen, Rückgabewertausnahmen usw. Daher müssen diese Ausnahmen in unserer HTTP-Anforderungsbibliothek behandelt werden.

Zum Beispiel können wir HTTP-Anforderungsausnahmen basierend auf dem HTTP-Statuscode und dem Antworttext prüfen. Wenn eine Ausnahme auftritt, können wir entsprechend der Art der Ausnahme entsprechende Fehlerinformationen zurückgeben, sodass diese rechtzeitig während des Entwicklungsprozesses erkannt und verarbeitet werden können.

  1. RESTful API-Unterstützung.

Beim Aufruf der RESTful-API müssen wir verschiedene Übermittlungsformate unterstützen, z. B. JSON-Daten oder Formulardaten usw. Um unsere HTTP-Anforderungsbibliothek vielseitiger zu machen, kann ein ContentType-Attributfeld hinzugefügt werden, um verschiedene Übermittlungsformate zu unterstützen. Gleichzeitig müssen wir bei der Übermittlung von JSON-Daten die Daten auch in das JSON-Format kodieren.

  1. Umgang mit Rückgabewerten.

Nach dem Aufruf der Schnittstelle müssen wir den Rückgabewert verarbeiten. Im Allgemeinen kann das Format des Rückgabewerts verschiedener API-Schnittstellen unterschiedlich sein. Daher müssen wir eine entsprechende Verarbeitung in der Anwendung der oberen Ebene entsprechend dem Rückgabewertformat der API-Schnittstelle durchführen. Beispielsweise können Sie die Deserialisierungsmethode basierend auf dem Format des Rückgabewerts festlegen.

2.3 Code-Implementierung

Basierend auf den oben genannten Entwurfspunkten können wir uns zu Beginn der Implementierung der HTTP-Anforderungsbibliothek auf die folgende Code-Implementierung beziehen:

package httpreq

import (
    "bytes"
    "encoding/json"
    "io/ioutil"
    "net"
    "net/http"
    "time"
)

type Request struct {
    URL        string
    Method     string
    Headers    map[string]string
    Body       []byte
    Params     map[string]string
    Timeout    int
    RetryTimes int
    ContentType string
}

type Response struct {
    StatusCode int
    Body       []byte
}

func Do(req Request) (*Response, error) {
    if req.Method == "" {
        req.Method = http.MethodGet
    }

    // 处理请求参数
    if req.Params != nil {
        req.URL = AddQueryParams(req.URL, req.Params)
    }

    // 创建一个请求
    httpRequest, err := http.NewRequest(req.Method, req.URL, bytes.NewBuffer(req.Body))
    if err != nil {
        return nil, err
    }

    // 处理请求头
    if req.Headers != nil {
        for k, v := range req.Headers {
            httpRequest.Header.Set(k, v)
        }
    }

    // 设置ContentType
    if req.ContentType != "" {
        httpRequest.Header.Set("Content-Type", req.ContentType)
    }

    // 设置请求超时
    httpClient := &http.Client{
        Transport: &http.Transport{
            DialContext: (&net.Dialer{
                Timeout:   time.Duration(req.Timeout) * time.Second,
                KeepAlive: time.Duration(req.Timeout) * time.Second,
            }).DialContext,
            MaxIdleConns:        100,              // http.ConnectionPool数量
            IdleConnTimeout:     90 * time.Second, // http.ConnectionPool中连接的空闲超时时间
            TLSHandshakeTimeout: 10 * time.Second,
            ExpectContinueTimeout: 1 * time.Second,
        },
    }

    // 发起请求
    resp, err := httpClient.Do(httpRequest)
    if err != nil {
        return nil, err
    }

    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    // 处理异常
    if resp.StatusCode >= 400 {
        return nil, NewError(resp.StatusCode, body)
    }

    return &Response{StatusCode: resp.StatusCode, Body: body}, nil
}

func AddQueryParams(url string, params map[string]string) string {
    var queryParams string
    for k, v := range params {
        queryParams = queryParams + "&" + k + "=" + v
    }
    url = url + "?" + queryParams[1:]
    return url
}

func NewError(statusCode int, body []byte) error {
    errorMsg := string(body)
    if errorMsg == "" {
        errorMsg = http.StatusText(statusCode)
    }
    return &httpError{StatusCode: statusCode, Message: errorMsg}
}

type httpError struct {
    StatusCode int
    Message    string
}

func (e *httpError) Error() string {
    return e.Message
}

func (r *Response) BindJSON(v interface{}) error {
    return json.Unmarshal(r.Body, v)
}

func (r *Response) BindText() string {
    return string(r.Body)
}

3

Durch die obige Diskussion können wir feststellen, dass die Kapselung einer Golang-HTTP-Anforderungsbibliothek nicht besonders schwierig ist. Der Schlüssel liegt darin, dass wir uns über unsere Bedürfnisse im Klaren sind und einige Details von Netzwerkanforderungen verstehen. Anschließend können wir die von der Standardbibliothek bereitgestellten Methoden verwenden, um eine hervorragende HTTP-Anforderungsbibliothek in Golang zu kapseln. Gleichzeitig müssen wir während des Implementierungsprozesses auch einige Details berücksichtigen, wie z. B. Ausnahmebehandlung, RESTful-API-Unterstützung, Verarbeitung von Rückgabewerten usw. Durch sorgfältiges Design und Implementierung können wir eine hochwertige HTTP-Anforderungsbibliothek entwickeln, um unsere Golang-Entwicklung effizienter und bequemer zu gestalten.

Das obige ist der detaillierte Inhalt vonGolang kapselt HTTP-Anfragen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn