Рейтинг:0

Перенаправление Nginx на основе строки запроса

флаг in

Я переношу старые ссылки на новый сайт, он будет использовать тот же домен

Вот несколько старых ссылок.

Старые ссылки Новые ссылки
http://example.com/?p=contact /контакт
http://example.com/?p=static&id=career /карьера
http://example.com/?p=static&id=about
http://example.com/?p=catalog&action=images&cat_id=1 /категория продукта/категория-слаг-1
http://example.com/?p=catalog&action=images&cat_id=2 /продукт-категория/категория-слаг-2
http://example.com/?p=catalog&action=viewimages&pid=1&cat_id=1 /продукт/продукт-слаг-1
http://example.com/?p=catalog&action=viewimages&pid=2&cat_id=3 /продукт/продукт-слаг-2

У новой страницы продукта нет идентификатора в URL-адресе, поэтому я перечисляю их все вручную, и всего 5 категорий и 20 страниц продуктов.

Это то, что я пробовал, прежде чем узнал, что вложенные if не поддерживаются.

место расположения / {
    если ($arg_p = контакт) {возврат 301/контакт; }
    если ($arg_p = статический) { 
        если ($arg_id = карьера) { return 301 /career; }
        # другие статические страницы перенаправляются на /about
        возврат 301 /об;
    }

    если ($arg_p = каталог) {
        если ($arg_action = изображения) {
            если ($arg_cat_id = 1) { return 301 /product-category/category-slug-1; }
            если ($arg_cat_id = 2) { return 301 /product-category/category-slug-2; }
            # другие неуказанные категории должны перенаправляться на /product-categories
            вернуть 301 /категории товаров;
        }
        если ($arg_action = просмотр изображений) {
            если ($arg_pid = 1) { return 301 /product/product-slug-1/; }
            если ($arg_pid = 2) { return 301 /product/product-slug-2/; }
        }
        # другие незарегистрированные ссылки по умолчанию /products
        возврат 301 /продукты;
    }
}

Какой конфиг должен быть?

Рейтинг:2
флаг gr

Вы можете сделать это с несколькими цепочками карта блоки. Вот идея:

карта $arg_p $url_p {
    контакт /контакт;
    статический $url_id;
    каталог $url_action;
    # значением по умолчанию будет пустая строка
}

карта $arg_id $url_id {
    карьера /карьера;
    о /о;
    # другие статические страницы перенаправляются на /about
    по умолчанию /о;
}

карта $arg_action $url_action {
    изображения $url_cat_id;
    просмотр изображений $url_pid;
    # другие незарегистрированные действия по умолчанию /products
    по умолчанию /продукты;
}

карта $arg_cat_id $url_cat_id {
    1 /категория-продукта/категория-слаг-1;
    2 /категория-продукта/категория-слаг-2;
    # другие неуказанные категории должны перенаправляться на /product-categories
    по умолчанию /категории товаров;
}

карта $arg_pid $url_pid {
    1 /продукт/продукт-слаг-1;
    2 /продукт/продукт-слаг-2;
    # другие товары, не включенные в список, по умолчанию /products
    по умолчанию /продукты;
}

сервер {
    Слушать ...
    имя сервера ...
    ...
    if ($url_p) { # если переменная '$url_p' не является пустой строкой
        вернуть 301 $url_p;
    }
    место расположения / {
        ...
    }
    ...
}

Некоторый карта блоки можно укоротить, например, предположим, что у вас есть 3 статические страницы /карьера, /клиенты и страница "по умолчанию" , 5 категорий и 45 товаров:

карта $arg_id $url_id {
    ~^(карьера|клиенты)$ /$1;
    по умолчанию /о;
}

карта $arg_cat_id $url_cat_id {
    ~^([1-5])$ /product-category/category-slug-$1;
    по умолчанию /категории товаров;
}

карта $arg_pid $url_pid {
    ~^([1-9]|[1-3]\d|4[0-5])$ /product/product-slug-$1;
    по умолчанию /продукты;
}

Обновлять

ОП заявляет, что он не может использовать карта директива, так как у него нет доступа к полной конфигурации nginx, а только к сервер содержимое блока.В то время как предыдущее решение гораздо более элегантно (и должно быть более эффективным с точки зрения производительности), можно сделать то же самое, используя только если блоки:

если ($arg_p = контакт) {возврат 301/контакт; }

if ($arg_p = static) { set $page static_$arg_id; }
если ($page = static_career) { return 301 /career; }
если ($ страница) { вернуть 301 / о; } # все, что не является 'карьерой', перенаправляется на '/about'

если ($arg_p = каталог) { установить $action $arg_action; }

если ($ действие = изображения) { установить $page category_$arg_cat_id; }
если ($page = category_1) { return 301 /product-category/category-a; }
если ($page = category_2) { return 301 /product-category/category-b; }
# ... другие категории
if ($action = images) { return 301 /product-categories; } # указана неуказанная категория

if ($action = viewimages) { установить $page product_$arg_pid; }
если ($page = product_1) { return 301 /product/product-a; }
если ($page = product_2) { return 301 /product/product-b; }
# ... другие продукты
if ($action = viewimages) { return 301 /products; } # указан не включенный в список продукт

# если вы хотите каким-то особенным образом обработать какое-либо действие, не указанное в списке
# if ($action) { ... } # 'action' аргумент запроса не 'images' или 'viewimages'

Этот фрагмент можно поместить либо в сервер или же место расположения контекст.

флаг in
Я получил `nginx: [emerg] директива "карта" здесь не разрешена`. Нельзя ли использовать карту внутри блока «сервер»? У меня нет доступа для изменения nginx вне блока «сервер».
флаг in
Нашел этот вопрос https://stackoverflow.com/questions/27358804/, поэтому я думаю, что карта для меня не вариант. Можно ли просто переписать (регулярное выражение для старых параметров запроса) (новые ссылки)? Я не очень понимаю в регулярных выражениях.
флаг in
Это хороший способ объединить параметры запроса и сохранить их как переменную.
Рейтинг:1
флаг in

Я остановился на этом решении.

место расположения / {
  если ($arg_p = контакт) {возврат 301/контакт; }
  if ($args ~ p=static&id=career) { return 301 /career; }
  if ($arg_p = static) { return 301 /about; }
  if ($args ~ p=catalog&action=images&cat_id=1) { return 301 /product-category/category-a; }
  if ($args ~ p=catalog&action=images&cat_id=2) { return 301 /product-category/category-b; }
  # и другие cat_id
  if ($args ~ p=catalog&action=viewimages&pid=1&cat_id=1) { return 301 /product/product-a; }
  if ($args ~ p=catalog&action=viewimages&pid=2&cat_id=1) { return 301 /product/product-b; }
  # и другие pid
  если ($arg_p = каталог) { return 301 /products; } #other p=catalog по умолчанию /products
  try_files $uri $uri/ /index.php$is_args$args;
}

Он работает, но не может справиться со случаем, когда порядок параметров запроса не указан ниже, например /?id=career&p=static (id и p меняются местами)

Также cat_id в p=catalog&action=viewimages не используется, но когда я удаляю cat_id из правил, p=catalog&action=viewimages&pid=10 всегда перенаправляет на p=catalog&action=viewimages&pid=1, поэтому мне пришлось поставить cat_id.

Если у кого-то была лучшая идея обработать динамический порядок параметров запроса, не стесняйтесь публиковать в качестве ответа. Я отмечу его как принятый, если он работает.

РЕДАКТИРОВАТЬ: Для параметров запроса динамического порядка и гораздо более чистого, если см. Ответ Ивана Шацкого

Ivan Shatsky avatar
флаг gr
Смотрите обновление к моему ответу.

Ответить или комментировать

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