玩转Nginx Location:实用技巧与避坑指南
Nginx是一款高性能的Web服务器,而Location块作为Nginx配置的核心之一,为我们提供了强大的路由跳转能力。本文将深入探讨Nginx Location块的实用技巧与避坑指南,以便能更好的了解Nginx服务器配置。
location指令
在上述语法中, =
、~
、~ *
、^~
和@
都是 location
用于实现访问控制的前缀,且在使用时只能选择一种,当然也可以不设置前缀。
merge_slashes
是一个用于配置的指令,用于控制是否合并多个连续的斜杠(/
) 。当merge_slashes
设置为on
时,Nginx将合并请求中的多个连续斜杠为单个斜杠。这是比较有用的,因为在Web请求中,有时候会由于用户输入、URL构造等原因导致出现多个斜杠。例如,example.com//path/to/resource
中的双斜杠。
根据上表的描述,可将 location
根据不同前缀的使用方式,分为以下几种:
前缀字符串 :常规匹配(空)、 =
精确匹配、^~
匹配上这条之后不再进行正则表达式匹配
正则表达式: ~
区分大小写的正则匹配、 ~ *
不区分大小写的正则匹配
用于内部调整的命名location:@
精确匹配
精准匹配指的就是用户访问的 URI
与配置的 URI
完全一致的情况,才会执行其后的指令块,示例配置如下 。
server { listen 8081; location / { } location = /Test1 { return 200 'exact match!'; } }
匹配成功则立即处理,nginx停止搜索其他匹配。
[root@dev conf]# curl http://192.168.2.129:8081/Test1 exact match!
常规匹配(最大前缀匹配)
由于 location
可以同时定义多个,当一个配置文件中同时出现多个 location
时,普通常规location 之间遵循“最大前缀匹配”原则,匹配最多的那个将会执行。
location /Test1/Test2 { return 200 'longest prefix string match!'; } location /Test1 { return 200 'prefix string match!'; }
示例如下:
[root@dev conf]# curl 192.168.2.129:8081/Test1/Test2 longest prefix string match!
这里需要特别注意的一点是,当普通
location
与正则location
同时存在时,如果正则location
匹配成功,则不会执行普通location
的最大前缀location
匹配结果。
正则匹配
Nginx 配置文件中,多个正则 location
之间按照nginx.conf的顺序依次匹配正则表达式,且只要匹配成功就不会继续匹配后面定义的正则 location
, 在实际应用中要注意正则 location 在配置文件中的书写顺序 。
#它匹配以/Test1/结尾的URL路径
location ~ /Test1/$ {
return 200 'first regular expressions match!';
}
location ~* /Test1/(\w+)$ {
return 200 'longest regular expressions match!';
}
[root@dev conf]# curl http://192.168.2.129:8081/3/Test1/ first regular expressions match! [root@dev conf]# curl http://192.168.2.129:8081/Test1/2 longest regular expressions match!
详细匹配流程
当一个URL请求到Nginx之后,首先会进行全部的前缀字符串Location匹配,location 的匹配并不完全按照其在配置文件中出现的顺序来匹配,请求URI 会按如下规则进行匹配:
- 1. 先精准匹配
=
,精准匹配成功则会立即执行,然后停止其他类型匹配; - 2. 没有精准匹配成功时,进行前缀匹配。先查找带有
^~
的前缀匹配,带有^~
的前缀匹配成功则立即停止其他类型匹配; - 3.
=
和^~
均未匹配成功前提下,进行普通前缀匹配成功则会暂存最长匹配的前缀字符串,继续查找正则匹配,查找正则匹配~
和~\*
。当同时有多个正则匹配时,按其在配置文件中出现的先后顺序优先匹配,命中则立即停止其他类型匹配; - 4. 所有正则匹配均未成功时,返回步骤 3中暂存的普通前缀匹配结果
实践问题
当把所有的Location放一起,Nginx的配置文件内容如下:
server { listen 8081; location /Test1/Test2 { return 200 'longest prefix string match!'; } location = /Test1 { return 200 'exact match!'; } location ~ /Test1/$ { #以/Test1/结尾的URL return 200 'first regular expressions match!'; } location ~* /Test1/(\w+)$ { # ~* 正则匹配,不区分大小写 return 200 'longest regular expressions match!'; } location ^~ /Test1/ { return 200 'stop regular expressions match!'; } location /Test1 { return 200 'prefix string match!'; }}
可以思考下访问URL:
- /Test1
- /Test1/
- /Test1/Test2
- /Test1/Test2/
- /test1/Test2
会返回什么内容呢?
[root@dev nginx2]# curl 192.168.2.129:8081/Test1 exact match![root@dev nginx2]# [root@dev nginx2]# curl 192.168.2.129:8081/Test1/ stop regular expressions match![root@dev nginx2]# [root@dev nginx2]# curl 192.168.2.129:8081/Test1/Test2 longest regular expressions match![root@dev nginx2]# [root@dev nginx2]# curl 192.168.2.129:8081/Test1/Test2/ longest prefix string match![root@dev nginx2]# [root@dev nginx2]# curl 192.168.2.129:8081/Test1/Test2/ longest prefix string match![root@dev nginx2]#
proxy_pass避坑指南
proxy_pass
是Nginx反向代理常用的一个指令,但是指令存在新手很容易踩的坑,就是 proxy_pass
中的URL是否有‘/’ 的问题。
proxy_pass的URL带有 /
在nginx中配置proxy_pass时,当在proxy_pass后面的url加上了/,相当于是绝对根路径,nginx转发时,会将原uri去除location匹配表达式后的内容拼接在proxy_pass中url之后。
#测试地址:http://192.168.2.129/test/tes.jsp #场景一: location ^~ /test/ { proxy_pass http://192.168.2.129:8081/server/; } #代理后实际访问地址:http://192.168.2.129:8081/server/tes.jsp #场景二: location ^~ /test { proxy_pass http://192.168.2.129:8081/server/; } #代理后实际访问地址:http://192.168.2.129:8081/server//tes.jsp #场景三: location ^~ /test/ { proxy_pass http://192.168.2.129:8081/; } #代理后实际访问地址:http://192.168.2.129:8081/tes.jsp
proxy_pass的URL不带/
proxy_pass配置中url末尾不带/时,如url中不包含path(只有ip和端口),则直接将原uri拼接在proxy_pass中url(ip和端口)之后;如url中包含path,则将原uri去除location匹配表达式后的内容拼接在proxy_pass中的url之后。
#测试地址:http://192.168.2.129/test/tes.jsp #场景一: location ^~ /test/{ proxy_pass http://192.168.2.129:8081/server; #url中包含path:/server } #代理后实际访问地址:http://192.168.2.129:8081/servertes.jsp #场景二: location ^~ /test { proxy_pass http://192.168.2.129:8081/server; } 代理后实际访问地址:http://192.168.2.129:8081/server/tes.jsp #场景三: location ^~ /test/ { proxy_pass http://192.168.2.129:8081; #url中不包含path } 代理后实际访问地址:http://192.168.2.129:8081/test/tes.jsp #场景四: location ^~ /test { proxy_pass http://192.168.2.129:8081; } 代理后实际访问地址:http://192.168.2.129:8081/test/tes.jsp
root和alias指令区别
在 Nginx 配置中,root
和 alias
都是用于指定静态资源的根目录路径,但它们在处理路径匹配和返回文件时存在一些差异。
root 指令
例如,假设我们有以下配置:
location /static/ {
root /var/www/;
}
当收到的请求是 http://example.com/static/image.jpg
时,Nginx 会查找文件系统中的 /var/www/static/image.jpg
并返回该文件。
这里需要注意的是,root
指令会将匹配的 URL 路径直接映射到文件系统中的相对路径, 也就是将请求 URL全 路径附加到根位置来形成要提供的最终文件路径。
alias指令
alias
指令表示别名的意思,会将匹配的 URL 路径替换为指定的文件系统路径。
location /static/ {
alias /var/www/;
}
在上面的例子中,/static/
被替换为 /var/www/
,当收到的请求是 http://example.com/static/image.jpg
时,Nginx 会查找文件系统中的 /var/www/image.jpg
并返回该文件。
综上所述,root
用于直接映射 URL 路径到文件系统中的相对路径,而 alias
允许在返回文件时修改 URL 路径的部分或全部。
评论列表 (0条):
加载更多评论 Loading...