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.map
bloques. 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 map
bloques se pueden acortar, por ejemplo, supongamos que tiene 3 páginas estáticas /career
y /clients
una 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 map
la directiva ya que no tiene acceso a la configuración completa de nginx, sino solo para server
bloquear 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 if
bloques:
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 server
o location
contexto.
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_id
se p=catalog&action=viewimages
usa, pero cuando elimino el cat_id
de las reglas, p=catalog&action=viewimages&pid=10
siempre 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