408 Request Timeout
Utilisation
Lorsqu’une erreur 408 Request Timeout survient, le client a bien initié une requête mais, pour une raison ou une autre, n’a pas transmis la totalité de la charge utile. Cela se produit lorsque la connexion internet est lente ou a été coupée. La réponse contient l’en-tête Connection, qui indique que la connexion a été fermée.
À la réception de l’en-tête Connection: close, le client retente la requête.
Remarque
408 Request Timeout signifie que le client a été trop lent à envoyer la requête au serveur. 504 Gateway Timeout signifie qu’un proxy ou une passerelle a dépassé son délai d’attente de la réponse du serveur dorsal. 408 est un délai d’expiration entre le client et le serveur, tandis que 504 est un délai d’expiration entre serveurs. 408 fait partie des rares codes 4xx qui justifient une nouvelle tentative automatique, car la cause est généralement passagère.
Impact SEO
Les moteurs de recherche comme Google n’indexent pas une URL renvoyant un statut 408. Les URL précédemment indexées qui renvoient ce code de statut sont retirées des résultats de recherche.
Exemple
Le client commence à envoyer un fichier PDF de 10K au serveur, mais la connexion souffre de problèmes de connectivité intermittents et le serveur conclut que la transmission est trop lente. Le serveur annule la requête et ferme la connexion. Une fois la connexion stabilisée, le client retransmet le fichier avec succès.
Requête initiale
PUT /docs HTTP/1.1
Host: example.com
Content-Type: application/pdf
Content-Length: 10000
Réponse initiale
HTTP/1.1 408 Request Timeout
Connection: Close
Content-Type: text/html
Content-Length: 198
<html>
<head>
<title>Connection Close</title>
</head>
<body>
<p>The transmission was not received quickly
enough. Check connectivity and try again.</p>
</body>
</html>
Requête suivante
PUT /docs HTTP/1.1
Host: example.com
Content-Type: application/pdf
Content-Length: 10000
<File transfer successful for PDF file>
Réponse finale
HTTP/1.1 200 OK
Comment corriger
Un 408 Request Timeout signifie que le serveur a fermé la connexion parce que le client n’a pas terminé la requête à temps.
Vérifiez la connectivité réseau et la latence. Une connexion instable ou lente retarde la transmission de la requête. Lancez ping et traceroute vers le serveur pour repérer les pertes de paquets ou les sauts à forte latence. Assurez-vous que la connexion est stable avant de réessayer.
Réduisez la taille de la charge utile ou fractionnez les envois volumineux. Envoyer un gros fichier sur une connexion lente dépasse la patience du serveur. Compressez la charge utile, utilisez un Transfer-Encoding par blocs, ou découpez l’envoi en plusieurs parties à l’aide des API d’upload multipart.
Augmentez les délais d’expiration côté client. La bibliothèque cliente HTTP ou le navigateur applique son propre délai d’expiration. Relevez les valeurs de délai de connexion et de lecture pour tenir compte des transferts plus lents. Avec curl, utilisez —connect-timeout et —max-time. Avec Python requests, définissez timeout=(connect, read).
Vérifiez la configuration des délais d’expiration du serveur. Ajustez les directives de délai selon le serveur web :
nginx :
client_header_timeout 60s;
client_body_timeout 60s;
keepalive_timeout 75s;
send_timeout 60s;
Apache :
Timeout 60
KeepAliveTimeout 5
RequestReadTimeout header=20-40 body=20
La directive RequestReadTimeout (mod_reqtimeout) contrôle séparément les délais de lecture des en-têtes et du corps. Augmentez ces valeurs lorsque les clients ont légitimement besoin de plus de temps.
Ajustez les réglages Keep-Alive. Un keepalive_timeout trop court ferme les connexions inactives avant que le client n’envoie la requête suivante sur une connexion persistante. Sous nginx, la valeur par défaut de keepalive_timeout est de 75 secondes. Relevez-la pour les API desservant des clients aux schémas de requêtes en rafales. Sous Apache, augmentez KeepAliveTimeout (5 secondes par défaut) et vérifiez que MaxKeepAliveRequests autorise un nombre suffisant de requêtes par connexion.
Vérifiez les délais d’expiration du proxy inverse et du répartiteur de charge. Lorsqu’un proxy inverse (nginx, HAProxy, AWS ELB) se trouve devant le serveur applicatif, chaque couche applique son propre délai d’expiration. Le proxy ferme la connexion en premier si son délai est plus court que celui du dorsal. En mode proxy inverse sous nginx :
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
AWS ALB applique par défaut un délai d’inactivité de 60 secondes, configurable dans les attributs du répartiteur de charge.
Retentez la requête. Un 408 est souvent passager. Rétablissez la connexion et resoumettez la requête complète. Mettez en place une logique de nouvelle tentative automatique avec temporisation exponentielle pour les clients programmatiques. L’en-tête Retry-After, lorsqu’il est présent, indique le délai à respecter avant de réessayer.
Examinez les journaux d’erreurs du serveur. nginx consigne les événements de délai d’expiration dans son journal d’erreurs. Apache consigne les violations de mod_reqtimeout. Inspectez /var/log/nginx/error.log ou /var/log/apache2/error.log à la recherche d’entrées correspondant à l’horodatage de la requête, afin de déterminer si le délai a expiré sur la lecture des en-têtes ou du corps.
Références de code
.NET
HttpStatusCode.RequestTimeout
Rust
http::StatusCode::REQUEST_TIMEOUT
Rails
:request_timeout
Go
http.StatusRequestTimeout
Symfony
Response::HTTP_REQUEST_TIMEOUT
Python3.5+
http.HTTPStatus.REQUEST_TIMEOUT
Java
java.net.HttpURLConnection.HTTP_CLIENT_TIMEOUT
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_REQUEST_TIMEOUT
Angular
@angular/common/http/HttpStatusCode.RequestTimeout