Назад | Перейти на главную страницу

Как отлаживать большую цепочку редиректов в nginx. Неожиданное перенаправление

У меня сейчас задача сделать большую миграцию сайта. И у меня в config большое количество редиректов. Но я не могу понять, почему одно перенаправление вызывает второе перенаправление в цепочке. Даже если любые другие редиректы прокомментированы / отключены.

Итак, моя конфигурация для местоположения:

server {

...
index index.php;

location / {
    try_files $uri $uri/ /index.php?$query_string;
}
location ~* /index.php {
    if ($args ~ "^page=flights&start_city=([\+\w\d\s]*)(&.*)?$"){
        return 301 $scheme://$server_name/flights?departure_city=$arg_start_city;
    }
    if ($is_args){
        return 301 $scheme://$server_name/$1;
    }

    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
}

Чего я жду? Я ожидаю, что старые ссылки вроде

https://example.com/index.php?page=flights&start_city=Berlin&s_loc_lat=&s_loc_long=

Становиться:

https://example.com/flights?departure_city=Berlin

И при этом ссылки вроде:

https://example.com/index.php?someoldpar=someoldkey&someoldpar2=someoldkey2

Становиться:

    https://example.com/

Что я получил при тестировании этого конфига?

. Я получил эту цепочку перенаправления для первой ссылки:

 1. GET https://example.com/index.php?page=flights&start_city=Berlin&s_loc_lat=&s_loc_long=
 2. 301 https://example.com/flights?departure_city=Berlin
 3. 301 https://example.com/

Как исключить шаг 3 для уже перенаправленных ссылок? Лаварел под бэкэндом.

Ваш try_files оператор перезаписывает URI на /index.php и добавляет строку запроса. Ваш if ($is_args) оператор перенаправляет любой URI со строкой запроса. У вас есть петля перенаправления.

В location ~* /index.php блок не может отличить исходный запрос, содержащий index.php и результат try_files дефолт.

Вы должны выполнить свои тесты на $request_uri переменная, которая всегда будет содержать исходный запрос вместе со строкой запроса. Вы можете использовать if или map. С более чем несколькими регулярными выражениями map является предпочтительным решением.

Например:

map $request_uri $redirect {
    default 0;
    ~^/index.php\?page=flights&start_city=(?<startcity>[\+\w\d\s]*)(&.*)?$ /flights?departure_city=$startcity;
    ~^/index.php\?                                                         /;
}

server {
    ...
    if ($redirect) {
        return 301 $redirect;
    }

Вы можете удалить свой location ~* /index.php блок, так как он больше не требуется. Регулярные выражения оцениваются по порядку до тех пор, пока не будет найдено правило сопоставления, поэтому упорядочивайте правила, начиная с наиболее конкретных и наименее конкретных последних. Используйте именованные захваты, так как числовые захваты могут выйти за пределы области видимости. Вам не нужно указывать схему или доменное имя, если они совпадают. В map директива находится за пределами блока server. Видеть этот документ для подробностей.