Nginx-UrlRewrite

一、引言:URL不只是地址,更是用户体验与安全的门面

你是否遇到过这些问题:

  • 网站改版后,旧链接全部失效,导致用户收藏夹和搜索引擎索引"404"?
  • 想要将所有 HTTP 流量强制跳转到 HTTPS,但又不想在代码里写一堆判断?
  • 希望隐藏真实的后端接口路径(如 /api/v1/user),对外暴露更简洁的 URL(如 /user)?
  • 需要根据请求参数或客户端类型(PC/手机)返回不同的内容?

这些问题的答案,都指向同一个强大的 Nginx 功能------URL Rewrite(URL重写)

它就像一个智能的"交通指挥官",能在请求到达后端应用之前,对 URL 进行修改、重定向或内部跳转。本文将带你从语法基础到十大经典场景,彻底掌握这项核心技能。

💡 核心价值
精通 URL Rewrite,你就能优雅地处理网站迁移、提升SEO、增强安全性,并构建极其灵活的路由规则


二、核心基石:rewrite 指令详解

Nginx 的 URL 重写功能由 ngx_http_rewrite_module 模块提供,其核心是 rewrite 指令。

基本语法

复制代码
rewrite <regex> <replacement> [flag];
  • <regex>: Perl 兼容的正则表达式 (PCRE),用于匹配请求的 URI。
  • <replacement> : 重写后的 URI。可以使用 $1, $2... 来引用正则中的捕获组。
  • [flag]: 可选标志位,控制重写后的行为。这是最容易混淆但也最关键的部分。

四大核心标志位(Flag)深度解析

标志位 作用 类比
last 停止当前 server 块内的 rewrite 检查,并重新搜索 location "内部重写"。浏览器地址栏不变,服务器内部用新 URI 重新匹配 location
break 停止当前 server 块内的 rewrite 检查,不再重新搜索 location "内部中断"。直接使用当前重写后的 URI 处理请求,通常用于静态文件映射。
redirect 返回 302 临时重定向 "临时搬家"。浏览器地址栏会变成新的 URL。
permanent 返回 301 永久重定向 "永久搬家"。浏览器和搜索引擎会更新书签和索引。

关键区别lastbreak内部操作 ,对用户不可见;redirectpermanent外部重定向,会触发浏览器跳转。


三、十大经典应用场景实战

场景一:HTTP 强制跳转 HTTPS(SEO友好)

复制代码
server {
    listen 80;
    server_name www.example.com;
    # 永久重定向到HTTPS
    return 301 https://$server_name$request_uri;
    # 或者用rewrite
    # rewrite ^(.*)$ https://$server_name$1 permanent;
}

最佳实践 :优先使用 return 指令,因为它更高效、语义更清晰。

场景二:网站改版,旧URL平滑迁移(301重定向)

复制代码
# 旧文章页: /blog/post?id=123
# 新文章页: /article/123.html
rewrite ^/blog/post$ /article/$arg_id.html? permanent;

# 更复杂的路径映射
rewrite ^/old-category/(.*)$ /new-category/$1 permanent;

注意$arg_id 是 Nginx 内置变量,用于获取 id 参数的值。

场景三:隐藏真实路径,美化URL(内部重写)

复制代码
# 对外暴露 /user/123
# 内部实际请求 /api/v1/user?id=123
location /user/ {
    rewrite ^/user/(\d+)$ /api/v1/user?id=$1 last;
    proxy_pass http://backend;
}

用户看到的是干净的 /user/123,后端收到的是带参数的传统接口。

场景四:根据设备类型(PC/手机)返回不同内容

复制代码
# 检测User-Agent
if ($http_user_agent ~* "(mobile|android|iphone|ipod)") {
    rewrite ^(.*)$ $1/mobile/ last;
}

location / {
    root /var/www/html;
    # PC用户访问 /index.html
    # 手机用户访问 /mobile/index.html
}

场景五:阻止特定爬虫或恶意请求

复制代码
if ($http_user_agent ~* "bad-bot|spam-crawler") {
    return 403;
}

# 阻止访问 .env, .git 等敏感文件
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

场景六:统一URL格式(带/或不带斜杠)

复制代码
# 将 /page 重定向到 /page/ (目录形式)
rewrite ^([^.]*[^/])$ $1/ permanent;

场景七:实现多级域名到路径的映射

复制代码
# user1.example.com -> example.com/user/user1
# user2.example.com -> example.com/user/user2
if ($host ~* "^([a-z0-9-]+)\.example\.com$") {
    set $username $1;
    rewrite ^(.*)$ /user/$username$1 last;
}

场景八:API版本控制

复制代码
# /v2/api/... -> /api/v2/...
rewrite ^/v2/(.*)$ /api/v2/$1 last;

场景九:防盗链(防止图片被其他网站直接引用)

复制代码
location ~* \.(jpg|jpeg|png|gif)$ {
    valid_referers none blocked *.yourdomain.com yourdomain.com;
    if ($invalid_referer) {
        return 403;
        # 或者返回一个占位图
        # rewrite ^/.*$ /images/placeholder.png break;
    }
}

场景十:配合动静分离,处理SPA路由

复制代码
location / {
    root /var/www/app;
    try_files $uri $uri/ @rewrites;
}

location @rewrites {
    # 所有未匹配到文件的请求,都重写到 index.html
    rewrite ^(.*)$ /index.html last;
}

这是 Vue/React 等单页应用(SPA)在 history 模式下的标准配置。


四、性能与最佳实践

  1. 慎用 if :Nginx 官方文档有句名言:"If is Evil "。if 指令在 location 块中行为复杂,容易出错。能用 location 匹配就不要用 if
  2. 优先 return :对于简单的重定向(如 301/302),returnrewrite 更高效。
  3. 避免循环 :确保你的重写规则不会导致无限循环。例如,重写 /old/new,但 /new 又被重写回 /old
  4. 测试先行:在生产环境部署前,务必在测试环境中充分验证你的规则。

五、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
qq_白羊座1 小时前
CI/CD 与 DevOps 四
运维·ci/cd·devops
杨云龙UP2 小时前
Oracle Recycle Bin 回收站详解:DROP TABLE 后还能找回吗?
linux·运维·数据库·sql·mysql·oracle
GISer_Jing2 小时前
AI数字营销全链路自动化闭环_CSDN
运维·人工智能·自动化
蠢货爱好者2 小时前
Docker基础操作
运维·docker·容器
Drache_long3 小时前
DevOps
运维·devops
不像程序员的程序媛3 小时前
nginx日志配置
运维·nginx
hopsky3 小时前
phoenix docker 启动
运维·docker·容器
又熟了3 小时前
乌班图Ubuntu安装
linux·运维·ubuntu
无情的西瓜皮4 小时前
MCP协议实战:从零搭建一个AI Agent工具服务器
运维·服务器·python