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";
}
}
十四、总结 #
本章我们学习了:
- rewrite指令:基本语法和标志位
- 正则表达式:捕获组和命名捕获
- 重定向配置:301和302重定向
- if条件判断:条件运算符和示例
- set指令:变量赋值和拼接
- 常用场景:隐藏index.php、强制HTTPS、域名跳转
- 框架伪静态:WordPress、Laravel
- map指令:URL映射和设备适配
- 调试技巧:rewrite_log和调试日志
掌握Rewrite重写后,让我们进入下一章,学习WebSocket代理!
最后更新:2026-03-27