Nginx反向代理配置总结

在前后端分离项目中,可以通过前端配置Nginx来解决跨域问题。

前端页面mysite.com,后台接口是在myserver.com域下的myserver.com/querytags接口,当在页面里直接请求,浏览器会报跨域的错误。为了绕开浏览器的跨域安全限制,现在需要将请求的域名改成mysite.com,同时约定一个URL规则来表明代理请求的身份,然后Nginx通过匹配该规则,将请求代理回原来的域。

本文总结一下Nginx反向代理匹配规则。

location匹配规则

Nginx官方文档给出location语法如下:

1
location [=|~|~*|^~] uri { … }

其中,方括号中的四种标识符是可选项,用来改变请求字符串和uri的匹配方式。uri是待匹配的请求字符串,可以是不包含正则的字符串,这种模式被称为“标准的uri”;也可以包含正则,这种模式被称为”正则uri”。

可选标识符

标识符 描述
= 精确匹配;用于标准uri前,要求请求字符串和uri严格匹配。如果匹配成功,就停止匹配,立即执行该location里面的请求。
~ 正则匹配;用于正则uri前,表示uri里面包含正则,并且区分大小写。
~* 正则匹配;用于正则uri前,表示uri里面包含正则,不区分大小写。
^~ 非正则匹配;用于标准uri前,Nginx服务器匹配到前缀最多的uri后就结束,该模式匹配成功后,不会使用正则匹配。
普通匹配(最长字符匹配);与location顺序无关,是按照匹配的长短来取匹配结果。若完全匹配,就停止匹配。

location匹配顺序

总原则:先前缀字符串,再正则表达式

不管配置文件中的location顺序怎么写,在匹配时,都会先将所有前缀字符串拎出来,放在第一位;然后再去找所有正则表达式,作为第二位

  1. 首先匹配前缀字符串。前缀字符串有以下几种形式(举例):

    • a、location = /data/ {}
    • b、location ^~ /data/ {}
    • c、location /data/ {}
  2. 然后匹配正则表达式。正则表达式的几种形式(举例):

    • d、location ~ \.html? {}
    • e、location ~* \.html? {}

匹配顺序:

  • a的权限最大,一旦匹配到,立即停止,直接使用对应的location。
  • b的权限次之,一旦匹配到,就不再检查正则表达式。相当于打断了后续。
  • c如果匹配到了,不会立即停止,而是会先将它存储起来,然后继续往下匹配。
  • d如果匹配到了,立即停止,直接使用对应的location;
  • d如果没有匹配,继续往下找。
  • e如果匹配到了,立即停止,直接使用对应的location;
  • e如果没有匹配,就使用先前存储的那个前缀字符串。

也就是说,location /data/ {}这种模式是等级最低的。实在匹配不到了,才勉强使用它。

最长匹配

1
2
3
4
5
6
7
8
9
10
server {
location /images/ {

}


location / {

}
}

一个请求为:http://www.example.com/images/a.png

对于/images/a.png这个URI来说,上面的2个location中,location /images/是最长匹配。虽然location /也能匹配,但不是最长的。

由于不是精确匹配,Nginx此时会先将这个最长匹配保存起来。

  • 如果后面配置了正则表达式,那么Nginx会继续向下匹配正则表达式。
  • 如果后面没有配置正则表达式,Nginx就会使用刚才保存的最长的那个前缀匹配,也就是location /images/对应的地方。

proxy_pass使用

下面是几个例子。

proxy_pass直接映射到主机,没有其他路径

location proxy_pass 实际访问目标
/nginx_location/ http://server http://server/nginx_location/some/path
/nginx_location/ http://server/ http://server/some/path
/nginx_location http://server http://server/nginx_location/some/path
/nginx_location http://server/ http://server//some/path

proxy_pass直接映射到主机的/test

location proxy_pass 实际访问目标
/nginx_location/ http://server/test http://server/testsome/path
/nginx_location/ http://server/test/ http://server/test/some/path
/nginx_location http://server/test http://server/test/some/path
/nginx_location http://server/test/ http://server/test//some/path

总结

其实根本没这么复杂,只有两种情况:

  • 目标地址中不带 uri。即 proxy_pass 的参数形如 http://127.0.0.1:8090。此时新的目标 url 中,匹配的 uri 部分不做修改,原来是什么样就是什么样
  • 目标地址中带 uri。即 proxy_pass 的参数形如 http://127.0.0.1:8090/dir1/dir2。此时新的目标 url 中,匹配的 uri 部分将会被修改为该参数中的 uri,如 http://127.0.0.1:8888/dir1/dir2

有人说,你没有讨论 ip 和端口后带不带/的区别。其实是不需要的,因为/本身就是一个 uri,很明显属于上面的第二种情况。

参考


----------- 本文结束啦感谢您阅读 -----------

赞赏一杯咖啡

欢迎关注我的其它发布渠道