理清 nginx 中的 location 配置

简介: 理清 nginx 中的 location 配置

前言
location 指令是 nginx 中最关键的指令之一,location 指令的功能是用来匹配不同的 URI 请求,进而对请求做不同的处理和响应,这其中较难理解的是多个 location 的匹配顺序,本文会作为重点来解释和说明。

开始之前先明确一些约定,我们输入的网址叫做请求 URI,nginx 用请求 URI 与 location 中配置的 URI 做匹配。

nginx 文件结构
首先我们先简单了解 nginx 的文件结构,nginx 的 HTTP 配置主要包括三个区块,结构如下:

Global: nginx 运行相关
Events: 与用户的网络连接相关
http
http Global: 代理,缓存,日志,以及第三方模块的配置
server
server Global: 虚拟主机相关
location: 地址定向,数据缓存,应答控制,以及第三方模块的配置
从上面展示的 nginx 结构中可以看出 location 属于请求级别配置,这也是我们最常用的配置。

配置 location 块
location 语法
location 块通过指定模式来与客户端请求的 URI 相匹配。

location 基本语法:

匹配 URI 类型,有四种参数可选,当然也可以不带参数。
命名 location,用 @ 来标识,类似于定义 goto 语句块。
location [ = | ~ | ~ | ^~ ] /URI { … }
location @/name/ { … }
location 匹配命令解释
参数 解释
空 location 后没有参数直接跟着标准 URI,表示前缀匹配,代表跟请求中的 URI 从头开始匹配。
= 用于标准 URI 前,要求请求字符串与其精准匹配,成功则立即处理,nginx 停止搜索其他匹配。
^~ 用于标准 URI 前,并要求一旦匹配到就会立即处理,不再去匹配其他的那些个正则 URI,一般用来匹配目录
~ 用于正则 URI 前,表示 URI 包含正则表达式,区分大小写
~
用于正则 URI前,表示 URI 包含正则表达式,不区分大小写
@ @ 定义一个命名的 location,@ 定义的 location 名字一般用在内部定向,例如 error_page, try_files 命令中。它的功能类似于编程中的 goto。
location 匹配顺序
nginx 有两层指令来匹配请求 URI。第一个层次是 server 指令,它通过域名、ip 和端口来做第一层级匹配,当找到匹配的 server 后就进入此 server 的 location 匹配。

location 的匹配并不完全按照其在配置文件中出现的顺序来匹配,请求 URI 会按如下规则进行匹配:

先精准匹配=,精准匹配成功则会立即停止其他类型匹配;
没有精准匹配成功时,进行前缀匹配。先查找带有^~的前缀匹配,带有^~的前缀匹配成功则立即停止其他类型匹配,普通前缀匹配(不带参数^~)成功则会暂存,继续查找正则匹配;
=和^~均未匹配成功前提下,查找正则匹配~和~*。当同时有多个正则匹配时,按其在配置文件中出现的先后顺序优先匹配,命中则立即停止其他类型匹配;
所有正则匹配均未成功时,返回步骤 2 中暂存的普通前缀匹配(不带参数^~)结果。
以上规则简单总结就是优先级从高到低依次为(序号越小优先级越高):

  1. location = # 精准匹配
  2. location ^~ # 带参前缀匹配
  3. location ~ # 正则匹配(区分大小写)
  4. location ~* # 正则匹配(不区分大小写)
  5. location /a # 普通前缀匹配,优先级低于带参数前缀匹配,多个前缀匹配命中时,取较长的那个
  6. location / # 任何没有匹配成功的,都会匹配进这里处理
    上述匹配规则可以用以下伪代码表示,加深理解:

function match(uri):
rv = NULL

if uri in exact_match:
return exact_match[uri]

if uri in prefix_match:
if param of prefix_match[uri] is '^~':
return prefix_match[uri]
else:
rv = prefix_match[uri] // 注意这里没有 return,且这里是最长匹配

if uri in regex_match:
return regex_match[uri] // 按文件中顺序,找到即返回
return rv
案例分析
接下来,让我们通过一些实际案例来验证上述规则。

案例 1
server {
server_name website.com;
location /doc {
return 701; # 用这样的方式,可以方便知道请求到了哪里
}
location ~* ^/document$ {
return 702;
}
}
curl -I website.com:8080/document 返回 HTTP/1.1 702
说明:按照上述的规则,显然第二个正则匹配会有更高的优先级

案例 2
server {
server_name website.com;
location /document {
return 701;
}
location ~* ^/document$ {
return 702;
}
}
curl -I website.com:8080/document 返回 HTTP/1.1 702
说明:第二个匹配了正则表达式,优先级高于第一个普通前缀匹配

案例 3
server {
server_name website.com;
location ^~ /doc {
return 701;
}
location ~* ^/document$ {
return 702;
}
}
curl http://website.com/document 返回 HTTP/1.1 701
说明:第一个前缀匹配^~命中以后不会再搜寻正则匹配,所以会第一个命中

案例 4
server {
server_name website.com;
location /docu {
return 701;
}
location /doc {
return 702;
}
}
curl -I website.com:8080/document 会返回 HTTP/1.1 701

server {
server_name website.com;
location /doc {
return 702;
}
location /docu {
return 701;
}
}
curl -I website.com:8080/document 依然返回 HTTP/1.1 701
说明:前缀匹配下,返回最长匹配的 location,与 location 所在位置顺序无关

案例 5
server {
listen 8080;
server_name website.com;

location ~ ^/doc[a-z]+ {
    return 701;
}

location ~ ^/docu[a-z]+ {
    return 702;
}

}
curl -I website.com:8080/document 返回 HTTP/1.1 701
把顺序换一下:

server {
listen 8080;
server_name website.com;

location ~ ^/docu[a-z]+ {
    return 702;
}

location ~ ^/doc[a-z]+ {
    return 701;
}

}
curl -I website.com:8080/document 返回 HTTP/1.1 702
说明:可见正则匹配是使用文件中的顺序,先匹配成功的返回

其他 location 配置相关
匹配问号后的参数
请求 URI 中问号后面的参数是不能在 location 中匹配到的,这些参数存储在$args变量中,可以用if来判断。

例如,下面的配置匹配带有 tag 参数的 URI。

location / {
if ($args ~ tag=) {

 # 如果地址匹配到 tag=

}
}
命名 location
带有@的 location 是用来定义一个命名的 location,这种 location 不参与请求匹配,一般用在内部定向。用法如下:

location / {
try_files $uri $uri/ @custom
}
location @custom {

# ...do something

}
上例中,当尝试访问 URI 找不到对应的文件就重定向到我们自定义的命名 location(此处为 custom)。

值得注意的是,命名 location 中不能再嵌套其它的命名 location。

location 实际使用建议
所以实际使用中,个人觉得至少有三个匹配规则定义,如下:

第一个必选规则:直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。

[kod.hitonexpress.com)
[kod.heyf.net)
[kod.hnwxkj.com)
[kod.hebmj258.com)
[kod.hsddcz.com)
[kod.huayin116.com)
[kod.huawin.net)
[kod.hnqyjk.com)
[kod.hsrz.net)
[kod.hwave.net)
这里是直接转发给后端应用服务器了,也可以是一个静态首页:

location = / {
proxy_pass http://tomcat:8080/index
}
第二个必选规则是处理静态文件请求,这是 nginx 作为 http 服务器的强项,有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用:

location ^~ /static/ {
root /webroot/static/;
}
location ~* .(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
第三个规则就是通用规则,用来转发动态请求到后端应用服务器:

location / {
proxy_pass http://tomcat:8080/
}

相关文章
|
2月前
|
编解码 应用服务中间件 Linux
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
303 1
|
6月前
|
应用服务中间件 Linux 网络安全
Centos 8.0中Nginx配置文件和https正书添加配置
这是一份Nginx配置文件,包含HTTP与HTTPS服务设置。主要功能如下:1) 将HTTP(80端口)请求重定向至HTTPS(443端口),增强安全性;2) 配置SSL证书,支持TLSv1.1至TLSv1.3协议;3) 使用uWSGI与后端应用通信(如Django);4) 静态文件托管路径设为`/root/code/static/`;5) 定制错误页面(404、50x)。适用于Web应用部署场景。
721 87
|
6月前
|
负载均衡 应用服务中间件 nginx
Nginx配置与命令
Nginx 是一款高性能的 HTTP 和反向代理服务器,其配置文件灵活且功能强大。本文介绍了 Nginx 配置的基础结构和常用指令,包括全局块、Events 块、HTTP 块及 Server 块的配置方法,以及静态资源服务、反向代理、负载均衡、HTTPS 和 URL 重写等功能实现。此外,还提供了常用的 Nginx 命令操作,如启动、停止、重载配置和日志管理等,帮助用户高效管理和优化服务器性能。
|
2月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
261 18
|
2月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
325 17
|
3月前
|
数据建模 应用服务中间件 PHP
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
本示例演示如何通过Docker挂载同一宿主目录至Nginx与PHP容器,实现PHP项目运行环境配置。需注意PHP容器中监听地址修改为0.0.0.0:9000,并调整Nginx配置中fastcgi_pass指向正确的IP与端口。同时确保Nginx容器中/var/www/html权限正确,以避免访问问题。
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
|
4月前
|
应用服务中间件 网络安全 nginx
配置Nginx以支持Websocket连接的方法。
通过上述配置,Nginx将能够理解WebSocket协议的特殊要求,代理Websocket流量到合适的后端服务器。注意,Websocket并不是HTTP,尽管它最初是通过HTTP请求启动的连接升级,因此保证Nginx了解并能够妥善处理这种升级流程是关键。
1096 10
|
3月前
|
Ubuntu 应用服务中间件 Linux
在Ubuntu上配置Nginx实现开机自启功能
至此,Nginx应该已经被正确地设置为开机自启。在Ubuntu中利用 `systemd`对服务进行管理是一种高效的方式,为系统管理员提供了强大的服务管理能力,包括但不限于启动、停止、重启服务,以及配置服务的开机自启动。通过这些简洁的命令,即使是对Linux不太熟悉的用户也能轻松地进行配置。
181 0
|
5月前
|
安全 应用服务中间件 网络安全
Nginx SSL/TLS协议栈中配置深度解析与实践指南-优雅草卓伊凡
Nginx SSL/TLS协议栈中配置深度解析与实践指南-优雅草卓伊凡
364 0
Nginx SSL/TLS协议栈中配置深度解析与实践指南-优雅草卓伊凡
|
5月前
|
JSON 前端开发 应用服务中间件
配置Nginx根据IP地址进行流量限制以及返回JSON格式数据的方案
最后,记得在任何生产环境部署之前,进行透彻测试以确保一切运转如预期。遵循这些战术,守卫你的网络城堡不再是难题。
252 3