Nginx学习笔记(九)—— Nginx Rewrite深度解析

发布于:2025-08-16 ⋅ 阅读:(18) ⋅ 点赞:(0)

🔀🔀 Nginx Rewrite深度解析

📌📌 一、Rewrite核心价值与原理
匹配成功
匹配失败
原始请求
Rewrite规则
执行重写操作
直接访问
新URL/路径
后续处理

核心作用

  • 🔧 URL美化:将复杂动态URL转为静态友好地址
  • 🔀 路径校正:自动补全缺失斜杠或修正大小写
  • 🚚 流量调度:根据条件路由到不同后端服务
  • 🔒 安全加固:隐藏敏感路径参数
  • 📶 访问控制:基于规则拒绝恶意请求
⚙⚙⚙️ 二、Rewrite配置语法

基础指令结构

rewrite regex replacement [flag];

核心参数解析

参数 必需 描述
regex Perl兼容正则表达式
replacement 替换后的目标字符串
flag 控制重写行为(详见下表)

标志位详解

Flag 作用 执行特点
last 终止当前location重写 用新URI重新搜索location
break 终止所有重写 在当前location继续执行
redirect 302临时重定向 浏览器地址栏变化
permanent 301永久重定向 浏览器缓存重定向
🔧🔧🔧 三、核心指令详解
1️⃣ rewrite指令
location /blog/ {
    # 将 /blog/123 → /posts?id=123
    rewrite ^/blog/(\d+)$ /posts?id=$1 last;
}
2️⃣ if条件判断
# 语法:if (condition) { ... }
location / {
    # 移动设备重定向
    if ($http_user_agent ~* "mobile|android") {
        rewrite ^(.*)$ /mobile$1 last;
    }
    
    # 非法IP拦截
    if ($remote_addr = "202.96.134.33") {
        return 403;
    }
}

条件运算符

  • =: 字符串相等
  • !=: 字符串不等
  • ~: 正则匹配(区分大小写)
  • ~*: 正则匹配(不区分大小写)
  • -f: 文件存在
  • -d: 目录存在
3️⃣ set变量设置
location / {
    set $site_version "v2";
    
    # 根据时间设置版本
    if ($time_hour > 18) {
        set $site_version "nightly";
    }
    
    rewrite ^/(.*)$ /$site_version/$1;
}
4️⃣ breakreturn控制流
location /api/ {
    # 终止重写链
    rewrite ^/api/v1/(.*)$ /legacy/$1 break;
    rewrite ^/api/v2/(.*)$ /new/$1 break;
    
    # 直接返回响应
    return 200 "API Endpoint";
}
🔄🔄🔄 四、实战配置案例
🌐 案例1:域名标准化
server {
    listen 80;
    server_name example.com www.example.com;
    
    # 统一主域名
    if ($host != 'example.com') {
        rewrite ^(.*)$ https://example.com$1 permanent;
    }
    
    # HTTP转HTTPS
    if ($scheme = http) {
        rewrite ^(.*)$ https://$host$1 permanent;
    }
}
📁 案例2:路径重写
location /ecommerce {
    # 智能路径重写
    rewrite ^/ecommerce/product-(\d+)$ /products/$1 last;
    rewrite ^/ecommerce/category-(.*)$ /categories/$1 last;
    rewrite ^/ecommerce/(.*)$ /shop/$1 last;
}
🛡 案例3:防盗链实现
location ~* \.(jpg|png|gif)$ {
    # 允许空Referer和自身域名
    valid_referers none blocked server_names *.example.com;
    
    # 非法引用重写到水印图
    if ($invalid_referer) {
        rewrite ^(.*)$ /watermark$1 break;
    }
}
🔀 案例4:多级路径合并
location /archive {
    # /archive/2023/05/01 → /posts?date=2023-05-01
    rewrite ^/archive/(\d+)/(\d+)/(\d+)$ /posts?date=$1-$2-$3 last;
    
    # /archive/cat/tech → /category?name=tech
    rewrite ^/archive/cat/(\w+)$ /category?name=$1 last;
}
📊📊 五、全局变量应用

常用内置变量

变量 描述 应用场景
$args 请求参数 保留原始参数
$request_uri 完整原始URI 带参数的完整重定向
$scheme 协议类型 HTTP/HTTPS转换
$http_user_agent 浏览器UA 设备适配
$http_referer 来源页面 防盗链检测
$remote_addr 客户端IP 访问控制

高级变量应用

location /analytics {
    # 带参数重定向:/analytics?page=home → /stats/home
    if ($args ~* "page=(.*)") {
        set $page $1;
        rewrite ^ /stats/$page? last;
    }
    
    # 保留原始参数:/search?q=nginx → /v2/search?q=nginx
    rewrite ^/search(.*)$ /v2/search$1?$args last;
}
⚠⚠⚠️ 六、高阶技巧与陷阱规避
🔧 技巧1:递归重写控制
location /download {
    # 最多递归10次
    rewrite_by_depth 10;
    
    # 文件版本清理
    rewrite "^/(.*)-v\d+\.(.*)$" /$1.$2 last;
}
🎭 技巧2:动态重写映射
# 创建重写映射表
map $uri $new_uri {
    default          "";
    ~^/old-blog/(.*) /new-blog/$1;
    ~^/shop/(.*)     /ecommerce/$1;
}

server {
    location / {
        if ($new_uri) {
            rewrite ^ $new_uri last;
        }
    }
}
📶 技巧3:AB测试路由
split_clients $request_uri $variant {
    50%     "groupA";
    50%     "groupB";
}

location / {
    rewrite ^/(.*)$ /$variant/$1 last;
}
❌ 常见陷阱解决方案:
  1. 循环重定向问题
# 添加终止条件
location / {
    if ($request_uri ~ "^/(.*)/$") {
        set $has_slash on;
    }
    if ($has_slash != on) {
        rewrite ^(.*)$ $1/ permanent;
    }
}
  1. 正则性能优化
# 优化前(低效)
rewrite ^/([0-9]{4})/([0-9]{2})/([0-9]{2})/(.*)$ /archive/$1$2$3/$4;

# 优化后(高效)
rewrite ^/(\d{4})/(\d{2})/(\d{2})/(.+)$ /archive/$1$2$3/$4 last;
  1. 变量未定义错误
# 安全访问变量
if ($arg_id = "") {
    set $arg_id "default";
}
rewrite ^/(.*)$ /item/$arg_id last;
📊📊 七、调试与监控方案

专用日志格式

log_format rewrite_log '$remote_addr - $request_uri '
                       '-> $uri [$status] '
                       '"$http_user_agent"';

server {
    rewrite_log on;  # 启用重写日志
    error_log /var/log/nginx/rewrite.log notice;
    
    location / {
        access_log /var/log/nginx/rewrite_access.log rewrite_log;
    }
}

诊断命令集

# 实时跟踪重写流程
tail -f /var/log/nginx/rewrite.log

# 测试重写规则
curl -I http://example.com/test-path

# 重写规则语法检查
nginx -t

性能监控

# 统计重写次数
grep -c "rewritten" /var/log/nginx/rewrite.log

# 查找最耗时的重写
awk '/rewrite_log/ {print $NF,$7}' access.log | sort -nr

📚📚 总结图谱

Rewrite核心
语法基础
指令系统
应用场景
性能优化
regex/replacement
flag控制
if/set/break
return
路径重写
域名跳转
防盗链
递归控制
映射表
AB测试

网站公告

今日签到

点亮在社区的每一天
去签到