La description de Chromium est admirablement simple: “Le chargement d’une URL a entraîné trop de redirections.” Le navigateur a suivi une chaîne de redirections, la chaîne ne s’est pas terminée, et à un moment donné il a cessé de suivre.

Le nombre auquel il s’arrête provient de la Fetch Standard, qui est sans ambiguïté sur ce point: “si le redirect count de la requête est 20, renvoyer une erreur réseau”. Ainsi vingt sauts, puis la page que vous voyez est celle du navigateur, pas la vôtre.

Ce qui rend cette erreur digne de son propre article n’est pas le mécanisme, qui est évident. C’est qu’une boucle de redirection n’est presque jamais une seule chose cassée. Ce sont deux choses, chacune se comportant exactement comme configurée, en désaccord sur quelque chose qu’aucune d’elles ne peut voir.

Le classique, qui est un désaccord sur HTTPS

Vous mettez un CDN ou un équilibreur de charge devant votre application. Il termine TLS, ce qui est son travail, et transmet la requête à votre origine sur HTTP ordinaire, ce qui est normal et généralement délibéré.

Votre application a une règle qui dit: si cette requête n’est pas HTTPS, redirigez-la vers HTTPS. Aussi correct, et sur un serveur sans proxy devant lui, exactement ce qu’il faut.

Maintenant, mettez-les ensemble. Le navigateur demande https://example.com. Le CDN termine le TLS et transmet http://example.com à votre application. Votre application voit HTTP ordinaire, fait la chose sensée, et répond “rediriger vers https://example.com”. Le navigateur obéit. Le CDN termine TLS et transmet HTTP. Vingt fois, puis le navigateur abandonne.

Aucun composant n’est mal configuré en soi. L’application applique HTTPS. Le proxy termine TLS. Le bogue vit dans l’écart entre eux, c’est pourquoi les deux équipes peuvent regarder leur propre configuration et conclure correctement qu’elle va bien.

La solution est que l’application doit arrêter de poser la mauvaise question. Au lieu de “cette requête était-elle HTTPS”, elle doit demander “la requête originale était-elle HTTPS”, ce que l’en-tête X-Forwarded-Proto existe pour lui dire. La plupart des frameworks ont un paramètre pour faire confiance à cet en-tête depuis un proxy connu, et c’est généralement désactivé par défaut pour une bonne raison: un en-tête que n’importe qui peut définir n’est pas une preuve à moins que vous ne sachiez qui l’a défini.

La même forme, trois fois de plus

Une fois que vous voyez le motif, les autres boucles courantes sont la même histoire avec des noms différents.

www contre l’apex. Une couche redirige example.com vers www.example.com. Une autre, ajoutée plus tard ou par quelqu’un d’autre, redirige www vers l’apex. Chaque règle est défendable. La paire est une boucle.

La barre oblique finale. Votre serveur web redirige /about vers /about/. Le routeur du framework redirige /about/ vers /about. Les deux appliquent une forme canonique. Elles ne sont pas d’accord sur laquelle est canonique.

La boucle de connexion, qui est celle qui atteint les vrais utilisateurs. L’application ne voit pas de session valide, elle redirige donc vers /login. La page de connexion vérifie le cookie de session, croit être connectée, et redirige vers l’application. Encore et encore.

Ce dernier vaut la peine de s’attarder dessus, car la cause est généralement le cookie qui ne persiste pas plutôt que les règles de redirection étant fausses: un cookie Secure sur une page servie sur HTTP, un cookie SameSite=None sans Secure, un cookie défini sur www.example.com étant lu sur example.com, ou un navigateur configuré pour refuser les cookies tiers dans un contexte embarqué. La logique de redirection est correcte partout. Elle agit sur une session qui n’a jamais persisté.

Faible
"Votre page de connexion est coincée dans une boucle. Elle se recharge simplement sans cesse."
Meilleur
ERR_TOO_MANY_REDIRECTS sur /login, seulement dans une fenêtre privée, seulement après que j'ai déconnecté et reconnecté. Fonctionne dans ma fenêtre normale. La chaîne est /app → /login → /app.

Pourquoi celui-ci est inhabituellement difficile à voir de l’intérieur

Une boucle de redirection est souvent spécifique à un état dans lequel vous n’êtes pas.

S’il s’agit de la boucle de connexion, votre cookie est déjà défini et fonctionnant, le site se comporte donc parfaitement pour vous et boucle pour quiconque arrive frais. S’il s’agit d’une règle www que quelqu’un a ajoutée la semaine dernière, elle ne boucle que pour les personnes qui ont tapé l’autre nom d’hôte. S’il dépend d’un cookie que le navigateur refuse, il se reproduit dans une fenêtre privée et nulle part ailleurs.

Et le contrôle évident le rate. curl -I https://example.com vous montre une réponse, qui sera un 301 d’apparence parfaitement raisonnable avec un en-tête Location. Rien ne dit que la chaîne ne se termine jamais. Ce que vous voulez, c’est de suivre le tout:

curl -sIL -o /dev/null -w '%{url_effective} %{http_code}\n' https://example.com
curl -sI https://example.com | grep -i '^location'

Ou ouvrez l’onglet Réseau avec Conserver le journal coché, ce qui est la seule façon de conserver les sauts antérieurs au lieu de les effacer à chaque navigation. La chaîne est le diagnostic: lisez l’en-tête Location à chaque étape et vous pouvez généralement voir les deux règles qui discutent dans les trois premiers sauts.

Session Replay

Extension Chrome gratuite. Un clic sur la page qui se comporte mal capture la capture d'écran, la console et le journal réseau, et vous donne un lien à coller dans le ticket.

Obtenez l'extension

Une chose sur le 301 qui vaut la peine d’être connue avant de l’utiliser

Un 301 n’est pas simplement un 302 qui signifie plus.

MDN est spécifique sur une conséquence qui surprend les gens: dans la Fetch Standard, un user agent recevant un 301 en réponse à un POST utilise GET pour la requête redirigée. Votre soumission de formulaire devient un GET, le corps est parti, et l’échec ne ressemble pas du tout à un problème de redirection. Si vous avez besoin que la méthode soit conservée, 308 est celle qui interdit de le changer.

La règle générale est plus terne et plus utile: optez pour 302 ou 307 pendant que vous travaillez encore sur l’URL canonique, et utilisez 301 ou 308 quand vous êtes sûr. Une redirection permanente est une affirmation, et les affirmations sont beaucoup plus faciles à faire qu’à retirer.

Ce qu’il faut en retenir

ERR_TOO_MANY_REDIRECTS signifie vingt sauts sans fin, et la fin manque parce que deux règles ne sont pas d’accord, pas parce que l’une est cassée.

Donc ne commencez pas en cherchant la règle cassée. Commencez par lister chaque couche qui est autorisée à émettre une redirection: le CDN, l’équilibreur de charge, le serveur web, le framework, l’application, et tout ce qu’un plugin a ajouté sans le dire à personne. Ensuite, lisez la chaîne, un en-tête Location à la fois, et trouvez les deux qui discutent.

Et quand elle ne se reproduit pas pour vous, c’est une information plutôt qu’un obstacle. Cela signifie que la boucle dépend d’un état que vous avez déjà passé, et le moyen le plus rapide d’y arriver est une fenêtre privée, un nom d’hôte différent, ou la vue complète de ce que le navigateur a réellement reçu de quelqu’un pour qui c’est en ce moment en train d’échouer.