Le code 408 Request Timeout signifie que le serveur n’a pas reçu un message de requête complet dans le temps où il acceptait d’attendre. L’attente porte sur le client : ligne de requête, en-têtes, ou corps. La spécification indique que le serveur devrait fermer la connexion. Le client peut renvoyer la requête plus tard. Ce n’est pas un délai de génération de page.
Cette frontière évite les mauvais correctifs. Si votre outil a bien envoyé la requête et que le proxy attend l’application, vous êtes sur un autre code.
Situations qui déclenchent un 408
- Un envoi de fichier ou un POST volumineux traverse un réseau lent. Le serveur a lu le début, puis le corps n’arrive pas avant
client_body_timeout(Nginx) ouRequestReadTimeout(Apache). - Le client ouvre une connexion et n’envoie pas la ligne de requête. Des sondes, des navigateurs interrompus ou un proxy qui garde des connexions mortes finissent en 408. Nginx nomme souvent le cas voisin
client_header_timeout. - Une connexion keep-alive reste ouverte sans nouvelle requête. Selon le serveur et le client, la fermeture est vue comme un 408 au lieu d’une simple coupure.
- Un formulaire mobile passe en veille au milieu de l’envoi. La requête n’est jamais complète. L’utilisateur voit un échec, le journal montre un corps trop court.
- Un équipement intermédiaire (pare-feu, proxy d’entreprise) coupe les flux lents et le serveur d’origine conclut que le client s’est tu.
Le point commun : l’application PHP ou la base n’a en général même pas commencé le travail, parce que la requête HTTP n’est pas entière.
Vérifier que la requête n’arrive pas
- Rejouez une requête minuscule, un GET de la même URL, sans corps. Si elle répond 200 et que seul le gros POST répond 408, le délai de lecture du corps est en cause.
- Dans le journal d’accès, regardez les octets reçus et le temps. Un 408 avec un corps annoncé plus grand que le corps reçu confirme la coupure.
- Comparez depuis un autre réseau. Un 408 limité au bureau pointe vers le proxy local, pas vers le disque du serveur.
- Mesurez l’URL simple depuis l’extérieur avec un test d’URL. S’il obtient un code normal alors que vos uploads échouent, ne changez pas le code de la page : changez le traitement de l’envoi.
Un délai de plusieurs secondes sur une page déjà générée n’est pas un 408. Pour ce cas, la démarche de test de disponibilité sert à voir si l’URL répond, pas à expliquer un upload coupé.
Ajuster le délai côté réception
| Symptôme | Réglage concerné | Gestes utiles |
|---|---|---|
| Upload légitime coupé | client_body_timeout, RequestReadTimeout | Relever ce délai, et seulement celui-là |
| Connexions sans en-tête | client_header_timeout, keep-alive | Laisser un délai court : ce trafic n’est pas un client |
| Un seul réseau touché | Proxy ou pare-feu du client | Tester hors de ce réseau avant de toucher au serveur |
| Corps toujours tronqué | Taille maximale et timeout ensemble | Vérifier client_max_body_size : un corps trop gros peut échouer autrement, en 413 |
Augmentez le délai de lecture du corps uniquement pour les URL d’upload. Le laisser à plusieurs minutes sur tout le site occupe des connexions avec des clients qui ne finiront pas.
Ce qu’il ne faut pas faire
N’allongez pas proxy_read_timeout ou le délai Cloudflare en croyant corriger un 408 : ces réglages attendent la réponse de l’amont, pas les octets du visiteur. Ne transformez pas non plus le symptôme en 503 de maintenance. Ne demandez pas aux utilisateurs de « vider le cache » : le cache ne complète pas une requête jamais envoyée.
Si les 408 s’accumulent sur une URL précise du tunnel d’achat, regardez la taille du POST et le réseau, pas le thème. Une fois la requête reçue en entier, un autre code prendra le relais si l’application est lente. Ce sera alors un sujet de passerelle, pas un 408.
