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 :
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 :
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.
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.
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.
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 :
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 }
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()
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.
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.
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!