Redirecionamento Nginx baseado na string de consulta

Redirecionamento Nginx baseado na string de consulta

Estou migrando links de sites antigos para um novo site, ele usará o mesmo domínio

Aqui estão alguns links antigos.

Links antigos Novos links
http://example.com/?p=contact /contato
http://example.com/?p=static&id=career /carreira
http://example.com/?p=static&id=about /sobre
http://example.com/?p=catalog&action=images&cat_id=1 /categoria-produto/categoria-slug-1
http://example.com/?p=catalog&action=images&cat_id=2 /categoria-produto/categoria-slug-2
http://example.com/?p=catalog&action=viewimages&pid=1&cat_id=1 /produto/produto-slug-1
http://example.com/?p=catalog&action=viewimages&pid=2&cat_id=3 /produto/produto-slug-2

A nova página do produto não tem id na URL, então listo todas elas manualmente, e são apenas 5 categorias e 20 páginas de produtos no total.

Isso é o que eu tentei antes de saber que aninhado if não é compatível.

location / {
    if ($arg_p = contact) { return 301 /contact; }
    if ($arg_p = static) { 
        if ($arg_id = career) { return 301 /career; }
        # other static pages redirect to /about
        return 301 /about;
    }

    if ($arg_p = catalog) {
        if ($arg_action = images) {
            if ($arg_cat_id = 1) { return 301 /product-category/category-slug-1; }
            if ($arg_cat_id = 2) { return 301 /product-category/category-slug-2; }
            # other unlisted categories should redirect to /product-categories
            return 301 /product-categories;
        }
        if ($arg_action = viewimages) {
            if ($arg_pid = 1) { return 301 /product/product-slug-1/; }
            if ($arg_pid = 2) { return 301 /product/product-slug-2/; }
        }
        # other unlisted links defaults to /products
        return 301 /products;
    }
}

Qual deve ser a configuração?

Responder1

Você pode fazer isso com vários encadeadosmapblocos. Aqui está uma ideia:

map $arg_p $url_p {
    contact    /contact;
    static     $url_id;
    catalog    $url_action;
    # default value will be an empty string
}

map $arg_id $url_id {
    career     /career;
    about      /about;
    # other static pages redirect to /about
    default    /about;
}

map $arg_action $url_action {
    images     $url_cat_id;
    viewimages $url_pid;
    # other unlisted actions defaults to /products
    default    /products;
}

map $arg_cat_id $url_cat_id {
    1          /product-category/category-slug-1;
    2          /product-category/category-slug-2;
    # other unlisted categories should redirect to /product-categories
    default    /product-categories;
}

map $arg_pid $url_pid {
    1          /product/product-slug-1;
    2          /product/product-slug-2;
    # other unlisted products defaults to /products
    default    /products;
}

server {
    listen ...
    server_name ...
    ...
    if ($url_p) { # if '$url_p' variable is not an empty string
        return 301 $url_p;
    }
    location / {
        ...
    }
    ...
}

Alguns mapblocos podem ser encurtados, por exemplo, vamos supor que você tenha 3 páginas estáticas /careere /clientsuma página "default" /about, 5 categorias e 45 produtos:

map $arg_id $url_id {
    ~^(career|clients)$        /$1;
    default                    /about;
}

map $arg_cat_id $url_cat_id {
    ~^([1-5])$                 /product-category/category-slug-$1;
    default                    /product-categories;
}

map $arg_pid $url_pid {
    ~^([1-9]|[1-3]\d|4[0-5])$  /product/product-slug-$1;
    default                    /products;
}

Atualizar

OP afirma que não pode usar mapa diretiva, pois não tem acesso à configuração completa do nginx, mas apenas para serverbloquear conteúdo. Embora a solução anterior seja muito mais elegante (e deva ser mais eficaz em termos de desempenho), é possível fazer o mesmo usando apenas ifblocos:

if ($arg_p = contact) { return 301 /contact; }

if ($arg_p = static) { set $page static_$arg_id; }
if ($page = static_career) { return 301 /career; }
if ($page) { return 301 /about; } # anything that is not 'career' redirected to '/about'

if ($arg_p = catalog) { set $action $arg_action; }

if ($action = images) { set $page category_$arg_cat_id; }
if ($page = category_1) { return 301 /product-category/category-a; }
if ($page = category_2) { return 301 /product-category/category-b; }
# ... other categories
if ($action = images) { return 301 /product-categories; } # unlisted category specified

if ($action = viewimages) { set $page product_$arg_pid; }
if ($page = product_1) { return 301 /product/product-a; }
if ($page = product_2) { return 301 /product/product-b; }
# ... other products
if ($action = viewimages) { return 301 /products; } # unlisted product specified

# if you want to process any unlisted action in some special way
# if ($action) { ... } # 'action' query argument neither 'images' nor 'viewimages'

Este fragmento pode ser colocado em serverou locationcontexto.

Responder2

Acabei com esta solução.

location / {
  if ($arg_p = contact) { return 301 /contact; }
  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; }
  # and other 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; }
  # and other pid
  if ($arg_p = catalog) { return 301 /products; } #other p=catalog defaults to /products
  try_files $uri $uri/ /index.php$is_args$args;
}

Está funcionando, mas não consegue lidar com o caso quando a ordem dos parâmetros de consulta não está escrita abaixo, por exemplo /?id=career&p=static(id e p são trocados)

Também cat_idin p=catalog&action=viewimagesnão é usado, mas quando retiro o cat_iddas regras, p=catalog&action=viewimages&pid=10sempre redireciona para p=catalog&action=viewimages&pid=1, então tive que colocar o cat_id.

Se alguém tiver uma ideia melhor de como lidar com a ordem dinâmica dos parâmetros de consulta, fique à vontade para postar como resposta. Vou marcá-lo como aceito se funcionar.

EDIT: Para parâmetros de consulta de ordem dinâmica e muito mais limpo se, consulteA resposta de Ivan Shatsky

informação relacionada