Nginx Location路由规则配置详解

  Location 语法详解

  Nginx配置文件中,Location配置项的语法格式如下

  按照匹配的符号不同,location路由匹配主要分成精准匹配、普通匹配、正则匹配、默认根路径匹配。下面逐一进行介绍。

  1. 精确匹配

  精准匹配的符号标记为“=”,下面是一个简单的精准匹配location的例子。

  如果请求URI和精准匹配的模式字符串/image完全相同,那么精准匹配通过。在所有的匹配类型中,精准匹配的优先级最高。

  2. 普通匹配

  普通匹配的符号标记为“^~”,下面是一个简单的普通匹配location的例子。

  普通匹配属于字符串前缀匹配,详细来说:如果请求路径URI头部匹配到location的模式字符串,那么匹配成功。如果匹配到多个前缀,那么最长模式匹配优先。

  配置以下两个普通匹配类型的location,具体配置如下:

  此时请求Nginx,http://localhost/image/car的请求地址,将输出 普通匹配 image/car

  普通匹配是前缀匹配,也是Nginx默认的匹配类型。也就是说,类型符号“^~”可以省略,如果location没有任何匹配类型,就为普通的前缀匹配。如果一个URI命中多个location普通匹配,则最长的location普通匹配获胜。

  为了对以上结论进行论证,这里举一个例子,在配置文件中配置两个同样字符串模式的location,一个不带类型符号,一个带“^~”符号,具体如下:

  执行重启Nginx的脚本openresty-restart.bat,发现Nginx不能启动,查看error.log错误日志,报错信息如下:

  ... 17:33:39 [emerg] 18760#25944: duplicate location "/demo" in .https://zhuanlan.zhihu.com/nginx-location-demo.conf:115

  从错误信息可以看出,在配置文件中有两个重复的location配置。

  3. 正则匹配

  正则匹配的类型按照类型符号的不同可以细分为以下4种:

  (1)~:标准正则匹配,区分字母大小写,进行正则表达式测试,若测试成功,则匹配成功。

  (2)~*:标准正则匹配,不区分字母大小写,进行正则表达式测试,若测试成功,则匹配成功。

  (3)!~:反向正则匹配,区分字母大小写,进行正则表达式测试,若测试不成功,则匹配成功。

  (4)!~*:反向正则匹配,不区分字母大小写,进行正则表达式测试,若测试不成功,则匹配成功。

  下面是一个正则匹配的例子,可以匹配以hello.php或hello.asp结尾的URL请求。

  在浏览器中给Nginx发送http://localhost/1/2/hellp.php的请求地址,输出的请求结果: 正则匹配: hello.(asp|php)$ 匹配成功

  如果配置文件中存在多个正则匹配location,那么它们之间的规则是顺序优先的,只要匹配到第一个正则类型的location,就停止后面的正则类型的location测试。

  例如,这里有两个正则匹配的location规则:\.(do|jsp)$和hello\.(do|jsp)$,具体如下:

  在浏览器中给Nginx发送http://localhost/1/2/hellp.do的请求地址,输出的结果是由配置在前面的location输出的。

  4. 默认根路径匹配

  根路径的路径规则就是使用单个“/”符号,示例如下:

  通过浏览器随便访问一个地址,如http://localhost/foo,使之不能匹配到其他的location,只能匹配到“/”根路径,返回的结果。

  表面看上去,location/{...}根路径匹配非常类似普通匹配,但实际上该规则自成一类,虽然只有唯一的一个路径,但是此类规则优先级是最低的。

  5. try_files介绍

  try_files是nginx中http_core核心模块所带的指令,主要是能替代一些rewrite的指令,提高解析效率。官网的文档为Module ngx_http_core_module.

  如果给出的file都没有匹配到,则重新请求最后一个参数给定的uri,就是新的location匹配。

  比如,访问localhost:80/apps/shop/123,此时访问不到,则会调用localhost:80/apps/index.html去重新访问一次。

  6. 使用案例

  本地资源文件项目目录

  nginx.conf location配置如下

  root和alias的区别在于:location 后的路径是否拼接在root 上,location的路径后面的 / ,加与不加无所谓。

  比如页面访问方式一的请求路径是:

  localhost:80/front nginx会自动转换为:/data/front/index.html 会自动追加location路径,所以location的路径必须对应资源文件夹的名称;

  页面访问方式二的请求路径是:

  localhost:80/web nginx会自动转换为: /data/front/index.html ,会去掉location路径

  最后总结一下4种location之间的匹配次序,大致如下:

  (1)类型之间的优先级:精准匹配>普通匹配>正则匹配>“/”默认根路径匹配。

  (2)普通匹配同类型location之间的优先级为最长前缀优先。普通匹配的优先级与location在配置文件中所处的先后顺序无关,而与匹配到的前缀长度有关。

  (3)正则匹配同类型location之间的优先级为顺序优先。只要匹配到第一个正则规则的location,就停止后面的正则规则的测试。正则匹配与location规则定义在配置文件中的先后顺序强相关。