nginx
在收到一条请求时将先通过 server_name
匹配一个 server
, 然后使用 server
中的 location
继续匹配.
匹配 server_name
在 nginx
中, server_name
决定了当收到一个请求后哪一个 server
会被使用. nginx
会使用请求头中的 Host
字段与 server_name
进行匹配. 定义 server_name
时可以使用 完全名称
、通配符名称
、正则表达式名称
, 它们的匹配顺序如下:
- 完全匹配
- 前通配符匹配, 即
*.example.org
- 后通配符匹配, 即
mail.*
- 正则表达式匹配
如果没有匹配到结果, 将会使用 default_server
进行处理, 如果没有定义, 则第一个定义的为 default_server
. 使用三个简单的 server
作为例子, 让他们监听 80
端口, server_name
分别设置为 *.org
、*.net
、*.com
:
server {
listen 80;
server_name example.org www.example.org;
return 401;
}
server {
listen 80;
server_name example.net www.example.net;
return 402;
}
server {
listen 80;
server_name example.com www.example.com;
return 403;
}
复制代码
在上面的配置中, 默认的服务器为 第一个
, 随便访问一个不存在的 server
将会返回 401
. 不过可以使用 default_server
手动设置一个默认主机, default_server
设置在 listen
字段, 如下:
server {
listen 80 default_server;
server_name example.net www.example.net;
}
复制代码
之后再匹配时, 未匹配到将会使用这个 server
.
禁止访问
如果想要禁止一个没有携带 Host
字段的请求, 可以定义如下 server
:
server {
listen 80;
server_name "";
return 444;
}
复制代码
server_name
定义为空字符串, 如果 Host
字段为空或不存在, 将会匹配到这个 server
, 然后返回 404
状态码.
Nginx
的444
状态比较特殊,如果返回444
那么客户端将不会收到服务端返回的信息,就像是网站无法连接一样, 浏览器直接显示502
. 但是如果使用反向代理, 还是显示正常状态码
如果想要禁止访问不存在的主机, 可以这样定义:
server {
listen 80 default_server;
server_name _;
return 444;
}
复制代码
_
在这里没有任何特别含义, 因为一个域名中不会出现 _
, 所以不会与任何真实的域名相同, 使用其他非法字符是相同的道理.
同时匹配 IP
和 server_name
现在来看一下对于监听不同 IP
和不同 server_name
混合使用时是如何处理的:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
}
server {
listen 192.168.1.1:80;
server_name example.net www.example.net;
}
server {
listen 192.168.1.2:80;
server_name example.com www.example.com;
}
复制代码
在这个配置中, nginx
首先匹配 IP
, 匹配到后再匹配它们的 server_name
, 如果没有匹配到 server_name
, 则使用到它们默认的 server
. 举个例子, 如果一个域名为 www.example.com
的请求来自 192.168.1.1:80
. 但是监听 192.168.1.1:80
的 server
只有两个, 这两个都不能匹配 www.example.com
, 那么就使用这两个 server
中的默认主机, 由于没有使用 defualt_server
定义监听, 所以默认为第一个即 www.example.org
这个 server
. 当然你可以定义 defualt_server
:
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
}
server {
listen 192.168.1.1:80 default_server;
server_name example.net www.example.net;
}
server {
listen 192.168.1.2:80 default_server;
server_name example.com www.example.com;
}
复制代码
匹配 location
在 nginx
匹配到一个 server
后, 就会通过 location
继续处理请求, 下面是一个示例:
server {
listen 172.17.0.3:80;
server_name _;
location / {
return 401;
}
location ~*\.(gif|jpg|png)$ {
return 402;
}
location ~*\.(gif|jpg|png)$ {
return 404;
}
location /api {
return 403;
}
}
复制代码
nginx
首先会在所有的 location
中搜索 前缀
进行匹配, 匹配到前缀后, 将按顺序匹配使用 正则表达式
定义的 location
, 匹配到就结束, 如果没有匹配到, 则使用之前匹配到前缀的那个 location
进行处理, 下面是具体匹配的例子:
- 一个
/x.gif
请求, 首先匹配到的前缀为/
, 然后使用剩下的x.gif
跟location
的正则去匹配, 先匹配到了location ~*\.(gif|jpg|png)$
, 返回402
. - 一个
/x.pdf
请求, 由于x.pdf
无法被匹配到, 所以使用location /
进行处理. - 一个
/api/x.gif
, 首先匹配到前缀为/api
, 然后使用剩下的x.gif
跟location
的正则去匹配, 先匹配到了location ~*\.(gif|jpg|png)$
, 返回402
. - 一个
/api/x.pdf
请求, 由于x.pdf
无法被匹配到, 所以使用location /api
进行处理.