Client HTTP en Go : faire des requêtes correctement de A à Z
Go (Golang) est un langage réputé pour sa simplicité et ses performances, notamment dans le domaine de la programmation réseau. Le package intégré net/http fournit un client HTTP puissant et flexible, adapté aussi bien aux requêtes simples qu'aux systèmes complexes à forte charge. Dans cet article, nous allons voir comment utiliser correctement le client HTTP en Go, des requêtes de base aux configurations avancées.
1. Bases : création et exécution de requêtes simples
La façon la plus simple d'effectuer une requête HTTP en Go est d'utiliser les fonctions d'aide du package net/http, comme http.Get et http.Post. Cependant, pour le code de production, il est recommandé d'utiliser une création explicite du client et de la requête.
Requête GET de base :
package main
import ( "fmt" "io/ioutil" "net/http")
func main() { // Créer un nouveau client client := &http.Client{}
// Créer une requête req, err := http.NewRequest("GET", "https://api.example.com/data", nil) if err != nil { fmt.Println("Erreur lors de la création de la requête :", err) return }
// Exécuter la requête resp, err := client.Do(req) if err != nil { fmt.Println("Erreur lors de l'exécution de la requête :", err) return } defer resp.Body.Close()
// Lire le corps de la réponse body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Erreur lors de la lecture de la réponse :", err) return }
fmt.Println("Statut :", resp.Status) fmt.Println("Corps :", string(body))}Requête POST avec corps JSON :
package main
import ( "bytes" "encoding/json" "fmt" "net/http")
type Payload struct { Name string `json:"name"` Email string `json:"email"`}
func main() { payload := Payload{Name: "John", Email: "john@example.com"} jsonData, _ := json.Marshal(payload)
client := &http.Client{} req, err := http.NewRequest("POST", "https://api.example.com/users", bytes.NewBuffer(jsonData)) if err != nil { fmt.Println("Erreur :", err) return }
// Définir les en-têtes req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer your-token")
resp, err := client.Do(req) if err != nil { fmt.Println("Erreur :", err) return } defer resp.Body.Close()
fmt.Println("Statut :", resp.Status)}2. Gestion des timeouts et des contextes
L'une des erreurs les plus fréquentes est l'absence de timeouts. Sans eux, votre client peut rester bloqué indéfiniment en attendant une réponse du serveur. En Go, il existe deux méthodes principales pour gérer les délais d'attente.
Timeout au niveau du client :
client := &http.Client{ Timeout: 10 * time.Second, // Timeout global pour toute la requête}Timeout avec utilisation du contexte (recommandé) :
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil)if err != nil { log.Fatal(err)}
resp, err := client.Do(req)if err != nil { // Vérifier si le timeout a expiré if errors.Is(err, context.DeadlineExceeded) { fmt.Println("La requête a dépassé le timeout") } else { fmt.Println("Erreur :", err) } return}defer resp.Body.Close()L'utilisation du contexte offre plus de flexibilité : vous pouvez annuler la requête à tout moment (par exemple, lors de la fermeture de l'application) et transmettre des valeurs via le contexte.
3. Gestion des erreurs et tentatives de reprise
Le réseau n'est pas fiable, votre client doit donc être prêt à faire face à des pannes temporaires.