Vérifiez les erreurs lorsque vous appelez http.ResponseWriter.Write ()

Disons que j’ai ce gestionnaire http:

func SomeHandler(w http.ResponseWriter, r *http.Request) { data := GetSomeData() _, err := w.Write(data) } 

Dois-je vérifier l’erreur renvoyée par w.Write ? Exemples J’ai vu l’ignorer et ne rien faire. De même, les fonctions telles que http.Error() ne renvoient pas d’erreur à traiter.

C’est à vous. Mon conseil est que, à moins que la documentation de certaines méthodes / fonctions n’indique explicitement qu’elle ne retourne jamais d’erreurs non nil (telles que bytes.Buffer.Write() ), vérifiez toujours l’erreur et le moins que vous puissiez faire est de la connecter. Si une erreur survient, elle laissera une marque sur laquelle vous pourrez enquêter si cela devenait un problème plus tard.

Cela est également vrai pour l’écriture sur http.ResponseWriter .

Vous pourriez penser que ResponseWriter.Write() peut uniquement renvoyer des erreurs si l’envoi des données échoue (par exemple, la connexion est fermée), mais ce n’est pas vrai. Le type concret qui implémente http.ResponseWriter est le type http.response non http.response , et si vous cochez la méthode response.write() exscope, vous verrez qu’il peut renvoyer une erreur non nil pour un tas d’autres raisons.

Raisons pour lesquelles ResponseWriter.Write() peut renvoyer une erreur non nil :

  • Si la connexion a été http.Hijacker (voir http.Hijacker ): http.ErrHijacked
  • Si la longueur du contenu a été spécifiée et que vous essayez d’écrire plus que cela: http.ErrContentLength
  • Si la méthode HTTP et / ou le statut HTTP n’autorisent aucun corps de réponse et que vous tentez d’écrire plus de 0 octet: http.ErrBodyNotAllowed
  • Si l’écriture de données sur la connexion réelle échoue.

Même si vous ne pouvez rien faire avec l’erreur, la journalisation peut être très utile pour le débogage ultérieur de l’erreur. Par exemple, vous (ou une autre personne de la chaîne de gestionnaires) avez piraté la connexion et vous essayez de lui écrire plus tard. vous obtenez une erreur ( http.ErrHijacked ), la connexion révélera immédiatement la cause.

Astuce pour les erreurs de journalisation “faciles”

Si vous ne pouvez rien faire avec des erreurs occasionnelles et que ce n’est pas un “showstopper”, vous pouvez créer et utiliser une fonction simple qui effectue la vérification et la journalisation, par exemple:

 func logerr(n int, err error) { if err != nil { log.Printf("Write failed: %v", err) } } 

En l’utilisant:

 logerr(w.Write(data)) 

Astuce pour les erreurs de “journalisation automatique”

Si vous ne voulez même pas utiliser la fonction logerr() tout le temps, vous pouvez créer un wrapper pour http.ResponseWriter qui le fait “automatiquement”:

 type LogWriter struct { http.ResponseWriter } func (w LogWriter) Write(p []byte) (n int, err error) { n, err = w.ResponseWriter.Write(p) if err != nil { log.Printf("Write failed: %v", err) } return } 

En l’utilisant:

 func SomeHandler(w http.ResponseWriter, r *http.Request) { w = LogWriter{w} w.Write([]byte("hi")) } 

En utilisant LogWriter comme un wrapper autour de http.ResponseWriter , si les écritures sur http.ResponseWriter origine échouent, elles seront enregistrées automatiquement.

Cela a également le grand avantage de ne pas attendre une fonction de journalisation pour pouvoir appeler une valeur de votre LogWriter “down” dans la chaîne, et tous ceux qui tenteront de l’écrire seront surveillés et consignés. s’inquiéter ou même savoir à ce sujet.

Cependant, il faut faire attention lors du passage de LogWriter à la chaîne, car cela présente également un inconvénient: une valeur de LogWriter pas d’autres interfaces que le http.ResponseWriter origine pourrait également utiliser, par exemple http.Hijacker ou http.Pusher .

Voici un exemple sur le terrain de jeu Go qui montre cela en action, et montre également que LogWriter ne va pas implémenter d’autres interfaces; et montre également un moyen (en utilisant 2 assertions de type “nestedes”) comment toujours extraire ce que nous voulons de LogWriter (un http.Pusher dans l’exemple).