La descrizione stessa di Chromium è ammirabilmente lineare: “Il tentativo di caricare un URL ha risultato in troppi redirect.” Il browser ha seguito una catena di redirect, la catena non si è conclusa, e a un certo punto ha smesso di seguire.

Il numero in cui si ferma viene dal Fetch Standard, che è inequivocabile: se il conteggio di redirect della richiesta è 20, restituire un errore di rete. Quindi venti hop, e poi la pagina che vedi è quella del browser, non la tua.

Quello che rende questo errore degno del suo articolo non è il meccanismo, che è ovvio. È che un ciclo di redirect non è quasi mai una cosa rotta. Sono due cose, ciascuna che si comporta esattamente come configurata, in disaccordo su qualcosa che nessuna delle due riesce a vedere.

Il caso classico, che è un disaccordo su HTTPS

Metti un CDN o un load balancer di fronte alla tua applicazione. Termina TLS, che è il suo lavoro, e inolttra la richiesta alla tua origin su HTTP semplice, che è normale e di solito deliberato.

La tua applicazione ha una regola che dice: se questa richiesta non è HTTPS, reindirizzala a HTTPS. Anche questo è corretto, e su un server senza proxy di fronte, esattamente giusto.

Ora mettili insieme. Il browser chiede https://example.com. Il CDN termina TLS e inolttra http://example.com alla tua app. La tua app vede HTTP semplice, fa la cosa sensata, e risponde “reindirizza a https://example.com”. Il browser obbedisce. Il CDN termina TLS e inolttra HTTP. Venti volte, e poi il browser si arrende.

Nessun componente è configurato male di per sé. L’applicazione sta forzando HTTPS. Il proxy sta terminando TLS. Il bug vive nello spazio tra loro, ecco perché entrambi i team possono guardare la loro configurazione e concludere correttamente che è a posto.

La correzione è che l’app deve smettere di fare la domanda sbagliata. Invece di “questa richiesta era HTTPS”, deve chiedere “era HTTPS la richiesta originale”, che è quello che l’header X-Forwarded-Proto serve a dirle. La maggior parte dei framework ha un’impostazione per fidarsi di quell’header da un proxy noto, e di solito è disattivata per una buona ragione: un header che chiunque può impostare non è una prova a meno che tu non sappia chi l’ha impostato.

La stessa forma, altre tre volte

Una volta visto il modello, gli altri cicli comuni sono la stessa storia con sostantivi diversi.

www contro l’apex. Un livello reindirizza example.com a www.example.com. Un altro, aggiunto più tardi o da qualcun altro, reindirizza www di nuovo all’apex. Ogni regola è difendibile. La coppia è un ciclo.

La barra finale. Il tuo web server reindirizza /about a /about/. Il router del tuo framework reindirizza /about/ a /about. Entrambi stanno forzando una forma canonica. Dissentono su quale sia quella canonica.

Il ciclo di login, che è quello che raggiunge gli utenti veri. L’app non vede una sessione valida, così reindirizza a /login. La pagina di login controlla il cookie di sessione, crede di essere collegato, e reindirizza all’app. Avanti e indietro.

Quest’ultimo vale la pena soffermarsi, perché la causa di solito è il cookie che non riesce a stare piuttosto che le regole di redirect essere sbagliate: un cookie Secure su una pagina servita su HTTP, un cookie SameSite=None senza Secure, un cookie impostato su www.example.com che viene letto su example.com, o un browser configurato per rifiutare i cookie di terze parti in un contesto incorporato. La logica di redirect è corretta in tutto. Sta agendo su una sessione che non ha mai persistito.

Debole
"La tua pagina di login è bloccata in un ciclo. Si ricarica continuamente."
Migliore
ERR_TOO_MANY_REDIRECTS su /login, solo in una finestra privata, solo dopo aver fatto logout e nuovo login. Funziona nella mia finestra normale. Catena è /app → /login → /app.

Perché questo è insolitamente difficile da vedere dall’interno

Un ciclo di redirect è spesso specifico per uno stato in cui non sei.

Se è il ciclo di login, il tuo cookie è già impostato e funzionante, così il sito si comporta perfettamente per te e cicla per chiunque arrivi da capo. Se è una regola www che qualcuno ha aggiunto la scorsa settimana, cicla solo per le persone che hanno scritto l’altro nome host. Se dipende da un cookie che il browser sta rifiutando, riproduce in una finestra privata e da nessun’altra parte.

E il controllo ovvio se lo perde. curl -I https://example.com ti mostra una risposta, che sarà un 301 perfettamente ragionevole con un header Location. Nulla in esso dice che la catena non termina mai. Quello che vuoi è seguire l’intera cosa:

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

Oppure apri la scheda Rete con Conserva log selezionato, che è l’unico modo per mantenere gli hop precedenti invece di pulirli ad ogni navigazione. La catena è la diagnosi: leggi l’header Location ad ogni passaggio e solitamente puoi vedere le due regole in disaccordo entro tre hop.

Session Replay

Estensione Chrome gratuita. Un clic sulla pagina che si comporta male acquisisce lo screenshot, la console e il log di rete, e ti consegna un link da incollare nel ticket.

Scarica l'estensione

Una cosa su 301 che vale la pena sapere prima di usarlo

Un 301 non è semplicemente un 302 che lo significa di più.

MDN è specifico su una conseguenza che sorprende le persone: nel Fetch Standard, un user agent che riceve un 301 in risposta a un POST usa GET per la richiesta reindirizzata. Il tuo invio di form diventa un GET, il corpo è sparito, e l’errore non assomiglia affatto a un problema di redirect. Se hai bisogno che il metodo sia preservato, 308 è quello che proibisce di cambiarlo.

La regola generale è più noiosa e più utile: ricorri a 302 o 307 mentre stai ancora lavorando per capire quale sia l’URL canonico, e usa 301 o 308 quando ne sei sicuro. Un redirect permanente è un’affermazione, e le affermazioni sono molto più facili da fare che da ritirare.

Cosa portare da tutto ciò

ERR_TOO_MANY_REDIRECTS significa venti hop senza una conclusione, e la conclusione manca perché due regole dissentono, non perché una è rotta.

Quindi non iniziare cercando la regola rotta. Inizia elencando ogni livello che è autorizzato a emettere un redirect: il CDN, il load balancer, il web server, il framework, l’applicazione, e qualunque cosa un plugin abbia aggiunto senza dire a nessuno. Poi leggi la catena, uno header Location alla volta, e trova i due che stanno discutendo.

E quando non riproduce per te, questa è un’informazione piuttosto che un ostacolo. Significa che il ciclo dipende da uno stato che hai già superato, e il modo più veloce per arrivarci è una finestra privata, un nome host diverso, o l’immagine completa di quello che il browser effettivamente ha ricevuto da qualcuno per cui sta fallendo adesso.