쿼리 문자열을 기반으로 하는 Nginx 리디렉션

쿼리 문자열을 기반으로 하는 Nginx 리디렉션

이전 웹사이트 링크를 새 웹사이트로 마이그레이션하고 있는데 동일한 도메인을 사용하게 됩니다.

다음은 오래된 링크입니다.

오래된 링크 새로운 링크
http://example.com/?p=연락처 /연락하다
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에 ID가 없어서 수동으로 모두 나열했는데 카테고리가 총 5개, 상품 페이지가 20개에 불과합니다.

이것이 중첩된 if가 지원되지 않는다는 것을 알기 전에 시도한 것입니다.

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

구성은 어떻게 되어야 합니까?

답변1

여러개 연결해서 하면 됩니다map블록. 다음은 아이디어입니다.

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

일부 블록은 단축될 수 있습니다. 예를 들어 3개의 정적 페이지 , "기본" 페이지 , 5개의 카테고리 및 45개의 제품이 map있다고 가정합니다 ./career/clients/about

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

업데이트

OP는 전체 nginx 구성에 대한 액세스 권한이 없고 블록 콘텐츠 map에만 액세스할 수 있으므로 지시문을 사용할 수 없다고 말합니다 . server이전 솔루션이 훨씬 더 우아하지만(성능 측면에서 더 효과적이어야 함) if블록만 사용하여 동일한 작업을 수행하는 것도 가능합니다.

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'

이 조각은 또는 컨텍스트에 배치될 수 server있습니다 location.

답변2

나는이 솔루션으로 끝났습니다.

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

작동하지만 쿼리 매개변수 순서가 아래에 기록되지 않은 경우 /?id=career&p=static(예: id와 p가 전환됨) 를 처리할 수 없습니다.

또한 cat_idin은 사용되지 않지만 규칙에서 p=catalog&action=viewimagesthe를 제거하면 항상 로 리디렉션되므로 를 넣어야 했습니다 .cat_idp=catalog&action=viewimages&pid=10p=catalog&action=viewimages&pid=1cat_id

누군가 쿼리 매개변수의 동적 순서를 처리하는 더 나은 아이디어가 있다면 자유롭게 답변을 게시해 주세요. 작동하면 승인된 것으로 표시하겠습니다.

편집: 동적 주문 쿼리 매개변수 및 훨씬 더 깔끔한 내용은 다음을 참조하세요.Ivan Shatsky의 답변

관련 정보