nginx:使用rewrite重写url

1、概述

大家好,我是欧阳方超,可以关注我的公众号“欧阳方超”,后续内容将在公众号首发。
这次要介绍的话题,一言以蔽之,使用nginx做代理时location的配置问题。

2、需求

首先介绍一下我的的需求,承载着我的业务功能的jar包(我暂且把这个称为业务jar包吧)成功部署后,理论上前端就可以调用接口了,假如jar包启动后对外提供的接口地址为(以信息分页查询接口为例):

http://192.168.1.10:8000/information/pageinfo

但是我又用nginx对接口做了反向代理,配置的location大致如下(假设nginx的监听端口是80):

location /api {
    proxy_pass http://192.168.1.10:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

此时前端可以通过下面的形式调用上面的信息分页查询接口:

http://192.168.1.9/api/information/pageinfo

这段代理配置很好理解,Nginx 将会把请求从 http://192.168.1.9/api/information/pageinfo 转发到后端服务器,转发的 URL 会是:

http://192.168.1.10:8000/information/pageinfo

这是因为 location /api 中的 /api 部分会被去掉,剩下的路径 /information/pageinfo 会被附加到 proxy_pass 后面的地址。

3、问题的出现

以上,似乎没啥问题,但是问题就出在本系统中前端要调用一个获取登录用户信息的接口,而这个接口是在另一个jar包中(暂且把这个称为登录jar包吧),这个jar包部署后,对外提供的获取用户信息的接口是这样的:

http://192.168.1.10:8001/getUser

按照惯例,我也应该使用nginx对这个获取用户信息的接口做反向代理,假设先按下面的方式进行配置:

location /api {
    proxy_pass http://192.168.1.10:8001;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

上面这种配置方式显然与为业务jar包做代理的location模块冲突了,显然是不行的,估计有人要站出来说了,把这个location后的表达式改一下,比如改成/apiv1,前端调用获取登录用户的信息时直接写成http://192.168.1.9/apiv1/getUser,这样不就可以了吗,业务类接口的路径第一部分是api,而获取登录信息接口路径的第一部分是apiv1,这个首先要说一下啊,我是一个爱纠结的人,作为一个纠结的人,我怎么可能允许同样一个系统暴露给前端的接口在路径的第一部分就不一样呢,我坚信使用nginx的location配置一定能能够屏蔽掉这种差异,只是我目前不知道该怎么配置,需要折腾一番摆了。

4、问题解决

在查找解决办法的过程中,nginx的rewrite命令被我发现了,从字面理解他具有重写的功能,于是就查了一下他的用法,他可以利用正则规则对客户端请求的url进行重写,具体到我的场景中,我如果把对获取登录用户信息的接口代理的location模块改写成如下形式,就能满足我的使用需求了:

location = /api/getUser {
    rewrite ^/api(.*) $1 break;
    proxy_pass http://192.168.1.10:8001;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

在上述配置中,前端使用http://192.168.1.9/api/getUser接口请求获取登录用户的信息,由于该location模块使用了精确匹配的模式,所以该请求会被匹配到,当匹配到时rewrite指令将使用则正则表达式将/api路径去掉,只保留剩下的路径部分,即/getUser,break用以结束rewrite指令,经过rewrite的处理后,请求变为/getUser,经过proxy_pass后,请求变为http://192.168.1.10:8001/getUser,进而把这个url转发到后台,如果有携带的有参数的话将一并转发过去。
注意,由于这里使用的是精确匹配,不能被该location匹配到的接口将走location /api模块,这样就完全统一了前端调用接口时路径的第一部分,即/api。

5、总结

至此,我的纠结症得到了完美治愈。
限于我有限的认知,这是我能找到的解决我面临的问题的方案,有没有其他配置方式,欢迎各路大佬在评论区留言讨论。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值