路由匹配规则
-
优先级:精确匹配 > 前缀匹配 > 正则匹配 > 通用匹配
-
语法示例
nginx# 精确匹配 localhost/home location =/home {...} # 前缀匹配 localhost/api/... # 前缀匹配会搜索所有前缀匹配的 location, 最后返回匹配最长的 location location ^~/api/ {...} # 正则匹配 localhost/static/.../file.jpg # ~ 区分大小写,~* 不区分大小写 # !~ 区分大小写取非,!~* 不区分大小写取非 location ~*/repo/.+\.(gif|jpg|jpeg)$ {...} # 通用匹配 localhost/index.html location / {...} -
可以捕获组获取匹配结果
bash# 根据环境名称设置路径 location ^~/(staging|prod|dev)/ { root /dist/$1 }
路径跳转:不同 location 之间跳转
-
语法:
rewrite <regex> <replacement> [flag];ruby# 去除路径起始的环境名称 location ^~/(staging|prod|dev) { rewrite ^/(staging|prod|dev)/(.*)$ /$2 break; } -
flag 标记:
- last :本条规则匹配完成后,不终止重写后的 url 匹配,浏览器地址栏不变
- break :本条规则匹配完成即终止,终止重写后的 url 匹配,浏览器地址栏不变
- redirect :返回 302 临时重定向,浏览器地址会显示跳转后的 URL 地址
- permanent :返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址
根据环境名称设置路由
-
文件目录结构:
markdown- dist - dev - index.html - assets - js/css/... 资源文件 - prod - ... -
nginx 配置规则
nginxhttp { include mime.types; default_type application/octet-stream; # ... # 根据请求 url 获取环境名称: localhost/dev --> dev # 注意:map 需要位于 http {...} 中 map $request_uri $env_name_uri { ~^/(staging|prod|dev)(/|$) $1; default ""; } server { listen 443 ssl; server_name localhost; # ... # index 通过 url 获取环境名称,后续资源加载如果采用绝对路径就需要从 cookie 中获取环境名称 set $env_name $env_name_uri; if ($env_name = "") { set $env_name $cookie_env; } add_header Set-Cookie "env=$env_name; Path=/; Max-Age=3600; HttpOnly; SameSite=Lax"; # 动态设置 root 路径 root /dist/$env_name; index index.html; location / { try_files $uri $uri/ /index.html; } # 处理环境特定路径, 重定向到不包含环境名称的路径 location ^~/(staging|prod|dev) { rewrite ^/(staging|prod|dev)/(.*)$ /$2 break; try_files $uri $uri/ /index.html; } # 资源文件访问可能不会携带环境名称,从 cookie 获取环境名称 location ^~/assets/ { root /dist/$env_name; try_files $uri $uri/ =404; expires 30d; access_log off; # 启用 Gzip 压缩 gzip on; gzip_types text/css application/javascript image/svg+xml; gzip_min_length 1024; gzip_comp_level 6; } # api 根据不同环境配置不同的 host set $api_host ""; if ($env_name = "staging") { set $api_host "http://127.0.0.1:8001"; } if ($env_name = "prod") { set $api_host "http://127.0.0.1:8000"; } location ^~/api/ { proxy_pass $api_host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; } }
全局变量汇总
| 核心请求变量 | 说明 |
|---|---|
$args , $query_string |
请求中的参数(Query String),如 ?name=john 中的 name=john |
$is_args |
如果请求有参数,值为 ?;否则为空字符串 |
$uri |
当前请求的规范化 URI (不含参数),如 /api/user |
$request_uri |
完整的原始请求 URI (含参数),如 /api/user?name=john |
$scheme |
请求协议(http 或 https) |
$request_method |
请求方法(GET、POST 等) |
$request_length |
请求总长度(含请求行、请求头、请求体) |
$request_body |
请求体内容(通常用于 proxy_pass 或日志记录) |
$remote_addr |
客户端 IP 地址 |
$remote_port |
客户端端口号 |
$server_addr |
服务器 IP 地址 |
$server_port |
服务器端口号 |
$server_name |
匹配请求的 server 块中的 server_name 值 |
$host |
优先级顺序 : 1. 请求行中的 Host 头 2. server_name 匹配的域名 3. 配置中首个 server_name |
| 相应相关变量 | |
$status |
HTTP 响应状态码(如 200、404) |
$body_bytes_sent |
发送给客户端的响应体字节数(不含响应头) |
$bytes_sent |
发送给客户端的总字节数(含响应头) |
$sent_http_* |
任意响应头的值,如 $sent_http_content_type |
| 连接与请求控制 | |
$connection |
连接序列号 |
$connection_requests |
当前连接上的请求数量(用于 keepalive 连接) |
$nginx_version |
Nginx 版本号 |
| 时间相关变量 | |
$time_iso8601 |
ISO 8601 格式的本地时间(如 2023-10-05T14:31:12+08:00) |
$time_local |
普通日志格式的本地时间(如 05/Oct/2023:14:31:12 +0800) |
$request_time |
请求处理总耗时 (单位:秒,精确到毫秒) |
$upstream_response_time |
上游服务器响应耗时(单位:秒) |
| 代理相关变量 | |
$proxy_host |
proxy_pass 指令中指定的上游主机名 |
$proxy_port |
proxy_pass 指令中指定的上游端口 |
$upstream_addr |
上游服务器的 IP 和端口(如 192.168.1.23:8080) |
$upstream_status |
上游服务器的 HTTP 响应状态码 |
$upstream_http_* |
从上游服务器返回的响应头(如 $upstream_http_server) |
| 其他实用变量 | |
$http_* |
任意请求头的值 $http_user_agent, $http_referer,$http_cookie |
$cookie_* |
获取特定 Cookie 值(如 $cookie_sessionid) |
$arg_* |
获取特定 URL 参数 (如 $arg_id 获取 ?id=123 中的 123) |
$document_root |
当前请求的 root 或 alias 指令指定的根目录路径 |
$realpath_root |
$document_root 的绝对路径(符号链接解析后) |