Перейти к содержимому

Редирект на другой домен - где ставить правило и почему оно не работает

Настраиваем постоянный редирект на новый домен и разбираемся, почему правило не срабатывает или срабатывает не полностью.

Решение

Ставим правило в nginx отдельным серверным блоком:

server {
listen 80;
server_name old-domain.ru www.old-domain.ru;
return 301 https://new-domain.ru$request_uri; # адрес страницы сохраняется
# оба написания имени, с www и без, склеивают одним блоком
}

Отдельный блок надёжнее условия внутри рабочего: он не участвует в обработке живого сайта и не задевает его правила. В окружении такой блок кладут отдельным файлом в каталог подключаемых конфигов.

Меняем адрес сайта в настройках платформы:

// Настройки - Настройки продукта - Сайты - параметры сайта
$site = new CSite();
$site->Update($siteId, ['SERVER_NAME' => 'new-domain.ru']);
// адрес отсюда идёт в письма и в абсолютные ссылки, а не из строки браузера

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

Проверяем, что отвечает сервер:

Окно терминала
curl -sI http://old-domain.ru/catalog/ | head -3
curl -sI https://new-domain.ru/catalog/ | head -3

В первом ответе должен быть код 301 и заголовок с новым адресом, во втором - 200. Цепочка из двух и более перенаправлений означает, что правило дублируется на разных уровнях.

Сбрасываем кеш композита:

// закешированные страницы хранят абсолютные ссылки со старым доменом
CHTMLPagesCache::getInstance()->deleteAll();
BXClearCache(true);

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

Ищем оставшиеся абсолютные ссылки в контенте:

SELECT ID, NAME FROM b_iblock_element
WHERE DETAIL_TEXT LIKE '%old-domain.ru%' OR PREVIEW_TEXT LIKE '%old-domain.ru%'
LIMIT 50;

Редирект такие ссылки подхватит, но каждая даст лишний переход. На большом каталоге их переписывают запросом, предварительно сняв резервную копию таблицы.

Ставим редирект с IP-адреса на домен:

server {
listen 80 default_server; # ловит всё, что не совпало по имени
server_name _;
return 301 https://new-domain.ru$request_uri;
}

Блок по умолчанию заодно закрывает обращения по чужому домену, направленному на этот сервер: без него сайт открывается по любому имени, указывающему на его IP.

Порядок работ при переезде получается такой: правило в nginx, адрес сайта в настройках, сброс кеша, замена абсолютных ссылок в контенте. Пропуск любого шага даёт свой набор жалоб, и по симптому легко понять, какой именно шаг забыт.

Типичные проблемы

Правило редиректа из админки не срабатывает.

Его перехватывает nginx или .htaccess: они отрабатывают раньше кода платформы. Проверяют сверху вниз, начиная с конфига веб-сервера.

Часть страниц уходит на старый домен после смены.

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

Браузер показывает цепочку из нескольких редиректов.

Одно и то же правило прописано и в nginx, и в .htaccess. Оставляют один уровень: лишние перенаправления замедляют ответ и портят индексацию.

Редирект с домена в национальной зоне не работает.

Кириллический домен приходит в кодировке punycode. В конфиге сервера его пишут в этом виде, а не буквами.

Статика на старом домене продолжает отдаваться.

nginx отдаёт существующие файлы сам, не заглядывая в правила приложения. Для статики правило нужно в самом nginx.

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

На каком уровне ставить редирект?

Постоянный редирект целого домена - в nginx: он отрабатывает первым и не тратит PHP. Точечные правила по отдельным адресам удобнее вести в платформе: их видно в админке и они переживают перенос сервера.

Чем 301 отличается от 302 при смене домена?

Первый говорит поисковику, что переезд постоянный, и вес страницы передаётся новому адресу. Второй означает временный переезд, и старый адрес остаётся в индексе.

Как перенаправить с IP-адреса на домен?

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

Нужно ли что-то делать со ссылками внутри контента?

Абсолютные ссылки на старый домен стоит переписать: редирект их подхватит, но каждая даёт лишний переход. Ищут прямым запросом по таблицам контента.

Смежное

Первоисточник