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. 测试先行:在生产环境部署前,务必在测试环境中充分验证你的规则。

五、结语

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

相关推荐
星野爱8951 小时前
远程控制哪家安全性更高?ToDesk、UU远程、向日葵隐私屏深度测评!
linux·运维·网络
ALINX技术博客1 小时前
【黑金云课堂】FPGA技术教程Linux开发:系统定制
linux·运维·fpga开发
bmjwin2 小时前
一个监控脚本实时追踪记录进程隐秘连接ip方法
运维·服务器
霁月的小屋2 小时前
Docker 工程化实践(六):Docker Compose 管理多容器应用
运维·docker·容器
luyun0202023 小时前
论坛里的小工具,吾爱出品
运维·服务器·windows
Miao121313 小时前
工程交付指标入门:如何重新掌控软件交付
大数据·运维·devops
码云骑士3 小时前
82-微调模型评估-自动化评测-人工评测-A-B测试实战
运维·python·自动化
涛声依旧393163 小时前
运维项目:InnoAI SQL 助手
运维·数据库·sql
养海绵宝宝的小蜗4 小时前
LVS(Linux Virtual Server)项目知识点总结
linux·运维·lvs
joopthd5 小时前
打破进口垄断:TDLAS/UV-DOAS/FTIR 全光谱检测国产器件全产业链布局(江苏旭海光电技术梳理)
运维·人工智能·uv·激光气体检测