10 мин чтенияИнженерия

Петля редиректов: как найти и исправить ERR_TOO_MANY_REDIRECTS

Петля редиректов гоняет браузер между URL, пока он не сдастся. Проследите цепочку редиректов одной командой, найдите правило, которое всему противоречит, и исправьте это раз и навсегда.

Marius Voß
DevRel · edge infra
Петля редиректов, изображенная как два URL, указывающие друг на друга, пока счетчик переходов браузера не заканчивается и не возвращается ERR_TOO_MANY_REDIRECTS

Петля редиректов - это цепочка HTTP-редиректов, которая никогда не приземляется: URL A отправляет браузер на URL B, B отправляет его обратно на A, и примерно после двадцати переходов браузер перестает пытаться и выводит ERR_TOO_MANY_REDIRECTS. На странице назначения ничего не сломано. Два правила просто не согласны друг с другом насчет того, где должен жить URL, и каждое из них постоянно отменяет действие другого.

Зацикленный редирект - одна из немногих веб-ошибок, которая сама называет свою причину, если смотреть на нужную вещь. Не на браузер, не на страницу ошибки и уж точно не на кеш: на цепочку редиректов. Каждый переход несет заголовок Location, и два адреса, которые постоянно повторяются, - это два правила, которые нужно примирить. Этот материал проходит диагностику одной командой, причины почти каждой петли редиректов, которые мне приходилось распутывать, и решение, которое незаметно не создает вторую петлю где-то еще. Если сама семья редиректов вам не до конца ясна, типы редиректов URL - это карта; здесь - версия для устранения неполадок.

Что на самом деле означает ERR_TOO_MANY_REDIRECTS

Браузеры следуют по редиректам за вас, но не бесконечно. Каждый клиент ведет бюджет переходов и отказывается от запроса, когда он заканчивается: Chrome останавливается на 20 и не дает это изменить, Firefox поставляется с тем же значением по умолчанию под network.http.redirection-limit, а curl допускает 50 переходов, прежде чем пожаловаться. Стандарт оставляет число открытым. RFC 9110 говорит лишь, что клиент должен обнаруживать циклические редиректы и вмешиваться в них, что на языке спецификации вежливо означает: каждому браузеру нужен свой предохранитель.

Это различие важно для диагностики, потому что сама ошибка вообще не доказывает наличие цикла. Цепочка из двадцати одного отдельного перехода без повторов вызывает точно такое же сообщение, как и два URL, вечно перекидывающих запрос друг другу. Обе ситуации стоит исправлять, но только у одной из них есть пара адресов, которую нужно примирить. Справочник MDN по редиректам описывает обе формы, а практическая разница становится видна в ту же секунду, как вы выводите цепочку.

Петля редиректов между HTTPS URL и HTTP URL: счетчик переходов браузера достигает лимита и возвращает ERR_TOO_MANY_REDIRECTS

Есть еще одна вещь, которую страница ошибки скрывает: постоянный редирект кешируется браузером. Если петля была построена на ответах 301, посетители продолжают зацикливаться локально даже после того, как вы исправили сервер, - пока запись в кеше не истечет или они сами ее не очистят. Именно поэтому я тестирую изменения редиректов на 302 и повышаю до 301 только после того, как цепочка выстроена правильно - привычка, которую подробно обосновывает материал 301 против 302.

Проследите цепочку редиректов одной командой

Забудьте про браузер. Самый быстрый способ разобраться в любой петле редиректов - терминал, потому что curl печатает каждый переход, вместо того чтобы сворачивать их в одну страницу ошибки:

curl -sIL https://example.com | grep -E '^HTTP|^[Ll]ocation'

Вы получаете строку статуса и заголовок Location для каждого перехода, по порядку. Прочитайте сверху вниз, и проявится один из трех паттернов. Два чередующихся URL означают настоящий цикл, и эта пара называет оба виновных правила. Длинная вереница разных URL означает цепочку, которую кто-то наслаивал годами, при этом каждый переход по отдельности законен. А цепочка, которая нормально разрешается в терминале, но все равно падает в браузере, означает, что петлю вызывают cookie, поскольку curl по умолчанию их не отправляет.

Этот последний случай заслуживает отдельной проверки, потому что именно из-за него люди полдня обвиняют свой DNS:

curl -sIL -c jar.txt -b jar.txt https://example.com/account | grep -E '^HTTP|^[Ll]ocation'

С подключенным cookie jar петля логина или согласия воспроизводится прямо в командной строке, где действительно видно, какой endpoint постоянно устанавливает, а затем отклоняет сессию. В браузере эквивалентный вид - панель Network с включенным "Preserve log", которая не дает более ранним переходам стереться при навигации страницы. Если вы вообще не хотите открывать терминал, наш чекер ссылок прослеживает цепочку прямо в браузере и печатает код статуса на каждом переходе.

Причины почти каждой петли редиректов

Как только цепочка видна, причина обычно одна из небольшого набора. Повторяющаяся пара URL подсказывает, на какой слой смотреть: смена схемы туда-обратно указывает на терминацию TLS, смена хоста указывает на правило канонического хоста, а путь, который то приобретает, то теряет слэш, указывает на порядок правил переписывания (rewrite).

правила https за прокси, который терминирует TLS

Это самый распространенный бесконечный редирект в современном вебе, и он появился в тот момент, когда прокси начали терминировать TLS перед origin-серверами. Прокси принимает HTTPS-запрос от посетителя, а затем забирает ваш origin по обычному HTTP. Ваш origin видит небезопасный запрос, делает то, что вы ему сказали, и редиректит на HTTPS. Прокси отдает этот редирект, получает запрос снова, снова забирает origin по HTTP, и так по кругу. Cloudflare документирует именно этот сбой в своем режиме flexible encryption, и у любого другого прокси есть та же ловушка под другим названием.

Есть два чистых решения. Переключить прокси в режим full encryption, чтобы он общался с вашим origin по TLS, - это правильный ответ почти во всех случаях. Либо, если переход до origin действительно должен оставаться обычным, сделать так, чтобы правило origin читало заголовок X-Forwarded-Proto, а не смотрело на само соединение, - тогда оно перестанет редиректить запросы, которые уже были защищены на edge.

www и apex не согласны, какой хост главный

Одно правило канонического хоста - это нормально. Два таких правила, написанных в разное время разными людьми, - это уже петля. Классический вариант: конфигурация сервера отправляет apex на www, а конфигурация приложения отправляет www обратно на apex, и оба уверены, что правы. Вы сразу увидите это в цепочке: example.com на www.example.com на example.com, до бесконечности.

Выберите один хост, закрепите его ровно в одном месте и удалите второе правило, вместо того чтобы пытаться примирить их между собой. То же самое касается правила для завершающего слэша или приведения к нижнему регистру: когда два правила нормализуют один и тот же URL в противоположных направлениях, вы получаете петлю редиректов, хотя каждое правило по отдельности вполне разумно.

настройка URL в CMS или приложении, которая больше не совпадает

Большинство приложений хранят свой собственный канонический адрес, и это поле - по сути, правило редиректа с дружелюбным названием. Смените домен, переедьте в новое окружение или восстановите снимок базы данных с другого хоста - и приложение начнет редиректить каждый запрос на адрес, который редиректит обратно. Поскольку эта настройка живет в базе данных, а не в конфиге веб-сервера, она переживает аудит конфигурации, который вы только что провели, - именно это и делает ее такой неприятной для поиска.

Характерный признак - цепочка, которая покидает ваш текущий хост и никогда на него не возвращается. Исправьте сохраненный адрес на домен, который вы на самом деле обслуживаете, а затем сбросьте кеш приложения или страниц, в который попал неверный адрес.

Здесь правила ни при чем, а проблема - в состоянии. Шлюз редиректит неаутентифицированных посетителей на страницу логина, страница логина редиректит аутентифицированных обратно, а cookie сессии, которую нельзя прочитать на целевом домене, оставляет обе стороны уверенными, что обрабатывать запрос должна другая. Баннеры согласия дают такую же форму, когда сам редирект, устанавливающий cookie согласия, оказывается заблокирован.

Признак тот же, что и в предыдущем разделе: чистое приватное окно работает нормально, либо curl без cookie jar разрешается без проблем. Проверьте домен cookie и область Path, ее атрибуты Secure и SameSite относительно схемы, которую вы на самом деле обслуживаете, и не устанавливается ли она на apex, а читается на www.

Что повторяется в цепочкеВероятная причинаЧто менять в первую очередь
http на https и обратноПрокси терминирует TLS, origin настаиваетРежим full encryption либо доверие XFP
Apex на www и обратноДва правила канонического хостаУдалить одно, оставить единственное правило
Путь то приобретает, то теряет слэшПравила rewrite в неверном порядкеНормализовать один раз, до маршрутизации
Покидает ваш хост, не возвращаетсяСохраненный адрес сайта устарелИсправить URL-настройку приложения, сбросить кеш

Петли редиректов редко остаются загадкой, когда цепочка у вас перед глазами, но они съедают полдня, если вы гадаете вместо того, чтобы трассировать. Если вы предпочитаете владеть слоем редиректов, а не спорить с ним, бесплатный план Elido дает вам ссылки, у которых назначение - это единственное сохраненное значение, которое можно перенаправить, а каждый переход логируется.

Исправьте без создания второй петли

Само исправление короткое, и порядок действий важнее синтаксиса. Измените одно правило, затем протрассируйте заново. Если изменить сразу три и перезагрузить страницу, вы ничего не узнаете о том, какое из них имело значение, - я видел, как команда потратила час именно так, разбираясь с петлей, вызванной правилом, которое они уже исправили с первой попытки.

  1. Уберите или инвертируйте ровно одно из двух правил, названных цепочкой, чтобы запрос мог достичь 200 за один переход.
  2. Запустите трассировку curl -sIL заново и убедитесь, что теперь цепочка состоит максимум из одного редиректа, без повторяющегося хоста.
  3. Очистите кеш браузера или протестируйте в приватном окне, потому что любой 301, который вы отдавали раньше, все еще закеширован локально и сымитирует сбой, которого уже нет.
  4. И только затем повышайте временные редиректы до постоянных, когда форма цепочки уже устоялась.

В конце этого списка поджидают две ловушки. Первая - HSTS: как только хост однажды отправил заголовок Strict-Transport-Security, браузеры сами обновляют каждый запрос до HTTPS, поэтому правило origin, которое тоже принудительно включает HTTPS, становится избыточным и может превратить неправильную настройку прокси в петлю, которую невозможно воспроизвести, не очистив запись HSTS. Вторая ловушка - кеширование перед петлей. CDN, который закешировал 301, с удовольствием продолжит его отдавать даже после того, как origin перестанет его присылать, поэтому сброс кеша - часть исправления, а не действие после него. Длинные цепочки, которые никогда не зацикливаются, тоже стоит подрезать заодно: каждый лишний переход - это еще один шанс потерять query-строку, именно так UTM-параметры пропадают в GA4, и отчасти поэтому короткие ссылки не обязаны вредить SEO, пока остаются на глубине в один переход.

Вид цепочки редиректов до и после: цепочка из четырех переходов, зацикленная между хостами, и тот же запрос, разрешенный единственным каноническим редиректом

Когда петля образуется на короткой ссылке

Короткие ссылки добавляют еще одно место, где может образоваться цикл, и это не редирект самого сокращателя. Короткая ссылка - это единственный сохраненный переход: слаг на входе, назначение на выходе. Петля появляется, когда назначение указывает обратно, а это случается чаще, чем кажется. Кто-то редактирует ссылку кампании так, что она указывает на лендинг, а на лендинге осталось старое правило, редиректящее на короткий URL, потому что в прошлом квартале это был канонический адрес для публикации, - и теперь они перекидывают запрос друг другу. Оба перехода ведут себя ровно так, как настроены.

В этой же цепочке встречаются еще два варианта. Первый - пара коротких ссылок, указывающих друг на друга после массового редактирования, обычно из-за импорта таблицы, в которой колонка назначения содержала короткие URL вместо финальных. Второй - кастомный домен, который все еще резолвится на хост, редиректящий обратно на сокращатель, - это скорее пережиток DNS, чем проблема самой ссылки, и кастомные домены для коротких ссылок описывает, как должны выглядеть записи. Во всех трех случаях исправление одно - направить назначение на финальную страницу, а не на очередной редирект, и сделать это можно, не трогая ничего уже напечатанного или опубликованного.

Поскольку назначение хранится отдельно, а не зашито в URL, ничего из этого не требует перепечатки. В этом вся суть управляемых ссылок, а короткая ссылка не работает - более широкое руководство по диагностике на случай, если симптом - не именно петля.

Не дайте следующей петле случиться

Петли редиректов - это баг дрейфа конфигурации, поэтому долговечные исправления - самые скучные. Держите решение о каноническом хосте в одном-единственном месте и относитесь к любому второму правилу, затрагивающему схему или хост, как к багу с первого взгляда. Трассируйте новые редиректы командой curl -sIL до того, как объявить о них, а не после того, как кто-то сообщит о пустой странице. Если ссылки важны для выручки, поставьте на них проверку: запланированная трассировка, которая падает, когда цепочка вырастает больше одного перехода, ловит дрейф задолго до клиента, а мониторинг редиректов ссылок показывает, как это выглядит, подключенное к настоящему алертингу.

Более широкая привычка - относиться к назначениям как к данным, которые можно аудировать. Предотвращение протухания ссылок описывает ту же дисциплину для ссылок, которые незаметно перестают резолвиться, и в любом случае это одна и та же еженедельная проверка. Если честно, большинство петель, которые я видел, были созданы двумя компетентными людьми, каждый из которых исправил одну и ту же проблему в разном слое с разницей в месяц. Запишите правило один раз - и петля перестанет быть возможной.

Читайте цикл материалов

Этот материал относится к кластеру инженерии. За формой самого пути редиректа обратитесь к материалу p95 редиректов ниже 15 мс, где разобрано, сколько стоит один корректно устроенный переход, а типы редиректов URL описывает, какой код статуса уместен где, прежде чем вы начнете наслаивать правила.

Похожие материалы в блоге

Частые вопросы

Что означает ERR_TOO_MANY_REDIRECTS?

Это значит, что браузер последовательно переходил по редиректам, так и не добравшись до настоящей страницы, уперся в лимит переходов и остановился. Сама страница обычно в порядке; два правила редиректа не согласны друг с другом насчет того, куда должен вести URL, и каждое из них отменяет действие другого. Chrome показывает ERR_TOO_MANY_REDIRECTS, Firefox сообщает, что страница перенаправляет неправильно, а Safari сообщает, что произошло слишком много редиректов.

Как исправить ERR_TOO_MANY_REDIRECTS?

Сначала проследите цепочку, затем уберите одно из двух правил, которые борются за URL. Выполните curl -sIL для адреса и прочитайте каждый заголовок Location: пара URL, которая постоянно повторяется, покажет, какое правило удалить или инвертировать. Обычные виновники - это правило HTTPS, работающее за прокси, который терминирует TLS, правило www, наложенное поверх другого правила www, и настройка адреса сайта, которая больше не соответствует обслуживаемому домену.

Сколько редиректов браузер выполнит, прежде чем сдастся?

Около двадцати, в зависимости от браузера. Chrome останавливается после 20 переходов, и этот лимит нельзя настроить, Firefox предоставляет тот же потолок через network.http.redirection-limit со значением по умолчанию 20, а curl следует до 50 переходов, если не изменить --max-redirs. Спецификация не задает конкретное число: RFC 9110 лишь говорит, что клиент должен обнаруживать циклические редиректы и вмешиваться в них, поэтому каждый клиент выбирает свой собственный потолок.

Помогает ли очистка cookie исправить петлю редиректов?

Иногда, и это уже подсказка. Если страница нормально загружается в приватном окне, петлю вызывает устаревший cookie сессии или согласия, а не правила вашего сервера, и его очистка - реальное решение для этого посетителя. Если петля возникает и в свежем приватном окне, cookie ни при чем, а проблема в правиле редиректа, настройке прокси или поле URL в CMS.

Почему мой сайт начал зацикливаться после включения HTTPS или CDN-прокси?

Потому что теперь два слоя настаивают на HTTPS, но один из них общается с вашим origin по обычному HTTP. Прокси запрашивает origin по порту 80, правило origin отправляет его обратно на HTTPS, прокси отвечает на этот запрос точно так же, и цикл никогда не заканчивается. Переключите режим шифрования прокси на full, чтобы он обращался к origin по TLS, либо сделайте так, чтобы ваше правило доверяло заголовку X-Forwarded-Proto, а не самому соединению.

Может ли короткая ссылка вызвать петлю редиректов?

Да, когда назначение указывает обратно на короткую ссылку, либо когда две ссылки указывают друг на друга. Самый частый вариант - отредактировать ссылку так, что она указывает на страницу, которая сама редиректит на короткий URL, и это переживает любое обновление браузера, потому что оба перехода работают именно так, как настроены. Направьте назначение на финальную страницу, а не на очередной редирект, и петля исчезнет без необходимости что-либо перепечатывать.

Попробуйте Elido

Вставьте URL - получите короткую ссылку

Без регистрации. Ссылка живёт 30 дней. Зарегистрируйтесь, чтобы оставить её навсегда.

Бесплатно, без регистрации · 2 в день

Попробуйте Elido

URL-сокращатель с хостингом в ЕС: собственные домены, глубокая аналитика, открытый API. Бесплатный тариф - без банковской карты.

Теги
redirect loop
err_too_many_redirects
too many redirects
redirect chain
infinite redirect
301 redirect loop

Читать дальше