背景

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.
  • =
  • ~
  • ~*
  • ^~

Ngnix Location的匹配顺序

对于每个请求来说,nginx 会选择最匹配的一个 location 来处理这个请求,nginx 其实就是通过对比这些 location 规则来选择一个 location,对比的顺序可以总结为:

  1. 首先匹配前缀匹配(没有 RE 表达式),针对当前这个请求,每个前缀匹配都匹配一遍.
  2. 搜索=匹配,如果当前请求匹配上了,搜索将会停止,直接使用这个这个 location.
  3. 如果第二步没有匹配上,nginx 会按照如下步骤继续搜索最长前缀匹配: 3.1 如果最长前缀匹配有^~这个modifier,nginx 会停止搜索并直接使用这个 location. 3.2 如果没有使用 ^~,暂存这个 location并且继续搜索.
  4. 只要最长前缀匹配被暂存和选中,nginx 就会看当前的 location 是否有大小写敏感的 RE(~~*),第一个匹配上这种会被当做有效的 location来处理这个请求.
  5. 如果没有 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