Nginx 变量参数详解:从基础使用到条件判断
Nginx 提供了丰富的内置变量(参数),可用于获取请求信息、服务器状态等数据,结合条件判断(if语句)能实现灵活的请求处理逻辑。本文系统梳理 Nginx 常用变量的含义、使用场景及条件判断语法,帮助开发者高效配置 Nginx。
核心内置变量:获取请求与服务器信息
Nginx 的内置变量以$开头,可在配置文件中直接引用,用于动态获取请求参数、客户端信息、服务器状态等。以下是最常用的变量分类及说明:
请求参数与 URI 相关变量
| 变量 |
含义 |
示例 |
$arg_NAME |
获取 HTTP 请求中指定参数的值(NAME 为参数名) |
请求/index.html?name=zhangsan中,$arg_name的值为zhangsan |
$args |
请求 URI 中的完整参数(与$query_string相同) |
请求/list?id=1&page=2中,值为id=1&page=2 |
$uri / $document_uri |
当前请求的 URI(不带参数,可能被内部重定向修改) |
请求/article/123?lang=cn中,值为/article/123 |
$request_uri |
客户端原始请求的完整 URI(带参数,永不改变) |
请求/article/123?lang=cn中,值为/article/123?lang=cn |
$is_args |
若请求带参数则为?,否则为空字符串 |
带参数时为?,无参数时为空 |
客户端与连接信息变量
| 变量 |
含义 |
示例 |
$remote_addr |
客户端 IP 地址 |
如192.168.1.100 |
$remote_port |
客户端连接使用的端口 |
如54321 |
$binary_remote_addr |
二进制格式的客户端 IP(节省内存) |
如\x0A\xE0B\x0E(对应10.224.66.14) |
$http_HEADER |
获取客户端请求头中指定字段的值(HEADER 为小写) |
$http_user_agent获取浏览器标识,$http_referer获取来源页 |
服务器与响应信息变量
| 变量 |
含义 |
示例 |
$host |
客户端请求头中的Host字段(无则用虚拟主机名,小写) |
如example.com(自动去除端口) |
$server_name |
虚拟主机配置的server_name值 |
如www.example.com |
$server_addr |
服务器 IP 地址 |
如10.0.0.1 |
$server_port |
服务器监听的端口 |
如80或443 |
$server_protocol |
响应使用的 HTTP 协议版本 |
如HTTP/1.1 |
$sent_http_HEADER |
响应头中指定字段的值(HEADER 为小写) |
$sent_http_content_type获取响应的Content-Type |
请求体与文件相关变量
| 变量 |
含义 |
示例 |
$content_length |
客户端请求头中的Content-Length字段 |
如1024(表示请求体大小为 1KB) |
$content_type |
客户端请求头中的Content-Type字段 |
如application/json |
$request_filename |
URI 经root或alias转换后的本地文件路径 |
若root /var/www,请求/index.html对应/var/www/index.html |
$document_root |
当前请求使用的root配置值 |
如/var/www/example.com |
变量的实际应用场景
内置变量可用于日志格式化、反向代理、重定向等场景,以下是典型示例:
1. 自定义访问日志格式
利用变量记录关键请求信息,便于后续分析:
1 2 3 4 5
| log_format detailed '$remote_addr [$time_local] "$request_method $request_uri" ' 'status=$status bytes_sent=$body_bytes_sent ' 'referer="$http_referer" user_agent="$http_user_agent"';
access_log /var/log/nginx/detail.log detailed;
|
2. 反向代理时传递客户端真实 IP
通过$remote_addr将客户端 IP 传递给后端服务:
1 2 3 4 5
| location /api { proxy_pass http://backend; proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实IP proxy_set_header Host $host; # 传递原始Host }
|
3. 根据请求参数重定向
利用$arg_name判断参数值并跳转:
1 2 3 4 5 6
| location / { # 若请求带参数?from=mobile,则重定向到移动端页面 if ($arg_from = mobile) { return 302 /mobile$request_uri; } }
|
条件判断:if语句的使用
Nginx 的if语句可结合变量和运算符实现条件逻辑,支持在server块或location块中使用,语法为:
1 2 3
| if (condition) { # 执行操作(如return、rewrite、set等) }
|
条件表达式语法
condition支持多种判断方式,优先级从高到低如下:
| 类型 |
运算符 |
说明 |
示例 |
| 变量与字符串比较 |
=(等于)、!=(不等于) |
判断变量与字符串是否相等 |
if ($request_method = POST) { ... } |
| 正则匹配 |
~(区分大小写)、~*(不区分大小写)、!~(不匹配)、!~*(不匹配,忽略大小写) |
变量与正则表达式匹配 |
if ($uri ~* \.html$) { ... }(匹配.html或.HTML结尾) |
| 文件 / 目录判断 |
-f(文件存在)、!-f(文件不存在)、-d(目录存在)、!-d(目录不存在)、-e(文件 / 目录 / 链接存在)、-x(文件可执行) |
检查文件系统状态 |
if (!-f $request_filename) { ... }(文件不存在时) |
| 变量非空判断 |
无运算符 |
变量不为空且非 “0 开头的字符串” 则为真 |
if ($http_referer) { ... }(存在 Referer 头时) |
常用操作指令
if块内可执行的操作包括:
return code:返回指定 HTTP 状态码并终止请求处理
1 2 3 4
| # 禁止POST请求 if ($request_method = POST) { return 405; # 405 Method Not Allowed }
|
rewrite:重写 URI(需配合last或break)
1 2 3 4
| # 将.html后缀的请求重写为.php if ($uri ~* ^/(.*)\.html$) { rewrite ^/(.*)\.html$ /$1.php last; }
|
1 2 3 4
| # 根据客户端IP设置变量 if ($remote_addr ~* 192\.168\.) { set $is_internal 1; # 内网IP标记为1 }
|
实战示例
1 2 3 4 5 6 7
| location ~* \.(jpg|png|gif)$ { # 允许的来源(none:直接访问,blocked:无Referer,example.com:指定域名) valid_referers none blocked example.com *.example.com; if ($invalid_referer) { return 403; # 非法来源返回403 } }
|
- 根据 UA 拦截爬虫:阻止特定 User-Agent 的请求
1 2 3
| if ($http_user_agent ~* "Baiduspider|Googlebot") { return 403; # 拦截百度和谷歌爬虫 }
|
- 动态设置缓存时间:HTML 不缓存,静态资源长缓存
1 2 3 4 5 6 7 8
| location / { if ($request_filename ~* \.(html)$) { add_header Cache-Control "no-cache"; # HTML不缓存 } if ($request_filename ~* \.(js|css|png)$) { add_header Cache-Control "max-age=86400"; # 静态资源缓存1天 } }
|