Nginx-Umleitung basierend auf Abfragezeichenfolge

Nginx-Umleitung basierend auf Abfragezeichenfolge

Ich migriere alte Website-Links auf eine neue Website. Es wird dieselbe Domain verwendet.

Hier sind einige alte Links.

Alte Links Neue Links
http://example.com/?p=contact /Kontakt
http://example.com/?p=static&id=career /Karriere
http://example.com/?p=static&id=about /um
http://example.com/?p=catalog&action=images&cat_id=1 /produktkategorie/kategorie-slug-1
http://example.com/?p=catalog&action=images&cat_id=2 /produktkategorie/kategorie-slug-2
http://example.com/?p=catalog&action=viewimages&pid=1&cat_id=1 /produkt/produkt-slug-1
http://example.com/?p=catalog&action=viewimages&pid=2&cat_id=3 /produkt/produkt-slug-2

Die neue Produktseite hat keine ID in der URL, also liste ich sie alle manuell auf. Es sind insgesamt nur 5 Kategorien und 20 Produktseiten.

Das habe ich versucht, bevor ich wusste, dass verschachteltes „if“ nicht unterstützt wird.

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

Wie sollte die Konfiguration sein?

Antwort1

Sie können es mit mehreren verkettetenmapBlöcke. Hier ist eine Idee:

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

Einige mapBlöcke können gekürzt werden. Nehmen wir zum Beispiel an, Sie haben 3 statische Seiten /career, /clientseine „Standard“-Seite /about, 5 Kategorien und 45 Produkte:

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

Aktualisieren

OP gibt an, dass er die Direktive nicht verwenden kann, mapda er keinen Zugriff auf die vollständige Nginx-Konfiguration hat, sondern nur auf serverBlockinhalte. Während die vorherige Lösung weitaus eleganter ist (und in Bezug auf die Leistung effektiver sein sollte), ist es möglich, dasselbe nur mit ifBlöcken zu tun:

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'

serverDieses Fragment kann entweder in einen beliebigen Kontext eingefügt werden location.

Antwort2

Am Ende bin ich zu dieser Lösung gekommen.

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

Es funktioniert, kann aber den Fall nicht behandeln, wenn die Reihenfolge der Abfrageparameter nicht unten angegeben ist, z. B. /?id=career&p=static(id und p sind vertauscht)

Außerdem wird cat_idin p=catalog&action=viewimagesnicht verwendet, aber wenn ich das cat_idaus den Regeln entferne, p=catalog&action=viewimages&pid=10erfolgt immer eine Weiterleitung zu p=catalog&action=viewimages&pid=1, also musste ich das einfügen cat_id.

Wenn jemand eine bessere Idee zur Handhabung der dynamischen Reihenfolge der Abfrageparameter hat, kann er diese gerne als Antwort posten. Ich werde es als akzeptiert markieren, wenn es funktioniert.

EDIT: Für dynamische Bestellabfrageparameter und viel saubereres if sieheIvan Shatskys Antwort

verwandte Informationen