前言与需求

自动电商平台归属了大数据研究院之后,我又恢复了那个“把nginx当成爸爸”的日子。开发不断地提出了的要求,我一样一样的疲命应付,并且在应付后记录下来,就怕以后再遇到类似的问题。

这次的需求是一个跳转,满足某个条件之后把“http://dvlshop.lechange.com/index.php/wap/?client_id=lc_mall_m&redirect_uri=https%3A%2F%2Fdvlshop.lechange.com%2Fopenapi%2Ftrustlogin_api%2Fparse%2Fwap_trustlogin_lecheng%2Fcallback&response_type=code&scope=read&state=http%3A%2F%2Fdvlshop.lechange.com%2Findex.php%2Fwap&user=token%2Flcid_9f9lmo2u6i7hkl6t6eaodn2blmg5jbsg&expire=1514191636&source_type=lc_app&nonce=cdizHO6uvSx5JK79Kmtz5RBpSi0ROhpF&signature=VeCceYCWDE6BZjIdni/68YCmhqc=%27 ”
改成
“http://dvlshop.lechange.com/index.php/wap/?client_id=lc_mall_m&redirect_uri=https%3A%2F%2Fdvlshop.lechange.com%2Fopenapi%2Ftrustlogin_api%2Fparse%2Fwap_trustlogin_lecheng%2Fcallback&=code&scope=read&state=http%3A%2F%2Fdvlshop.lechange.com%2Findex.php%2Fwap&user=token%2Flcid_9f9lmo2u6i7hkl6t6eaodn2blmg5jbsg&expire=1514191636&source_type=lc_app&nonce=cdizHO6uvSx5JK79Kmtz5RBpSi0ROhpF&signature=VeCceYCWDE6BZjIdni/68YCmhqc=%27”

具体条件是:

  1. 先判断是否有source_type=lc_app;
  2. 再判断是否有response_type;
  3. 如果以上两个都满足,将“response_type”改成“+auto+”;

各位看官,我理解你们此时不想继续看下去的心情,其实我当初看着那么一大坨uri心里也直犯闹,但是没办法,“食君之禄,分君之忧”,我只能耐着性子一个一个的拆开,还别说,拆开的话就清晰许多了,如下:
http://dvlshop.lechange.com/index.php/wap/?
client_id=lc_mall_m&
redirect_uri=https%3A%2F%2Fdvlshop.lechange.com%2Fopenapi%2Ftrustlogin_api%2Fparse%2Fwap_trustlogin_lecheng%2Fcallback&
response_type=code& #满足条件的话把这个改成+auto+
scope=read&
state=http%3A%2F%2Fdvlshop.lechange.com%2Findex.php%2Fwap&
user=token%2Flcid_9f9lmo2u6i7hkl6t6eaodn2blmg5jbsg&
expire=1514191636&
source_type=lc_app&
nonce=cdizHO6uvSx5JK79Kmtz5RBpSi0ROhpF&signature=VeCceYCWDE6BZjIdni/68YCmhqc=%27

开始操作

针对这次需求我的计划是这样的:把原地址看成"$1+ response_type +$2"这样的一个样式,确定$1和$2,然后rewrite成"$1+ +auto+ +$2"不就搞定了么? 于是乎我就凭着我那二把刀的nginx技术开始动手。折腾了大约半个小时,拿出来这样一个配置:

    location ~ .*\.php.*
    {
        include php_fcgi.conf;
        include pathinfo.conf;
        set $flag "0";
        if ( $request_uri ~ "source_type=lc_app" ) {
           set $flag  "1";
        }
        if ( $request_uri ~ "(.*)response_type(.*)" ){
           set $Flag  "$flag$flag";
           set $id $1;
           set $query $2;
        }
        if ($Flag = "11"){  #注意这个地方是11
            set $flag "0";
              rewrite ^.*$ http://dvlshop.lechange.com/index.php/wap/$id$query last;    #前面那一段是写死的
            }
        }

但是很不幸,nginx -s reload之后的结果是“$1+$2+$1+ response_type +$2”的格式(地址太长太恶心了,我就不写了)。

然后在arstercz大神的指点下,把那句rewrite改成了return 301 http://dvlshop.lechange.com/index.php/wap/?$id$query;。就达到了效果。

原因确定

后来追寻原因,原来是: rewrite后面接的$uri不需要$args,因为$args会被自动带过来。而return的则会丢失$args,需要手动补上$args。而我上面的$1,$2恰巧就是$args,所以用rewrite的话就会重复。举个例子,比如请求"http://localhost/?a=1" 想被 301 到"https://localhost/?a=1?a=1」" ,要么

    server {
        listen 80;
        rewrite / https://$host$uri permanent;
    }

要么就

    server {
        listen 80;
        return 301 https://$host$request_uri;
    }

补充说明

PS,这里补充一下uri、request_uri、document_uri之间的区别:

  • $request_uri: /stat.php?id=1585378&web_id=1585378
  • $uri: /stat.php (不带?后面)
  • $document_uri: /stat.php (与uri完全相同)

最后的最后,如果您觉得本文对您升职加薪有帮助,那么请不吝赞助之手,刷一下下面的二维码,赞助本人继续写更多的博文!
记一次配置rewrite和return的经历_第1张图片