Руководство по настройке редиректов в Nginx
Содержание
Nginx — один из самых распространённых веб-серверов, и настройка перенаправлений — рутинная часть работы с ним. Два основных инструмента — return и rewrite — часто путают, что приводит к неэффективным или нерабочим конфигурациям.
return vs rewrite
return (рекомендуется)
return 301 https://example.com;
- ✅ Быстро — отправляет HTTP-ответ напрямую, без движка регулярных выражений
- ✅ Простой синтаксис, сложно ошибиться
- ✅ Официальная рекомендация для большинства случаев перенаправления
- ❌ Не может захватывать и переиспользовать сегменты URL
rewrite (мощный, но медленнее)
rewrite ^/old-path/(.*)$ /new-path/$1 permanent;
- ✅ Поддерживает группы захвата регулярных выражений
- ✅ Может трансформировать структуру URL
- ❌ Медленнее, чем
return - ❌ Сложный синтаксис, легко создать бесконечный цикл
💡 Правило
Используйте return везде, где возможно. Прибегайте к rewrite только когда нужны группы захвата regex или сложная трансформация URL.
Базовые примеры
301 постоянный редирект
server {
listen 80;
server_name old-domain.com;
return 301 https://new-domain.com$request_uri;
}
302 временный редирект
server {
listen 80;
server_name example.com;
location /maintenance {
return 302 /maintenance.html;
}
}
Перенаправление одной страницы
location = /old-page.html {
return 301 /new-page.html;
}
HTTP на HTTPS
Рекомендуется: отдельные блоки server
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# конфигурация сайта...
}
⚠️ Избегайте директивы if
В сообществе Nginx есть поговорка: «if — это зло». Директива if может вызвать непредсказуемое поведение в определённых контекстах. Используйте отдельные блоки server для HTTPS-перенаправлений.
Канонизация www
без www → www
server {
listen 80;
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
return 301 https://www.example.com$request_uri;
}
www → без www
server {
listen 80;
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
return 301 https://example.com$request_uri;
}
Перенаправление путей
# Перенаправление каталога с удалением префикса
location /blog/ {
rewrite ^/blog/(.*)$ /articles/$1 permanent;
}
# Массовые перенаправления с map (эффективно для больших списков)
map $uri $new_uri {
/old-page-1 /new-page-1;
/old-page-2 /new-page-2;
}
server {
if ($new_uri) { return 301 $new_uri; }
}
Regex-перенаправления
# Удаление расширения .html
location ~ ^(.+)\.html$ {
return 301 $1;
}
# Удаление префикса с датой из URL
location ~ ^/\d{4}/\d{2}/\d{2}/(.+)$ {
return 301 /$1;
}
Типичные ошибки
1. Цикл rewrite
# ❌ Бесконечный цикл
location /old/ {
rewrite ^/old/(.*)$ /new/$1;
}
# ✅ Используйте флаг permanent или return
location /old/ {
return 301 /new$request_uri;
}
2. Потеря строки запроса
# ❌ Строка запроса потеряна
location /old { return 301 /new; }
# ✅ Сохранение строки запроса
location /old { return 301 /new$is_args$args; }
3. Отсутствие SSL-конфигурации для HTTPS
Если вы перенаправляете HTTP → HTTPS, но не настроили блок HTTPS-сервера с валидным сертификатом, пользователи получат ошибку соединения. Всегда проверяйте, что блок HTTPS существует и сертификат действителен, прежде чем включать перенаправление.
Советы по производительности
- Предпочитайте
returnвместоrewrite— нет накладных расходов на движок regex - Сокращайте цепочки перенаправлений: перенаправляйте напрямую с A на C, а не A → B → C
- Используйте
mapдля больших таблиц перенаправлений — вычисляется при загрузке конфигурации, а не при каждом запросе - Избегайте ненужных regex в блоках
location; используйте префиксные или точные совпадения, где возможно - Всегда запускайте
nginx -tпосле изменений, чтобы обнаружить синтаксические ошибки до перезагрузки
После настройки перенаправлений проверьте их с помощью 301check.com.