写在前面的话
前面我们谈了 nginx 基础的 WEB 服务配置以及定制我们的日志显示格式,接下来我能更加详细的说说 server 字段。
location 字段
在 Server 中,如果我们只是一个 WEB 服务,其实是不需要先前的 location 匹配的。
所以在之前的 demo.conf 中,我们完全可以直接写成:
# 80 端口测试
server {
listen 80;
server_name localhost;
root /data/www/demo-80;
index index.html index.htm;
...
}
一样能够实现我们的 WEB 访问。
这并不意味着 location 没有,相反的,location 在 nginx 中非常重要,在一些复制的处理逻辑中,我们都需用到 location 匹配来实现。
先来看看 location 的语法:
location [=|~|~*|^~] /uri/ {...}
当然这里的参数肯定不止这些,可以参考下表中常用的:
参数 | 说明 |
---|---|
= | 精确匹配,优先级最高 |
^~ | uri 以某个字符串开头,nginx 不会对 uri 编码,所以 /static/ /aa 能够匹配 /static/20%/aa |
~ | 区分大小写的正则匹配 |
~* | 不区分大小写的正则匹配 |
!~ | 区分大小写的正则匹配取反 |
!~* | 不区分大小写的正则匹配取反 |
/ | 通用匹配,能匹配到所有 |
其优先级为:= > ^~ > 正则 > /
我们在 vhosts 目录下新建一个 location-demo.conf 配置文件进行测试:
server {
listen 8081;
server_name localhost; location / {
echo "URI: /";
} location = / {
echo "URI: = /";
} location = /hello {
echo "URI: /hello";
} location ~ \.(jpg|png|gif|js|css) {
echo "URI: STATIC FILES";
} location ~* \.(jpg|png|gif|js|css) {
echo "URI: OTHER STATIC FILES";
} location ^~ /static {
echo "URI: /static";
} location ^~ /static/ {
echo "URI: /static/";
}
}
我们在另外一台机器*问测试:
于是我们可以得出一些结论:
1. 在默认访问一个没有 URI 的 URL,无论有没有 /,系统默认是当作 / 处理的,所以 1,2 我们都匹配 = / 的规则。
2. 在使用 = 匹配时,虽优先级最高,但 uri 也限定死了,和 3,4 一样,后面加不加 / 两个结果。如 后面加啥都不再满足该规则。
3. 在区分大小写和不区分大小写同时存在的时候,率先匹配更精确的区分大小写,然后才是不区分大小写,如:6,7,8。
4. 在匹配开头的时候,从开头开始,满足的越多,匹配的优先级越多,如:9,10。
5. 在前后都满足匹配的时候,默认从左往右匹配,如果左边匹配了就直接满足左边,如:11,12,13。
最后总结下:
1. = 优先级最高,但是必须精确。
2. 正则匹配需要从左往右匹配着走,如果左边已经满足,那么满足越多的优先级越高。
3. 区分大小写的优先级高于不区分大小写。
附带一个常用的静态文件处理规则:
location ~* .*\.(js|css|png|jpg|gif|jpeg|bmp|ico)?$
{
# 7天过期,不保存日志
expires 7d;
access_log off;
} location ~* .*\.(zip|rar|exe|msi|iso|gho|mp3|rmvb|mp4|wma|wmv|rm)?$
{
# 禁止这些文件下载
deny all;
}
root / alias
在之前的静态 WEB 服务中,我们使用 root 来指定了我们 index.html 存放的路径。但是在 nginx 除了 root,我们还要另外一种,alias。
我们可以通过示例来进行区分:
1. 创建测试使用的网页:
mkdir /data/www/root
mkdir /data/www/alias
echo '<h1>ROOT WEB SERVER</h1>' > /data/www/root/index.html
echo '<h1>ALIAS WEB SERVER</h1>' > /data/www/alias/index.html
2. 在 vhosts 下面添加配置文件:root-alias.conf
server {
listen 8082;
server_name localhost; location ^~ /root {
root /data/www/root;
index index.html index.htm;
} location ^~ /alias {
alias /data/www/alias;
index index.html index.htm;
}
}
然后重载 nginx:
/data/services/nginx/sbin/nginx -s reload
此时我们访问查看 root 匹配:
访问查看 alias 匹配:
查看 error.log 查找 404 的原因:
可以看到最终请求的结果为:/data/www/root/root/index.html
这个目录是不存在的,由此我们可以得出:
root 指定路径会自动将后面的 uri 拼接上去。因为平时的 / 匹配,多以拼接后不影响,但是 uri 如果不为 / 就会出现问题,由此导致 404。
alias 在在指定路径的时候则不会拼接,无论你后面的 uri 是如何花里胡哨都不会影响我们本身的目录。
但是需要注意,alias 需要后面的 uri 必须以 / 开头,否则同样 404。
如果你没有用 / 开头,则会访问到 /data/services/nginx/html/alias 下面去,前面为 nginx 的默认 WEB 路径。
最后,如果我们以:http://192.168.100.111:8082/alias123 访问,会发现:
查找目录变成了我们 uri 后面的部分?其实不是,其实质是将 uri 满足匹配的部分去掉,然后将后面的 123 拼接到了 alias 指定的目录,由于指定的目录最后没有 / 才导致看起来一样,如果给他加上 / 则会变成 alias/123。感兴趣的可以去测试。
小结
root 在实际应用中用的多些,如果有特殊需求,alias 能帮到大忙。当然,location 才是重点。