当前位置: 首页 > news >正文

Nginx内置变量及案例详解

好的,Nginx 内置变量是 Nginx 配置中极其强大且常用的功能。它们提供了关于当前请求、响应、连接状态等丰富的信息,使你能够实现动态配置、日志定制、访问控制、重写规则、代理设置等复杂逻辑。下面我将详细介绍常用的内置变量并辅以实际案例详解。

核心概念:

  • 来源: 这些变量由 Nginx 核心或模块(如 ngx_http_core_module, ngx_http_proxy_module, ngx_http_log_module 等)在请求处理的不同阶段自动设置。
  • 作用域: 大多数变量在请求处理期间都是可用的,可以在 location, server, http 块以及 access_log, rewrite, proxy_pass 等指令中使用。
  • 值类型: 通常是字符串。有些变量在某些上下文中可能为空。

常用内置变量分类及详解:

一、请求行与请求头相关变量

  1. $uri / $document_uri

    • 含义: 当前请求的 规范化后的 URI(不包括查询参数 ? 后面的部分)。Nginx 会对其进行解码、移除多余的斜杠、解析相对路径 ...
    • 案例:
      location /images/ {# 记录请求的图片路径 (如 /images/cat.jpg)access_log /var/log/nginx/image_access.log '$uri';
      }
      
  2. $request_uri

    • 含义: 客户端发来的 原始完整的请求 URI(包括查询参数)。未经任何规范化处理。
    • 案例:
      # 重写规则:如果请求URI包含 'oldpath',则重定向到新路径,但保留原始查询参数
      if ($request_uri ~* "^/oldpath/(.*)") {return 301 /newpath/$1?$args;
      }
      
  3. $args / $query_string

    • 含义: 请求 URI 中的 查询参数? 后面的部分)。两者通常等价。
    • 案例:
      # 根据查询参数做不同处理
      location /search {if ($args ~ "q=([^&]+)") {# 提取搜索关键词 (需要小心 if 的使用陷阱,通常建议用 map 或 split_clients)set $search_term $1;proxy_pass http://search_backend?query=$search_term;}# ... 其他处理
      }
      
  4. $is_args

    • 含义: 如果请求 URI 包含查询参数,则值为 ?;否则为空字符串。常用于拼接 URL。
    • 案例:
      # 在重写或代理时,优雅地添加或保留查询参数
      location /api/ {rewrite ^/api/(.*)$ /internal_api/$1$is_args$args break;proxy_pass http://api_backend;
      }
      
  5. $request_method

    • 含义: 客户端请求的 HTTP 方法(如 GET, POST, PUT, DELETE 等)。
    • 案例:
      # 限制特定 location 只允许 GET 和 HEAD 方法
      location /static/ {if ($request_method !~ ^(GET|HEAD)$) {return 405; # Method Not Allowed}# ... 静态文件服务配置
      }
      
  6. $http_HEADER_NAME

    • 含义: 获取 任意请求头 的值。将请求头名称转换为小写,用下划线 _ 代替连字符 -,并加上前缀 $http_
    • 案例:
      # 获取 User-Agent
      set $user_agent $http_user_agent;# 获取 X-Forwarded-For (常用于获取真实客户端IP,当Nginx前有代理时)
      set $real_client_ip $http_x_forwarded_for;# 获取 Authorization 头 (用于基础认证或JWT)
      set $auth_header $http_authorization;# 记录特定请求头到日志
      log_format custom_log '$remote_addr - [$time_local] "$request" $status "$http_referer" "$http_user_agent"';
      
  7. $host

    • 含义: 按以下优先级确定:
      1. 请求行中的主机名 (HTTP/1.0)。
      2. Host 请求头的值。
      3. 与请求匹配的 server_name 配置块中的第一个名称。
    • 重要: 不包含端口号。最常用且推荐用于配置基于域名的虚拟主机逻辑。
    • 案例:
      # 基于不同域名提供不同内容
      server {listen 80;server_name site1.com;root /var/www/site1;
      }
      server {listen 80;server_name site2.com;root /var/www/site2;
      }
      # 在通用配置中使用 $host
      location / {add_header X-Served-By $host always;
      }
      
  8. $http_host

    • 含义: 直接取自 Host 请求头的值,包含端口号(如果客户端指定了端口,如 Host: example.com:8080)。
    • $host 区别: $host 不包含端口,且回退机制更强。通常 $host 更安全通用,除非明确需要端口信息。
    • 案例:
      # 需要精确包含端口信息的情况 (较少见)
      if ($http_host != "www.example.com:443") {# ... 做一些处理
      }
      

二、客户端信息相关变量

  1. $remote_addr

    • 含义: 客户端 IP 地址。这是直接与 Nginx 建立 TCP 连接的客户端的 IP。重要提示: 如果 Nginx 前面有代理(如负载均衡器、CDN),这个地址是代理的 IP,而不是最终用户的 IP!获取真实用户 IP 通常用 $http_x_forwarded_for
    • 案例:
      # 基础访问日志通常包含客户端IP
      log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent"';
      access_log /var/log/nginx/access.log main;# 简单的 IP 访问限制 (生产环境建议用 `allow`/`deny` 或 `ngx_http_geo_module`)
      if ($remote_addr = "123.45.67.89") {return 403;
      }
      
  2. $remote_port

    • 含义: 客户端用于建立连接的 端口号
    • 案例: 较少单独使用,有时用于调试或详细日志记录。
      log_format detailed ... '$remote_addr:$remote_port ...';
      
  3. $remote_user

    • 含义: 如果请求使用了 HTTP 基本认证 (Basic Auth),此变量包含认证中提供的 用户名。否则为空。
    • 案例:
      # 记录谁访问了受保护区域
      location /admin/ {auth_basic "Admin Area";auth_basic_user_file /etc/nginx/.htpasswd;access_log /var/log/nginx/admin_access.log '$remote_user - $remote_addr [$time_local] "$request"';# ... 其他配置
      }
      

三、响应相关变量

  1. $status

    • 含义: 服务器返回给客户端的 HTTP 响应状态码 (如 200, 404, 500, 301 等)。极其常用
    • 案例:
      # 在访问日志中记录状态码
      log_format main ... '$status' ...;# 只记录错误状态 (4xx, 5xx) 到单独日志
      map $status $loggable {~^[23]  0; # 2xx, 3xx 不记录default 1; # 4xx, 5xx 记录
      }
      access_log /var/log/nginx/error_access.log main if=$loggable;# 根据状态码添加响应头 (例如标识错误来源)
      location @backend {proxy_pass http://backend;proxy_intercept_errors on;error_page 404 = @fallback;add_header X-Backend-Status $status always; # 记录后端实际状态
      }
      
  2. $body_bytes_sent

    • 含义: 发送给客户端的 响应体字节数,不包括响应头。近似于 Content-Length 的值。
    • 案例:
      # 记录传输的数据量 (用于流量分析、监控)
      log_format download '$remote_addr - [$time_local] "$request" $status $body_bytes_sent';
      access_log /var/log/nginx/download.log download;
      
  3. $bytes_sent

    • 含义: 发送给客户端的 总字节数(包括响应头)。
    • 案例: 需要精确计算总传输量时使用。
  4. $sent_http_HEADER_NAME

    • 含义: 获取 Nginx 发送给客户端的 任意响应头 的值。将响应头名称转换为小写,用下划线 _ 代替连字符 -,并加上前缀 $sent_http_
    • 案例:
      # 记录后端设置的自定义响应头 (如 X-Backend-ID)
      log_format backend_log ... '$sent_http_x_backend_id' ...;# 检查是否设置了某个响应头 (例如 Cache-Control)
      if ($sent_http_cache_control ~ "max-age=(\d+)") {set $cache_max_age $1;
      }
      

四、连接与请求处理相关变量

  1. $connection / $connection_requests

    • $connection: 当前连接的序列号(唯一标识一个连接)。在连接复用时,多个请求共享同一个 $connection
    • $connection_requests: 当前连接上已经处理过的 请求数量(对于 keepalive 连接)。
    • 案例:
      # 记录连接信息 (用于分析长连接复用情况)
      log_format connection_log '$remote_addr - $connection [$connection_requests] "$request"';
      
  2. $request_time

    • 含义: 处理请求所花费的 总时间(秒),精度为毫秒。从读取客户端请求的第一个字节开始,到将响应最后一个字节发送给客户端结束。关键性能指标!
    • 案例:
      # 记录慢请求 (例如超过 1 秒的请求)
      log_format slow_log '$remote_addr - [$time_local] "$request" $status $request_time';
      access_log /var/log/nginx/slow.log slow_log if=$slow_condition;map $request_time $slow_condition {~^\d\.\d{3}$ 0; # 小于1秒default       1; # 大于等于1秒
      }
      
  3. $request_length

    • 含义: 客户端请求的 总长度(包括请求行、请求头和请求体)。可用于检测异常大的请求。
    • 案例:
      # 限制非常大的请求 (防止DoS)
      client_max_body_size 10m; # 限制请求体大小
      # 在日志中记录请求长度
      log_format ... '$request_length' ...;
      
  4. $request

    • 含义: 完整的 原始请求行(如 GET /index.html?param=value HTTP/1.1)。
    • 案例:
      # 标准访问日志格式的核心部分
      log_format main ... '"$request"' ...;
      

五、时间相关变量

  1. $time_iso8601

    • 含义: 服务器时间的 ISO 8601 标准格式(如 2023-10-27T14:31:15+08:00)。日志记录推荐格式,便于解析和排序。
    • 案例:
      # 使用标准时间格式的日志
      log_format iso_log '$remote_addr - [$time_iso8601] "$request" $status';
      access_log /var/log/nginx/access.log iso_log;
      
  2. $time_local

    • 含义: 服务器时间的 本地格式(如 27/Oct/2023:14:31:15 +0800)。格式由 log_format 指令的默认值或配置决定。
    • 案例: 经典日志格式常用。
  3. $msec

    • 含义: 当前时间戳(秒),精度到毫秒(如 1698388275.123)。用于需要高精度时间戳的场景。
    • 案例: 自定义计时、唯一ID生成(需结合其他信息)。

六、代理与上游服务器相关变量(需启用相应模块)

  1. $proxy_host

    • 含义:proxy_pass 指令中指定的 代理目标服务器的主机名或 IP 地址和端口。如果 proxy_pass 只指定了 URI 部分,此变量可能为空。
    • 案例: 记录代理目标。
  2. $proxy_port

    • 含义: proxy_pass 指令中指定的 代理目标服务器的端口
  3. $proxy_add_x_forwarded_for

    • 含义: 一个非常有用的变量。用于构造 X-Forwarded-For 请求头以传递给上游服务器。它的值是 现有的 $http_x_forwarded_for 值(如果存在)后面加上逗号和 $remote_addr。如果不存在 $http_x_forwarded_for,则直接等于 $remote_addr。这是设置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 的标准做法。
    • 案例:
      location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 关键!传递真实客户端IP链
      }
      
  4. $upstream_addr

    • 含义: 处理请求的 上游服务器的 IP 地址和端口(或 Unix-domain socket 路径)。如果使用了负载均衡,它反映的是实际处理请求的那台后端服务器。调试后端问题的关键变量!
    • 案例:
      # 在日志中记录请求被转发到了哪个后端服务器
      log_format upstream_log ... '$upstream_addr' ...;
      access_log /var/log/nginx/upstream.log upstream_log;
      
  5. $upstream_status

    • 含义: 上游服务器返回的 HTTP 响应状态码。如果 Nginx 无法连接到上游,此变量通常为 502 (Bad Gateway) 或 504 (Gateway Timeout)。
    • 案例: 区分是后端服务错误 (5xx) 还是 Nginx 本身无法连接后端。
      log_format backend_error ... '$upstream_status' ...;
      
  6. $upstream_response_time

    • 含义: 从 Nginx 开始向上游服务器建立连接到接收完上游服务器响应头的 时间(秒),精度为毫秒。衡量后端服务器性能的关键指标!
    • 案例:
      # 记录后端响应时间
      log_format backend_perf ... '$upstream_response_time' ...;
      
  7. $upstream_http_HEADER_NAME

    • 含义: 从上游服务器响应中获取 任意响应头 的值。将响应头名称转换为小写,用下划线 _ 代替连字符 -,并加上前缀 $upstream_http_
    • 案例:
      # 获取后端设置的 Cache-Control 头来决定是否缓存
      proxy_cache_valid 200 302 10m if=($upstream_http_cache_control ~ "max-age=(\d+)");
      # 记录后端自定义头
      log_format ... '$upstream_http_x_backend_version' ...;
      

七、其他实用变量

  1. $scheme

    • 含义: 请求使用的 协议方案httphttps)。
    • 案例:
      # 强制 HTTPS 重定向
      if ($scheme != "https") {return 301 https://$host$request_uri;
      }
      
  2. $server_name

    • 含义: 匹配当前请求的 server 块中 server_name 指令的第一个名称
    • 案例: 在需要精确知道配置块匹配的 server name 时使用。
  3. $server_addr / $server_port

    • $server_addr: 接受请求的服务器的 IP 地址
    • $server_port: 接受请求的服务器的 端口号
    • 案例: 构造绝对 URL 或记录服务器信息。
  4. $nginx_version

    • 含义: 当前运行的 Nginx 版本号
    • 案例: 在响应头中标识服务器版本(注意安全风险,通常建议隐藏)或条件配置。
      # 根据版本启用不同特性 (谨慎使用)
      if ($nginx_version ~ "^1\.18\.") {# 针对 1.18.x 的特定配置
      }
      

综合案例详解:

  1. 动态访问日志:

    log_format dynamic_log '$remote_addr - $remote_user [$time_iso8601] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent" ''rt=$request_time uct="$upstream_connect_time" urt="$upstream_response_time" ''ups_addr=$upstream_addr ups_status=$upstream_status ''Host="$host" Real_IP="$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log dynamic_log;
    
    • 这个日志格式包含了客户端信息、时间戳、请求信息、响应状态、传输大小、来源、User Agent、关键时间指标(总时间、连接后端时间、后端响应时间)、后端服务器地址和状态码、请求的Host以及真实客户端IP链。非常适合调试和性能分析。
  2. 基于 User-Agent 的访问控制:

    map $http_user_agent $bad_bot {default 0;~*(googlebot|bingbot|yahoo) 0; # 允许好的爬虫~*(scrapers|spammer|malicious) 1; # 阻止坏的用户代理~*curl 1; # 阻止 curl (根据需求调整)
    }
    server {...if ($bad_bot) {return 403 "Access Forbidden";# 或者限制速率: limit_req zone=bot_zone burst=5 nodelay;}
    }
    
  3. 安全的文件下载限制:

    location ~* \.(sql|conf|env|key)$ {# 结合 $uri/$request_uri 匹配特定文件类型if ($args !~ "downloadkey=secret123") { # 简单示例,生产环境用更安全方式return 403 "Unauthorized access to sensitive files.";}# 或者只允许特定IP访问allow 192.168.1.0/24;deny all;# ... 文件服务配置
    }
    
  4. 负载均衡调试日志:

    log_format lb_debug '$time_iso8601 | CLIENT: $remote_addr | REQ: "$request" | ''UPSTREAM: $upstream_addr | STATUS: $upstream_status | ''TIME: $request_time / $upstream_response_time';
    access_log /var/log/nginx/lb_debug.log lb_debug;
    
    • 清晰展示请求时间线、客户端信息、具体请求、最终到达的后端、后端状态码以及关键时间指标,便于排查负载均衡或后端问题。
  5. 自定义错误页面带信息:

    error_page 404 /404.html;
    location = /404.html {internal; # 只能内部访问# 在错误页面中嵌入变量 (需要SSI支持或动态生成)ssi on;add_header Content-Type text/html;return 200 '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>Oops! Page Not Found</h1><p>The requested URL <code>$uri</code> was not found on this server.</p><p>Error occurred at: $time_iso8601</p></body></html>';
    }
    

重要注意事项:

  1. if 指令的陷阱: iflocation 上下文中有许多限制和令人惊讶的行为(有时会破坏继承关系)。尽量避免在 if 块中进行复杂的配置修改,优先使用 map, try_files, return, rewrite (带 last/break) 或 split_clients 等更安全的指令。如果必须用 if,主要用于检查变量值然后 returnrewrite
  2. 变量作用域: 大多数内置变量在请求范围内有效。使用 set 指令创建的自定义变量作用域是其所在的配置块(http, server, location)。
  3. 性能: 频繁使用某些变量(如正则匹配)或复杂的 map 块可能会影响性能。在高流量环境中需谨慎优化。
  4. 安全性: 不要将未经处理的用户输入(如 $args, $request_uri, $http_*)直接用于敏感操作(如文件路径、命令执行)。始终进行验证、过滤或转义。
  5. 空值: 某些变量在某些上下文中可能为空(例如 $remote_user 未认证时,$upstream_* 未使用代理时)。在逻辑判断时要考虑这种情况。
  6. 文档: 最权威的文档始终是 Nginx 官方文档:http://nginx.org/en/docs/varindex.html。不同模块提供的变量在其模块文档中列出。

通过熟练理解和灵活运用这些内置变量,你可以极大地提升 Nginx 配置的灵活性、可观测性和功能性,构建出更强大、更智能的 Web 服务器配置。

http://www.xdnf.cn/news/690049.html

相关文章:

  • 【mysql】-5 索引
  • 服务器tty2终端如何关机
  • WebAssembly 及 HTML Streaming:重塑前端性能与用户体验
  • 力扣100题---字母异位词分组
  • 力扣经典算法篇-16-最长公共前缀(顺序查找法,二分查找法,分治算法)
  • 学习率及相关优化参数详解:驱动模型高效训练
  • IP 风险画像技术略解
  • Parasoft C++Test软件单元测试_实例讲解(对多次调用的函数打桩)
  • apptrace 视角下移动端深度链接技术与优势​
  • 02-BTC-密码学原理 对hash算法如果出现漏洞的思考
  • MySQL 使用全局锁会导致的问题?
  • 【从零开始学习QT】Qt 概述
  • zookeeper 操作总结
  • 切换到旧提交,同时保证当前修改不丢失
  • K最近邻(KNN)算法完整实现指南
  • Linux -- gdb/cgdb的认识和使用
  • React Context 与状态管理:用与不用
  • 唯创WT2606B TFT显示灵动方案,重构电子锁人机互动界面,赋能智能门锁全场景交互!
  • 2025年北京市职工职业技能大赛第六届信息通信行业网络安全技能大赛复赛CTF部分WP-哥斯拉流量分析
  • 让Qt窗口覆盖整个桌面区域(支持多屏幕桌面)
  • 软件工程期末速成--附带几道题
  • 高光谱成像相机:表型技术在林业育种和精确林业的应用
  • element-plus bug整理
  • 操作系统(Operator System)
  • 从0到1掌握Kotlin高阶函数:开启Android开发新境界!
  • .NET 9的AI亮点
  • Vue2+Vuex通过数组动态生成store数据(扁平模式)
  • Dockerfile正确写法之现代容器化构建的最佳实践
  • docker镜像与dockerfile
  • C++修炼:map和set的封装