nginx-各种奇怪的rewrite需求

此文档记录鄙人在生产环境中遇到的一些rewrite需求。常规的一些rewrite需求可能分分钟就配好了,但有些复杂的需求最长的花了4个小时去研究。为了避免这种屡战屡败的现象发生,故记录文档,缩短耗时。

常规需求rewrite

一般rewrite需求都是对于SEO的需求,一些url会以302的状态码跳转,会影响到谷歌排名。需要将url跳转改为301跳转(永久重定向)。所以需要通过nginx来做301rewrite。
例:

rewrite /cn/service/onsite/detail https://support.oppo.com/cn/onsite-repair/ permanent;

不需要正则匹配的情况

带参数的url-rewrite后-保留参数

#例:
#https://example.com/cn/show/?q=xxx -->
#https://example.com/cn/getinfo/?q=xxx

if ( $arg_q ) { rewrite /cn/show/ https://example.com/cn/getinfo/ permanent;}

备注:

        判断参数q如果存在。/cn/getinfo/结尾没有带?,所以会把参数附在后面。

带参数的url-rewrite后-去除参数

#​例:
#https://example.com/cn/show/?aid=1234 -->
#https://example.com/cn/getinfo/

if ( $request_uri = "/cn/show/?aid=1234" ) {rewrite (.*) https://example.com/cn/getinfo/? permanent;}

备注:

        nginx的参数$uri获取的uri是不带参数的,可以通过$request_uri获取带参数uri。从而进行if判断。? 去掉转发后的参数。

需要正则匹配的情况

带参数url-rewrite后-参数的key变&value不变

#例:
#https://example.com/cn/show/?q=xxxx --> 
#https://example.com/cn/getinfo/?kw=xxxx
#ps:valu值xxxx是变量,301rewrite后改变key,但是value的值不变。

if ( $arg_q ){ rewrite /cn/show/ https://example.com/cn/getinfo/?kw=$arg_q? permanent;}

带参数url-需要正则匹配参数的value

#例:
#https://example.com/cn/show?city=xxxx (xxxx为1-4位数字) -->
#https://example.com/cn/getinfo/
#ps:需要参数的value满足条件的情况下,301转发到/cn/getinfo/且不保留参数。

if ( $arg_city ~ "[0-9]{1,4}" ) {rewrite /cn/show  https://example.com/cn/getinfo/? permanent;}

备注:
        前面提到,可以通过$request_uri获取带参数的uri从而做if判断。但是在实际配置过程中发现,如果要对参数的value进行正则匹配的话,通过 if ( $request_uri ~ “/cn/service/map?city=正则表达式”)这样的方式无法对uri中参数的value进行正常的匹配。所以上述例子中用到了$arg_parameterName这个nginx内置参数来正则匹配参数的value。

 带多个参数的url rewrite

#例:
#https://example.com/cn/shwo?id=123&name=456&age=20 -->
#https://example.com/cn/getinfo/
#ps:301后去除参数

set $cnshwo "";
if ( $arg_id = 123 ) {
  set $cnshwo "1";
}
if ( $arg_name = %456 ) {
  set $cnshwo "${cnshwo}1";
}
if ( $arg_age = 20 ) {
  set $cnshwo "${cnshwo}1";
}
if ( $help657 = 111 ) {
  rewrite (.*)$ https://example.com/cn/getinfo/? permanent;
}

备注:

        nginx不可以写多重if判断。所以要判断多种情况同时满足时,可以使用一个中间变量作为判断依据。

正则判断非某字段开头或结尾

#规则:不以/cn/.*开头;中间包含html;不以?.*结尾。


if ( $request_uri ~* ^(?!/cn/.*).*.html.*(?<!\?).*$ ) { rewrite /(.*).htm$ https://other-example.com/$1/ permanent; }

备注:

        正则表达式,^(?!str)不以str开头;(?<!str)$不以str结尾。

参考文档

https://segmentfault.com/a/1190000019266662https://segmentfault.com/a/1190000019266662

重定向POST请求

用rewrite重写POST请求的话,重写后的POST请求会变成GET请求,且body中的信息也会丢失。

对于POST请求需要进行307重定向。

if ( $request_uri ~ ^(/.*)/-/protected_branches$ ) {return 307 http://10.10.10.10:80/api?a=$1;}

备注:将uir为/xxxx/-/protected_branches的请求,307重定向到10.10.10.10服务器、80端口、uri=/api;url中query参数a等于匹配到的/xxxx的值。

map优化大量rewrite场景

场景:如果我们有上千条重定向规则需要去配置,且没有办发用正则去减少条目。这样的情况下,为了提高效率,可以使用map去实现。

首先,我们需要先准备map的文件。每行一个重定向,空格分隔并以冒号终止。

文件路径:/var/www/vhosts/acme.com/redirects/redirect.map

格式如下:

/source-url-1 https://acme.com/dest-url-1:
/source-url-2 https://acme.com/dest-url-2:

第二步,再http下配置

map_hash_max_size 4096;
map_hash_bucket_size 256;
map $request_uri $new_uri {
  include /var/www/vhosts/acme.com/redirects/redirect.map
}

第三步,我们在对应的server下或者server的location下,使用map文件获取的路径进行rewrite

if ($new_uri != "") {
	rewrite ^(.*)$ $new_uri permanent;
}

参考文档

Nginx Redirects With Map File Reliable Penguin - BlogClient provided a CSV file with several thousand redirects for site hosted on Plesk server. For maximum efficiency we implemented the redirects using ahttps://blogs.reliablepenguin.com/2021/05/19/nginx-redirects-with-map-file

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值