Примеры редиректов в NGINX

Обновлено Обновлено: Опубликовано Опубликовано:

Настройка перенаправлений

Настройки необходимо вносить в файлах конфигураций виртуальных доменов. В Linux на основе RPM (CentOS, Red Hat), как правило, они расположены в директории /etc/nginx/conf.d/. В Linux на основе Deb (Ubuntu, Debian) — в директории /etc/nginx/sites-enabled/. Во FreeBSD все в одном файле — /usr/local/etc/nginx/nginx.conf.

Саму настройку на перенаправление в NGINX можно прописать несколькими способами.

1. Первый:

rewrite ^ https://$host$request_uri? <флаг>;

$host — имя хоста из запроса, если отсутствует — имя в поле «Host» заголовка, если тоже отсутствует — имя сервера; $request_uri — первоначальный запрос с аргументами (все, что идет после доменного имени).
** где флаги могут быть следующие:

  • permanent — перенаправление с кодом 301.
  • redirect — перенаправить с кодом 302.
  • last — закончить обработку с переходом в новый location.
  • break — закончить обработку и остаться в текущем location.

2. Второй: 

return <код> https://$host$request_uri;

* где коды могут использоваться любые, но чаще всего — 301, 302, 404.

Есть различные мнения, какой из методов лучше и безопаснее, поэтому каким воспользоваться — решать по ситуации. В данных примерах используются оба варианта.

После внесения изменений, необходимо проверить их корректность:

nginx -t

И для их применения перезапустить веб-сервер:

systemctl restart nginx

service nginx restart

* в первом примере перезапуск выполняется на новых системах Linux. Второй пример — на устаревших или FreeBSD.

Проверяя редиректы в браузере, следует учесть, что настройки могут кэшироваться. Для обновления кэша используйте комбинацию Ctrl + F5. Если и это не помогает, закрывайте вкладку и открывайте новую.

С HTTP на HTTPS (другой порт)

Пример конфигурации для перенаправления запросов на другой порт — с 80 (http) на 443 (https):

server {
        listen 80;
        server_name domain.ru www.domain.ru;
        return 301 https://$host$request_uri;
}

* в данном примере для всех обращений к сайту domain.ru по 80 порту (http) будет работать редирект на 443 порт (https) с кодом 301 (для склеивания доменов).

С одного домена на другой

server {
        ...
        server_name domain1.ru;
        return 302 http://domain2.ru$request_uri;
}

C домена без www на домен с www

server {
        ...
        server_name domain.ru;
        return 301 http://www.$host$request_uri;
}

С www на без www

server {
        ...
        server_name "~^www\.(.*)$" ;
        return 301 $scheme://$1$request_uri;
}

C index.php на / (корень)

Данная настройка позволит перевести все запросы с /index.php на корневой адрес /:

server {
        ...
        if ($request_uri ~ "^(.*)index\.(?:php|html)") {
                return 301 $1;
        }
}

Перенаправление запросов для отсутствующих доменов (перенаправление по умолчанию)

Если обращение к веб-серверу идет по IP-адресу или домену, который не прописан в конфигурационном файле, можно перенаправить весь трафик на домен по умолчанию:

server {
        listen 80 default_server;
        return 302 https://welcome.domain.ru$request_uri;
}

или независимо от протокола:

server {
        listen 80 default_server;
        return 302 $scheme://welcome.domain.ru$request_uri;
}

server {
        listen 443 default_server;
        return 302 $scheme://welcome.domain.ru$request_uri;

        ssl on;
        ssl_certificate /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/cert.key;
}

$scheme позволяет перевести запрос на тот же протокол (http или https), по которому он был инициирован.
* если nginx должен слушать и обрабатывать запросы по https, необходимо указывать в настройках пути к сертификатам.

С IP-адреса на домен

В данном случае мы переводим все запросы по IP-адресу на конкретный домен:

server {
        listen 80;
        server_name 192.168.1.15;
        return 301 http://site.ru$request_uri;
}

* при отправке http-запроса на сервер 192.168.1.15 по IP-адресу, он будет переведен на домен site.ru.

Редирект домена и всех его поддоменов

server {
        ...
        server_name  domain domain.*;
        return 301 https://$host$request_uri;
}

На другой файл

Это скорее не перенаправление, а алиас или rewrite. Позволяет по запросу одного из файлов, отдать другой:

server {
        ...
        location = /robots.txt {
            rewrite ^/robots.txt$ /robots2.txt;
        }
}

* в данном примере по запросу robots.txt, сервер отдаст содержимое robots2.txt.

Часть url на другой сервер

Перенаправить запрос на другой сервер при обращении по url page1:

server {
        ...
        server_name  domain1.ru;
        location  ~ ^/page1/(.*)$ {
            return 301 $scheme://domain2.ru/$1;
        }
}

* в данном примере для всех запросов, начинающихся на /page1/... будет работать перенаправление на другой домен domain2.ru.

Редирект со слешем

1. Убрать слеш в конце url

а) с помощью rewrite:

server {
        ...
        rewrite ^/(.*)/$ /$1 permanent;
}

б) с помощью return:

server {
        ...
        if ($request_uri ~ "^(.*)/$") {
            return 301 /$1;
        }
}

2. Добавить слеш в конце url

а) с помощью rewrite:

server {
        ...
        rewrite ^(.*[^/])$ $1/ permanent;
}

б) с помощью return:

server {
        ...
        if ($request_uri ~ "^(.*)[^/]$") {
            return 301 $1/;
        }
}

На другую страницу

Нам может понадобиться перенаправлять запросы с одной страницы сайта на другую. Приведем примеры, как это сделать с помощью return и rewrite.

а) с помощью rewrite:

server {
        ...
        rewrite ^/page1$ /page2 permanent;
}

б) с помощью return:

server {
        ...
        location = /page1 {
            return 301 /page2;
        }
}

Удалить часть URL

Иногда нужно удалять часть url. Это можно сделать следующими способами:

server {
        ...
        rewrite /deleted-url/(.*) /$1 permanent;
}

или:

server {
        ...
        if ($request_uri ~ "/deleted-url/(.*)") {
                return 301 $1;
        }
}

* в данном примере из url мы удалим deleted-url/.

Перенаправить запрос в случае обращения к несуществующим файлам

Предположим, что нам нужно обращаться к скриптам на сервере, но без прописывания в URL .php на конце. Запрос будет выглядеть, примерно, http://url/. Чтобы nginx перекинул запрос на url.php вставляем следующее:

server {
        ...
        if (!-e $request_filename){
                rewrite ^(.*)$ /$1.php;
        }
}

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

Проксирование

Проксирование, в отличие от редиректа, не передает инструкции браузеру перейти на другой url — NGINX сам выполняет http-запрос по другому адресу и возвращает готовый ответ. Эта возможность может применяться для внутреннего распределения серверных ресурсов.

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

1. На другой сервер

Пример внутреннего перенаправления http-запроса на другой веб-сервер:

...
location / {
            proxy_pass $scheme://192.168.0.15:8080/;
            proxy_redirect     off;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
}

* в данном случае, принимать запросы от браузера и отвечать на них будет NGINX, а сама обработка будет выполняться на сервере с IP-адресом 192.168.0.15 на порту 8080.

Использование NGINX в качестве http-прокси:

server {
        ...
        server_name site1.ru www.site1.ru;
        location / {
            proxy_pass http://192.168.1.21/;
            proxy_redirect     off;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
}

server {
        ...
        server_name site2.ru www.site2.ru;
        location / {
            proxy_pass http://192.168.1.22/;
            proxy_redirect     off;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
}

* в данном примере запросы на site1.ru будут перекинуты на сервер 192.168.1.21, а запросы на site2.ru — 192.168.1.22.

HTTP proxy с авторизацией (если удаленный веб-сервер требует аутентификации):

server {
    ...
    location / {
        proxy_pass http://10.10.10.10/page/;
        proxy_set_header Authorization "Basic dGVzdDp0ZXN0";
        ...
    }
}

* где 10.10.10.10/page — страница, на которую будут перекинуты запросы; dGVzdDp0ZXN0 — логин:пароль test:test, закодированные в формате base64.

2. Часть url на другой сервер

Выше мы рассмотрели пример перенаправления запроса по части веб-адреса. По схожему сценарию мы можем делать проксирование:

server {
    ...
    location  ~ ^/page1/(.*)$ {
        proxy_pass   $scheme://10.10.10.10/$1;
    }
}

* и так, в данном примере при обращении по адресу site.ru/page1/<что-то еще>, nginx сделает внутренний запрос на сервер 10.10.10.10 по адресу 10.10.10.10/<что-то еще> и вернет готовый ответ.

3. На другой сайт

Мы можем сделать так, что при переходе по одному адресу у нас будет открываться совершенно другой сайт:

server {
    ...
    location / {
        proxy_pass https://www.dmosk.ru;
        proxy_set_header   Host             www.dmosk.ru;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}

* в данном случае мы при обращении к нашему серверу будем попадать на сайт https://www.dmosk.ru. Обратите внимание, что в proxy_set_header мы передаем хосту его имя — в противном случае, как правило, другой сервер вернет ошибку. Также мы не указываем proxy_redirect, иначе, nginx будет переводить запросы на реальный сайт (отправлять инструкции браузеру перейти на него), а не тот, что мы используем за http-прокси.

Немного о 301 и 302

В чем принципиальная разница между ответом с кодом 301 и 302? Для обычного посетителя сайта разницы нет. А вот для поискового робота разница огромная.

301-й редирект говорит о склеивании страниц. Это означает для поисковика то, что старая и новая страницы — это одно и то же. Таким образом, результаты ранжирования необходимо сохранить для новой страницы.

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

# Серверы # Интернет # UNIX # NGINX
Дмитрий Моск — частный мастер
Была ли полезна вам эта инструкция?

Да            Нет