Maison >développement back-end >Golang >golang encapsule les requêtes http

golang encapsule les requêtes http

PHPz
PHPzoriginal
2023-05-11 12:00:07638parcourir

Avec le développement d'Internet, les requêtes HTTP sont devenues la norme pour le développement back-end et constituent également le moyen permettant au front-end d'initier des requêtes réseau. Dans Golang, la bibliothèque standard dispose d'un package net/http intégré, fournissant un client et un serveur HTTP complets. Cependant, l'encapsulation d'une bibliothèque de requêtes HTTP nous permet de lancer des requêtes HTTP plus efficacement et plus facilement pendant le processus de développement. Dans cet article, nous verrons comment encapsuler une bibliothèque de requêtes HTTP Golang.

1. Analyse des exigences

Avant d'emballer une bibliothèque de requêtes HTTP, nous devons clarifier certaines exigences et fonctions afin de mieux concevoir et développer notre bibliothèque. Ici, nous pensons qu'une bibliothèque complète de requêtes HTTP doit avoir les fonctions suivantes :

  1. Prend en charge les méthodes HTTP telles que GET, POST, PUT et DELETE.
  2. Prend en charge la définition des en-têtes de demande, des corps de demande et des paramètres de demande.
  3. Prend en charge la définition des délais d'expiration et des tentatives.
  4. Prend en charge le formatage des valeurs de retour dans différents types de données.

Sur la base des exigences et des fonctions ci-dessus, nous pouvons commencer à concevoir et développer notre bibliothèque de requêtes HTTP.

2. Conception et mise en œuvre

2.1 Points de conception

Lors de la conception de notre bibliothèque de requêtes HTTP, nous devons prendre en compte certains points clés afin d'obtenir une bibliothèque de requêtes hautement disponible, évolutive et facile à utiliser. Plus précisément, nous devons considérer les aspects suivants :

  1. Problèmes de réseau.

Lorsque nous effectuons une requête HTTP, nous devons prendre en compte les problèmes de réseau, tels que l'expiration du délai de connexion, l'expiration du délai de demande, etc. Par conséquent, notre bibliothèque de requêtes HTTP doit prendre en charge la définition du délai d'expiration de la connexion et du délai d'expiration de la requête.

  1. Gestion des exceptions.

Lorsque nous lançons une requête HTTP, diverses exceptions imprévisibles peuvent se produire, telles que des exceptions réseau, des exceptions de valeur de retour, etc. Afin de rendre notre bibliothèque de requêtes HTTP plus robuste, ces exceptions doivent être gérées, par exemple, en fonction des codes d'état http, des informations sur les exceptions, etc.

  1. Prise en charge de l'API RESTful.

Dans l'API RESTful, il est souvent nécessaire de soumettre des données JSON ou des données de formulaire, etc. Par conséquent, dans notre bibliothèque de requêtes HTTP, nous devons prendre en charge la soumission et l'analyse de ces données.

  1. Gestion des valeurs de retour.

Après avoir lancé la requête HTTP, nous devons traiter la valeur de retour. Habituellement, le format de la valeur de retour des différentes interfaces API peut être différent. Par conséquent, nous devons prendre en charge le traitement correspondant en fonction du format de la valeur de retour de l'interface API.

2.2 Processus d'implémentation

Sur la base des points de conception ci-dessus, lorsque nous commençons à implémenter la bibliothèque de requêtes HTTP, nous pouvons suivre les étapes suivantes :

  1. Définir la structure de la requête HTTP.

Lors de l'encapsulation d'une bibliothèque de requêtes HTTP, nous devons encapsuler les informations de la requête HTTP. Plus précisément, nous pouvons définir une structure de requête HTTP pour stocker et transférer les informations requises pour la requête HTTP. Voici un exemple de la structure d'une requête HTTP :

type Request struct {
    URL        string
    Method     string
    Headers    map[string]string
    Body       []byte
    Params     map[string]string
    Timeout    int
    RetryTimes int
}
  1. initie une requête HTTP.

Après avoir défini la structure des requêtes HTTP, nous pouvons envoyer des requêtes HTTP via la bibliothèque standard de Golang.

Par exemple, nous pouvons utiliser la méthode http.NewRequest() pour créer une requête HTTP :

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

Utilisez la méthode DialContext() dans http.Transport pour définir le délai d'expiration de la connexion et le délai d'expiration de la demande :

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,
        }
    }

Ensuite, nous pouvons La méthode use Do() lance une requête HTTP et obtient la valeur de retour :

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

Après avoir lancé avec succès une requête HTTP, nous devons libérer des ressources pour éviter les fuites de mémoire causées par des requêtes malveillantes :

defer resp.Body.Close()
  1. Gestion des exceptions.

Lors du lancement d'une requête HTTP, diverses exceptions imprévisibles peuvent se produire, telles que des exceptions réseau, des exceptions de valeur de retour, etc. Par conséquent, ces exceptions doivent être gérées dans notre bibliothèque de requêtes HTTP.

Par exemple, nous pouvons vérifier les exceptions de requête HTTP en fonction du code d'état HTTP et du corps de la réponse. Si une exception se produit, nous pouvons renvoyer les informations d'erreur correspondantes en fonction du type d'exception, afin qu'elles puissent être découvertes et traitées à temps pendant le processus de développement.

  1. Prise en charge de l'API RESTful.

Lors de l'appel de l'API RESTful, nous devons prendre en charge différents formats de soumission, tels que les données JSON ou les données de formulaire, etc. Pour rendre notre bibliothèque de requêtes HTTP plus polyvalente, un champ d'attribut ContentType peut être ajouté pour prendre en charge différents formats de soumission. Dans le même temps, lors de la soumission de données JSON, nous devons également encoder les données au format JSON.

  1. Gestion des valeurs de retour.

Après avoir appelé l'interface, nous devons traiter la valeur de retour. Habituellement, le format de la valeur de retour des différentes interfaces API peut être différent. Par conséquent, nous devons effectuer le traitement correspondant dans l'application de couche supérieure en fonction du format de la valeur de retour de l'interface API. Par exemple, vous pouvez définir la méthode de désérialisation en fonction du format de la valeur de retour.

2.3 Implémentation du code

Sur la base des points de conception ci-dessus, lorsque nous commençons à implémenter la bibliothèque de requêtes HTTP, nous pouvons nous référer à l'implémentation de code suivante :

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.

Grâce à la discussion ci-dessus, nous pouvons constater qu'encapsuler une bibliothèque de requêtes HTTP Golang n'est pas une tâche particulièrement difficile. La clé est que nous devons être clairs sur nos besoins et comprendre certains détails des requêtes réseau, puis nous pouvons utiliser les méthodes fournies par la bibliothèque standard pour encapsuler une excellente bibliothèque de requêtes HTTP dans Golang. Dans le même temps, lors du processus de mise en œuvre, nous devons également prendre en compte certains détails, tels que la gestion des exceptions, la prise en charge de l'API RESTful, le traitement des valeurs de retour, etc. Grâce à une conception et une mise en œuvre minutieuses, nous pouvons développer une bibliothèque de requêtes HTTP de haute qualité pour rendre notre développement Golang plus efficace et plus pratique.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn