本文翻译自 https://www.keycdn.com/support/nginx-location-directive
背景
Nginx location
是使用 nginx 的过程中必须要掌握的技能,无论是在server blocks
还是其他 location blocks
中都会用到,这篇文章简单介绍了当请求来临时location
指令是如何处理客户端URI
请求的.
Nginx 的块(Block)配置
Nginx 将配置按照层级关系,用块状形式进行配置,每当一个请求来临时,nginx 服务器就会处理这个请求到底会映射到哪个块配置.在 Nginx 的配置文件中,两种主要的块配置是:
-
server
块配置 -
location
块配置
server
的块配置包含一系列的虚拟 server 配置,多个 server 配置就可以对多个 domain name 的请求,也包括 ip 端口进行处理.
而location
配置在server
块配置中起着至关重要的作用,决定了URI
或者资源请求应该如何被处理,这些 URI 请求可以被拆分为多个location
的配置
Nginx Location 指令语法
如下就是常用的 location 配置的语法格式,其中modifier
是可选的,location_match
就是制定 URI 应该去往哪个配置的关键.
location optional_modifier location_match {
. . .
}
Regular expressions(RE)或者字面量都可以用来定义modifier
,如果 location 配置中制定了modifier,可能会改变 nginx匹配 location的方式,如下介绍几种最重要的modifier:
- (none) 完全没有modifier表示 location会解释为前缀匹配,要确定匹配项,将根据从URI的开头匹配该location.
-
=
等号表示当前这个 location 会匹配一个确定的请求,配置什么就匹配什么请求,如果匹配上了,就会停止搜索. -
~
波浪号表示当前这个 location 会当成一个大小写敏感的RE匹配. -
~*
波浪号跟星号标识 location 会按照大小写不敏感的 RE 匹配. -
^~
非表达式(RE)匹配,正则表达式将不会生效.
Ngnix Location的匹配顺序
对于每个请求来说,nginx 会选择最匹配的一个 location 来处理这个请求,nginx 其实就是通过对比这些 location 规则来选择一个 location,对比的顺序可以总结为:
- 首先匹配前缀匹配(没有 RE 表达式),针对当前这个请求,每个前缀匹配都匹配一遍.
- 搜索
=
匹配,如果当前请求匹配上了,搜索将会停止,直接使用这个这个 location. - 如果第二步没有匹配上,nginx 会按照如下步骤继续搜索最长前缀匹配:
3.1 如果最长前缀匹配有^~
这个modifier,nginx 会停止搜索并直接使用这个 location.
3.2 如果没有使用^~
,暂存这个 location并且继续搜索. - 只要最长前缀匹配被暂存和选中,nginx 就会看当前的 location 是否有大小写敏感的 RE(
~
和~*
),第一个匹配上这种会被当做有效的 location来处理这个请求. - 如果没有 RE 的 location 匹配上,前面暂存的 location 就会被选中来处理这个请求.
注:所以 没有修饰符的 location 其实是很浪费资源的,可以用 ^~ 来替代.
举例
如下是一些 location 配置的例子,用来详细描述上面所说的处理顺序,你也可以按照具体实际情况来修改这些例子.
location = / {
# 只处理请求 /.
}
location /data/ {
# 所有以 /data/ 匹配,但是还会继续搜索.
# 如果没有其他 location 匹配上,就用这个处理请求.
}
location ^~ /img/ {
# 所有以 /img/ 开头的请求并且会停止搜索.
}
location ~* .(png|gif|ico|jpg|jpeg)$ {
# 以png, gif, ico, jpg ,jpeg结尾的请求.
# 如果请求是到 /img/ 路径的话 还是会被上面的 location 处理
}
如何防止图片盗链:
location ~ .(png|gif|jpe?g)$ {
valid_referers none blocked yourwebsite.io *.yourwebsite.io;
if ($invalid_referer) {
return 403;
}
}
在可写权限的目录禁止脚本:
location ~* /(media|images|cache|tmp|logs)/.*.(php|jsp|pl|py|asp|cgi|sh)$ {
return 403;
}
更多 nginx location 指令的信息,可以参见官网:Nginx