当前位置:C++技术网 > 资讯 > 一步步升级优化nginx服务器rewrite配置url地址重写

一步步升级优化nginx服务器rewrite配置url地址重写

更新时间:2017-11-04 12:11:27浏览次数:1+次

    今天要研究一个nginx地址转发配置。要实现的效果就是,多个地址转发到一个地址,但是带有不同的参数。地址转发有很多方法,nginx专业的叫法是地址重写和地址转发。
    下面说一下地址重写和地址转发的区别:
浏览器地址:地址重写时地址变成新的地址,地址转发则地址保持不变。
请求次数:地址重写有两次网络请求,地址转发则只会产生一次网络请求。
应用场景:地址重写可以重写到任何地址,地址转发一般发生在同一个站点内部。
url区别:地址重写必须使用完整的路径,如http://www.cjjjs.com/index.html。而地址转发相对于站内地址,可以写成/index.html,当然写全路径也不会错。
请求属性:地址转发过程中,可以将客户端请求的request范围内的属性传递给新的页面,但地址重写不可以。
速度:地址转发的速度比地址重写的速度快。
    整体梳理一下。
    地址重写的过程是:浏览器向服务器请求了一个地址,然后服务器将这个地址换成一个新地址,浏览器再用这个新地址发起一次请求。这个新地址可能是本站的,也有可能是外站的。这样就有了两次请求,所以如果新地址也是本站的,这样效率就低了。不过因为浏览器的地址栏会更新地址,所以体验也可能会好些。
    地址转发的过程是:浏览器向服务器请求了一个地址,服务器内部会请求一个新的地址,这个地址一般是本站的地址,然后结果正常返回给浏览器。这样只有一次请求,服务器代为请求了一次。站内的处理必然会快很多。但是浏览器地址栏的地址不会更换。如果你想让用户记住新的地址,这种方式就不合适。这种情况如果是想请求外站的地址,那么这种情况就是反向代理了。反向代理就是本服务器帮助浏览器访问其他网站。如果服务器只是访问本站的内容,只能叫做地址转发。
    下面就对地址重写做一个配置过程的展示,从最原始的方式一直升级为最终的形式,方便初学者循序渐进的学习。
1.多个地址重写到一个地址
server {
    location /test1/ {
        rewrite /test1/ /index.html   #错误写法,重写后的地址必须是绝对地址,不能用相对地址。
        # 语法:rewrite 被重写的地址,相对地址  重写后的地址,绝对地址
        rewrite /test1/ http://www.cjjjs.com/index.html   #正确写法,地址重写需要绝对地址
    }
    location /test2/ {
        rewrite /test2/ http://www.cjjjs.com/index.html   #正确写法,地址重写需要绝对地址
    }
}

    我们在server节点下配置多个location,这样可以检测到不同的地址,然后转发到同一个地址。这个思路简单直接。地址重写使用rewrite,语法见上面的说明。

2.将多个location合并到一个location
server {
    location /test/ {
        rewrite /test/1/ http://www.cjjjs.com/index.html
        rewrite /test/2/ http://www.cjjjs.com/index.html
    }
}

    多个location确实很冗余,不简洁。我们可以在一个location的rewrite里进行多个地址的重写即可。不过我们要在一个location的地址使用一样的开始,如test。这样就变得简练一些了。

3.使用正则表达式,将变化的数字变成参数。
server {
    location /test/ {
        rewrite ^/test/(\d+)/$ http://www.cjjjs.com/index.html
    }
}

    变化的内容,最好使用参数进行匹配,这样就不用写大量重复的rewrite。正则表达式则不在这里多讲,请查询相关资料学习。我们这里是加上了(\d+)来匹配数字。你可以用其他的匹配不同的内容。^是正则的开始,$是正则的结束。

4.使用正则表达式,支持末尾斜线的可选
server {
    location /test/ {
        rewrite ^/test/(\d+)/?$ http://www.cjjjs.com/index.html
    }
}

    我们前面的只能这样写请求地址:http://www.cjjjs.com/test/1/,末尾多了一个/符合,看起来是有点别扭。如果你想支持不要末尾的/,你可以再写一个rewrite。但是你不能保证所有人都喜欢没有末尾/的形式。但是你又不想写两条rewrite,所以我们就在正则表达式做改动。我们只要在末尾的/后加一个?,就可以实现可选了。

5.搞了这么多,重写后的地址一直都是一个。我们现在要开始实现重写后的地址和重写之前的地址一一对应,并转为参数形式。
server {
    location /test/ {
        rewrite ^/test/(\d+)/?$ http://www.cjjjs.com/index.html?id=$1
    }
}

    正则表达式里的()是将匹配分组,这样后续就可以进行参数提取。如果没有分组,那么整体匹配就是一个组。在后面的提取里,我们使用【$数字序号】来提取。我们这里只有一个()也就是一个组,那么$1就可以提取到这个组。也就是说,请求的地址中,这个匹配的内容将会被提取出来替换$1,这样就实现了地址重写后的一一对应。

6.我们看到后面有一个绝对域名地址,我们如果是站内的重写,就想自动获取域名。这样以后换域名,这里就不用修改了。
server {
    location /test/ {
        rewrite ^/test/(\d+)/?$ http://$server_name/index.html?id=$1
    }
}

    使用nginx的全局变量$server_name就可以读取前面的server_name的值。

    到此,所有的配置就算一步步的升级到最终的满意的形式了。最后一步如果是重写到外站的,那就不能用全局变量。如果是站内的转发,这样就可以实现。因为站内转发是不能用相对路径的,我们这样就可以实现站内的地址重写。只是说要多跳转一次,稍微慢一点。