Nginx Rewrite重写 #

一、Rewrite概述 #

Nginx的Rewrite模块允许你使用正则表达式重写URL,实现URL重定向、域名跳转等功能。

1.1 Rewrite的作用 #

  • URL美化
  • 旧URL重定向到新URL
  • 域名跳转
  • 隐藏真实路径
  • SEO优化

二、rewrite指令 #

2.1 基本语法 #

nginx
rewrite regex replacement [flag];
参数 说明
regex 正则表达式匹配
replacement 替换字符串
flag 标志位

2.2 基本示例 #

nginx
location / {
    rewrite ^/old-path$ /new-path permanent;
    rewrite ^/user/(\d+)$ /profile?id=$1 last;
    rewrite ^/download/(.*)$ /files/$1 redirect;
}

2.3 flag标志位 #

标志 说明
last 停止处理,重新搜索location
break 停止处理,不再搜索location
redirect 返回302临时重定向
permanent 返回301永久重定向

2.4 last vs break #

last:

nginx
location / {
    rewrite ^/api/(.*)$ /backend/$1 last;
}

location /backend/ {
    proxy_pass http://backend_server;
}

break:

nginx
location /api/ {
    rewrite ^/api/(.*)$ /backend/$1 break;
    proxy_pass http://backend_server;
}

三、正则表达式 #

3.1 常用正则 #

表达式 说明
. 任意字符
\w 字母、数字、下划线
\d 数字
\s 空白字符
^ 开始
$ 结束
* 0次或多次
+ 1次或多次
? 0次或1次
n次
至少n次
n到m次
() 分组
[] 字符集
|

3.2 捕获组 #

nginx
rewrite ^/user/(\d+)$ /profile?id=$1 last;
rewrite ^/article/(\d+)/(\d+)$ /post?year=$1&month=$2 last;
rewrite ^/category/([^/]+)/([^/]+)$ /list?cat=$1&sub=$2 last;

3.3 命名捕获 #

nginx
rewrite ^/user/(?<id>\d+)$ /profile?id=$id last;
rewrite ^/article/(?<year>\d+)/(?<month>\d+)$ /post?year=$year&month=$month last;

3.4 大小写控制 #

nginx
rewrite ^/API/(.*)$ /api/$1 last;
rewrite (?i)^/api/(.*)$ /api/$1 last;
rewrite ^(?i)/api/(.*)$ /api/$1 last;

四、重定向配置 #

4.1 301永久重定向 #

nginx
rewrite ^/old-page$ /new-page permanent;
rewrite ^/old-site.com(.*)$ https://new-site.com$1 permanent;

4.2 302临时重定向 #

nginx
rewrite ^/maintenance$ /maintenance.html redirect;
rewrite ^/promo$ /campaign redirect;

4.3 return指令 #

nginx
return 301 https://example.com$request_uri;
return 302 /new-page;
return 301 https://www.example.com$request_uri;

4.4 域名跳转 #

nginx
server {
    listen 80;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 80;
    server_name www.example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name www.example.com;
    root /var/www/example.com;
}

五、if条件判断 #

5.1 if语法 #

nginx
if (condition) {
    ...
}

5.2 条件运算符 #

运算符 说明
= 等于
!= 不等于
~ 正则匹配(区分大小写)
~* 正则匹配(不区分大小写)
!~ 正则不匹配
!~* 正则不匹配(不区分大小写)
-f 文件存在
!-f 文件不存在
-d 目录存在
!-d 目录不存在
-e 文件/目录/链接存在
!-e 不存在
-x 可执行
!-x 不可执行

5.3 条件示例 #

nginx
if ($request_method = POST) {
    return 405;
}

if ($request_uri ~* "^/api/") {
    proxy_pass http://api_backend;
}

if ($http_user_agent ~* "bot|spider") {
    return 403;
}

if (!-f $request_filename) {
    rewrite ^(.*)$ /index.php?$1 last;
}

if ($args ~ "debug=1") {
    set $debug_mode 1;
}

5.4 多条件判断 #

nginx
set $redirect 0;

if ($host = "old.example.com") {
    set $redirect 1;
}

if ($scheme = "http") {
    set $redirect "${redirect}1";
}

if ($redirect = "11") {
    return 301 https://www.example.com$request_uri;
}

六、set指令 #

6.1 变量赋值 #

nginx
set $mobile_rewrite 0;

if ($http_user_agent ~* "mobile|android|iphone") {
    set $mobile_rewrite 1;
}

if ($mobile_rewrite = 1) {
    rewrite ^(.*)$ /mobile$1 last;
}

6.2 变量拼接 #

nginx
set $base "/var/www";
set $path $base$uri;

七、常用Rewrite场景 #

7.1 隐藏index.php #

nginx
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

7.2 强制HTTPS #

nginx
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

7.3 强制www #

nginx
server {
    listen 80;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 80;
    server_name www.example.com;
    return 301 https://www.example.com$request_uri;
}

7.4 移除www #

nginx
server {
    listen 80;
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

7.5 移除尾部斜杠 #

nginx
rewrite ^/(.*)/$ /$1 permanent;

7.6 添加尾部斜杠 #

nginx
rewrite ^([^.]*[^/])$ $1/ permanent;

7.7 移除.php扩展名 #

nginx
location / {
    try_files $uri $uri/ $uri.php?$query_string;
}

7.8 移除.html扩展名 #

nginx
location / {
    try_files $uri $uri/ $uri.html?$query_string;
}

7.9 规范化URL #

nginx
rewrite ^/products/([^/]+)/([^/]+)/?$ /products?category=$1&product=$2 last;
rewrite ^/blog/(\d{4})/(\d{2})/([^/]+)/?$ /blog/post?year=$1&month=$2&slug=$3 last;

7.10 API版本控制 #

nginx
rewrite ^/api/v1/(.*)$ /api/$1 last;
rewrite ^/api/v2/(.*)$ /api/v2/$1 last;

八、WordPress伪静态 #

nginx
location / {
    try_files $uri $uri/ /index.php?$args;
}

rewrite /wp-admin$ $scheme://$host$uri/ permanent;

location ~* ^/wp-content/uploads/.*\.php$ {
    deny all;
}

location ~* /wp-admin/.*\.php$ {
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

九、Laravel伪静态 #

nginx
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

location ~ /\.(?!well-known).* {
    deny all;
}

十、map指令 #

10.1 map语法 #

nginx
map source_variable destination_variable {
    default value;
    pattern value;
}

10.2 URL映射 #

nginx
map $uri $new_uri {
    default "";
    /old-page /new-page;
    /about-us /about;
    /contact-us /contact;
}

server {
    location / {
        if ($new_uri) {
            rewrite ^ $new_uri permanent;
        }
    }
}

10.3 移动端适配 #

nginx
map $http_user_agent $mobile_device {
    default "";
    "~*android" "android";
    "~*iphone" "iphone";
    "~*ipad" "ipad";
}

server {
    location / {
        if ($mobile_device) {
            rewrite ^(.*)$ /$mobile_device$1 last;
        }
    }
}

十一、调试Rewrite #

11.1 开启调试日志 #

nginx
error_log /var/log/nginx/error.log debug;
rewrite_log on;

11.2 查看重写日志 #

bash
tail -f /var/log/nginx/error.log | grep rewrite

11.3 测试正则表达式 #

bash
pcretest

十二、Rewrite最佳实践 #

12.1 避免死循环 #

nginx
location / {
    rewrite ^/api/(.*)$ /backend/$1 last;
}

location /backend/ {
    rewrite ^/backend/(.*)$ /api/$1 last;
}

上述配置会导致死循环,应避免。

12.2 优先使用return #

对于简单重定向,优先使用return:

nginx
return 301 https://example.com$request_uri;

12.3 使用try_files处理静态文件 #

nginx
location / {
    try_files $uri $uri/ @backend;
}

location @backend {
    proxy_pass http://backend;
}

12.4 避免在if中使用rewrite #

nginx
if ($host = "example.com") {
    rewrite ^ https://www.example.com$request_uri? permanent;
}

应改为:

nginx
server {
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

十三、完整配置示例 #

nginx
server {
    listen 80;
    server_name example.com www.example.com;
    
    rewrite ^/(.*)/$ /$1 permanent;
    
    rewrite ^/old-page$ /new-page permanent;
    rewrite ^/old-category/(.*)$ /new-category/$1 permanent;
    
    if ($host = "example.com") {
        return 301 https://www.example.com$request_uri;
    }
    
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;
    
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.example.com;
    
    root /var/www/example.com;
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    location ~ /\.(?!well-known).* {
        deny all;
    }
    
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

十四、总结 #

本章我们学习了:

  1. rewrite指令:基本语法和标志位
  2. 正则表达式:捕获组和命名捕获
  3. 重定向配置:301和302重定向
  4. if条件判断:条件运算符和示例
  5. set指令:变量赋值和拼接
  6. 常用场景:隐藏index.php、强制HTTPS、域名跳转
  7. 框架伪静态:WordPress、Laravel
  8. map指令:URL映射和设备适配
  9. 调试技巧:rewrite_log和调试日志

掌握Rewrite重写后,让我们进入下一章,学习WebSocket代理!

最后更新:2026-03-27