
У меня в nginx.conf есть следующее:
location ~* /collections.*?products/([^/]+)/?$ {
rewrite ^/collections.*?products/([^/]+)/?$ /$1.html;
rewrite ^([^_]*)_([^_]*)_(.*)$ $1-$2-$3;
rewrite ^([^_]*)_(.*)$ $1-$2 permanent;
}
Чтобы переписать такие запросы, как
"/collections/products/someproduct/" to "/someproduct.html"
"/collections/products/some_product/" to "/some-product.html"
"/collections/products/some_other_product/" to "/some-other-product.html"
Однако я могу получить перенаправление 301 только в том случае, если последняя директива перезаписи (содержащая флаг permanent
) совпадает и обрабатывается, например, мой 2-й пример. В других 2 случаях я получаю временное перенаправление 302. Как мне обработать эти несколько директив перезаписи в этом блоке расположения и вернуть перенаправление 301 независимо от того, какие из них совпадают? Если я поставлю постоянный флаг на все директивы перезаписи, обработка прекратится после первого совпадения.
решение1
Вы можете преобразовать _
в -
рекурсивно и независимо от rewrite...permanent
.
Например:
location ~* /collections.*?products/([^/]+)/?$ {
rewrite ^(.*)_(.*)$ $1-$2 last;
rewrite ^/collections.*?products/([^/]+)/?$ /$1.html permanent;
}
Второй rewrite
выполняется только после того, как первый rewrite
не может найти больше ни одного подчеркивания. Смотретьэтот документдля большего.
решение2
Вы можете рассматривать 302
код состояния как «исключение» и «перехватывать» его с помощьюhttp://nginx.org/r/error_page.
location ~* /collections.*?products/([^/]+)/?$ {
rewrite ^/collections.*?products/([^/]+)/?$ /$1.html;
rewrite ^([^_]*)_([^_]*)_(.*)$ $1-$2-$3;
rewrite ^([^_]*)_(.*)$ $1-$2 permanent;
error_page 302 =301 @302to301;
}
location @302to301 {
return 300; # 300 is just a filler here, error_page dictates status code
#return 301 $sent_http_location;
}
Техника похожа на мою301-302-перенаправление-w-no-http-body-text.nginx.conf, согласносвязанный вопрос о создании перенаправлений 301/302 без тела ответа HTTP.
Обратите внимание, что внутри @302to301
у вас есть выбор между двумя операторами возврата, указанными выше; однако return
код не имеет значения в контексте этого обработчика, поскольку error_page
указанная выше директива гарантирует, что все 302
коды будут изменены 301
независимо от того, какой будет последующий код.
Другими словами, единственной разницей между двумя return
приведенными выше утверждениями будет содержимое тела HTTP-ответа, которое ни один браузер в любом случае не отображает для ответов 301, поэтому вы можете использовать более короткую return 300
версию без тела.