Redirección de Nginx basada en cadena de consulta

Redirección de Nginx basada en cadena de consulta

Estoy migrando enlaces de sitios web antiguos a un sitio web nuevo; usará el mismo dominio

Aquí hay algunos enlaces antiguos.

Enlaces antiguos Nuevos enlaces
http://ejemplo.com/?p=contacto /contacto
http://ejemplo.com/?p=static&id=carrera /carrera
http://ejemplo.com/?p=static&id=acerca de /acerca de
http://ejemplo.com/?p=catalog&action=images&cat_id=1 /categoría-de-producto/categoría-slug-1
http://ejemplo.com/?p=catalog&action=images&cat_id=2 /categoría-de-producto/categoría-slug-2
http://example.com/?p=catalog&action=viewimages&pid=1&cat_id=1 /producto/producto-slug-1
http://example.com/?p=catalog&action=viewimages&pid=2&cat_id=3 /producto/producto-slug-2

La nueva página del producto no tiene una identificación en la URL, por lo que las enumero todas manualmente y son solo 5 categorías y 20 páginas de productos en total.

Esto es lo que probé antes de saber que el si anidado no es compatible.

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;
    }
}

¿Cuál debería ser la configuración?

Respuesta1

Puedes hacerlo con varios encadenados.mapbloques. Aquí tienes una idea:

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 / {
        ...
    }
    ...
}

Algunos mapbloques se pueden acortar, por ejemplo, supongamos que tiene 3 páginas estáticas /careery /clientsuna página "predeterminada" /about, 5 categorías y 45 productos:

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;
}

Actualizar

OP afirma que no puede usar mapla directiva ya que no tiene acceso a la configuración completa de nginx, sino solo para serverbloquear contenidos. Si bien la solución anterior es mucho más elegante (y debería ser más efectiva en términos de rendimiento), es posible hacer lo mismo usando solo ifbloques:

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 se puede colocar en servero locationcontexto.

Respuesta2

Terminé con esta solución.

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, pero no puede manejar el caso en el que el orden de los parámetros de consulta no está escrito a continuación, por ejemplo /?id=career&p=static(id y p se intercambian)

Además , no cat_idse p=catalog&action=viewimagesusa, pero cuando elimino el cat_idde las reglas, p=catalog&action=viewimages&pid=10siempre redirige a p=catalog&action=viewimages&pid=1, así que tuve que poner el archivo cat_id.

Si alguien tiene una mejor idea para manejar el orden dinámico de los parámetros de consulta, no dude en publicarlo como respuesta. Lo marcaré como aceptado si funciona.

EDITAR: Para parámetros de consulta de pedidos dinámicos y mucho más limpios, consulteLa respuesta de Ivan Shatsky

información relacionada