Nginx之URL重写

1.URL重写模块(Rewrite)

摘要

这个模块允许使用正则表达式重写URI(需PCRE库),并且可以根据相关变量重定向和选择不同的配置。如果这个指令在server字段中指定,那么将在被请求的location确定之前执行,如果在指令执行后所选择的location中有其他的重写规则,那么它们也被执行。如果在location中执行这个指令产生了新的URI,那么location又一次确定了新的URI。这样的循环可以最多执行10次,超过以后nginx将返回500错误。

指令
break

语法:break  
默认值:none  
使用字段:server, location, if  
完成当前设置的规则,停止执行其他的重写指令。  
示例:

1
2
3
4
if  ($slow) {
   limit_rate  10k;
   break ;
}
if

语法:if (condition) { … }  
默认值:none  
使用字段:server, location  
注意:在使用if指令之前请查看if is evil page并且尽量考虑用try_files代替。  
判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。  
可以在判断语句中指定下列值:

  • 一个变量的名称;不成立的值为:空字符传”“或者一些用“0”开始的字符串。

  • 一个使用=或者!=运算符的比较语句。

  • 使用符号~*和~模式匹配的正则表达式:

  • ~为区分大小写的匹配。

  • ~*不区分大小写的匹配(firefox匹配FireFox)。

  • !~和!~*意为“不匹配的”。

  • 使用-f和!-f检查一个文件是否存在。

  • 使用-d和!-d检查一个目录是否存在。

  • 使用-e和!-e检查一个文件,目录或者软链接是否存在。

  • 使用-x和!-x检查一个文件是否为可执行文件。

正则表达式的一部分可以用圆括号,方便之后按照顺序用$1-$9来引用。  
示例配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if  ($http_user_agent ~ MSIE) {
   rewrite  ^(.*)$   /msie/ $1   break ;
}
                                                                                                                                                        
if  ($http_cookie ~*  "id=([^;] +)(?:;|$)"  ) {
   set   $ id   $1;
}
                                                                                                                                                        
if  ($request_method = POST ) {
   return  405;
}
                                                                                                                                                        
if  (!-f $request_filename) {
   break ;
   proxy_pass  http: //127 .0.0.1;
}
                                                                                                                                                        
if  ($slow) {
   limit_rate  10k;
}
                                                                                                                                                        
if  ($invalid_referer) {
   return    403;
}
                                                                                                                                                        
if  ($args ~ post=140){
   rewrite ^ http: //example .com/ permanent;
}

内置变量$invalid_referer用指令valid_referers指定。

return

语法:return code  
默认值:none  
使用字段:server, location, if  
这个指令结束执行配置语句并为客户端返回状态代码,可以使用下列的值:204,400,402-406,408,410, 411, 413, 416与500-504。此外,非标准代码444将关闭连接并且不发送任何的头部。

rewrite

语法:rewrite regex replacement flag  
默认值:none  
使用字段:server, location, if  
按照相关的正则表达式与字符串修改URI,指令按照在配置文件中出现的顺序执行。  
可以在重写指令后面添加标记。  
如果替换的字符串以http://开头,请求将被重定向,并且不再执行多余的rewrite指令。  
尾部的标记(flag)可以是以下的值:

  • last - 完成重写指令,之后搜索相应的URI或location。

  • break - 完成重写指令。

  • redirect - 返回302临时重定向,如果替换字段用http://开头则被使用。

  • permanent - 返回301永久重定向。

注意如果一个重定向是相对的(没有主机名部分),nginx将在重定向的过程中使用匹配server_name指令的“Host”头或者server_name指令指定的第一个名称,如果头不匹配或不存在,如果没有设置server_name,将使用本地主机名,如果你总是想让nginx使用“Host”头,可以在server_name使用“*”通配符(查看http核心模块中的server_name)。例如:

1
2
3
rewrite  ^( /download/ .*) /media/ (.*)\..*$  $1 /mp3/ $2.mp3  last;
rewrite  ^( /download/ .*) /audio/ (.*)\..*$  $1 /mp3/ $2.ra   last;
return    403;

但是如果我们将其放入一个名为/download/的location中,则需要将last标记改为break,否则nginx将执行10次循环并返回500错误。

1
2
3
4
5
location  /download/  {
   rewrite  ^( /download/ .*) /media/ (.*)\..*$  $1 /mp3/ $2.mp3   break ;
   rewrite  ^( /download/ .*) /audio/ (.*)\..*$  $1 /mp3/ $2.ra    break ;
   return    403;
}

如果替换字段中包含参数,那么其余的请求参数将附加到后面,为了防止附加,可以在最后一个字符后面跟一个问号:

1
rewrite  ^ /users/ (.*)$   /show ?user=$1?  last;

注意:大括号({和}),可以同时用在正则表达式和配置块中,为了防止冲突,正则表达式使用大括号需要用双引号(或者单引号)。例如要重写以下的URL:

1
/photos/123456

为:

1
/path/to/photos/12/1234/123456 .png

则使用以下正则表达式(注意引号):

1
rewrite   "/photos/([0-9] {2})([0-9] {2})([0-9] {2})"  /path/to/photos/ $1/$1$2/$1$2$3.png;

如果指定一个“?”在重写的结尾,Nginx将丢弃请求中的参数,即变量$args,当使用$request_uri$uri&$args时可以在rewrite结尾使用“?”以避免nginx处理两次参数串。  
在rewrite中使用$request_uri将www.example.com重写到example.com:

1
2
3
4
server {
    server_name www.example.com;
    rewrite ^ http: //example .com$request_uri? permanent;
}

同样,重写只对路径进行操作,而不是参数,如果要重写一个带参数的URL,可以使用以下代替:

1
2
3
if  ($args ^~ post=100){
   rewrite ^ http: //example .com /new-address .html? permanent;
}

注意$args变量不会被编译,与location过程中的URI不同(参考http核心模块中的location)。

rewrite_log

语法:rewrite_log on | off  
默认值:rewrite_log off  
使用字段:server, location, if  
变量:无  
启用时将在error log中记录notice 标记的重写日志。

set

语法:set variable value  
默认值:none  
使用字段:server, location, if  
指令设置一个变量并为其赋值,其值可以是文本,变量和它们的组合。  
你可以使用set定义一个新的变量,但是不能使用set设置$http_xxx头部变量的值。

uninitialized_variable_warn

语法:uninitialized_variable_warn on|off  
默认值:uninitialized_variable_warn on  
使用字段:http, server, location, if  
开启或关闭在未初始化变量中记录警告日志。  
事实上,rewrite指令在配置文件加载时已经编译到内部代码中,在解释器产生请求时使用。  
这个解释器是一个简单的堆栈虚拟机,如下列指令:

1
2
3
4
5
6
7
8
location  /download/  {
   if  ($forbidden) {
     return    403;
   }
   if  ($slow) {
     limit_rate  10k;
   }
   rewrite  ^/(download/.*) /media/ (.*)\..*$  /$1 /mp3/ $2.mp3   break ;

将被编译成以下顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
variable $forbidden
checking to zero
recovery 403
completion of entire code
variable $slow
checking to zero
checkings of regular excodession
copying  "/"
copying $1
copying  "/mp3/"
copying $2
copying  ".mp3"
completion of regular excodession
completion of entire sequence

注意并没有关于limit_rate的代码,因为它没有提及ngx_http_rewrite_module模块,“if”块可以类似”location”指令在配置文件的相同部分同时存在。  
如果$slow为真,对应的if块将生效,在这个配置中limit_rate的值为10k。  
指令:

1
rewrite  ^/(download/.*) /media/ (.*)\..*$  /$1 /mp3/ $2.mp3   break ;

如果我们将第一个斜杠括入圆括号,则可以减少执行顺序:

1
rewrite  ^( /download/ .*) /media/ (.*)\..*$  $1 /mp3/ $2.mp3   break ;

之后的顺序类似如下:

1
2
3
4
5
6
7
checking regular excodession
copying $1
copying  "/mp3/"
copying $2
copying  ".mp3"
completion of regular excodession
completion of entire code
2.简单案例
注,由于配置文件内容较多,为了让大家看着方便,我们备份一下配置文件,打开一个新的配置文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@nginx ~] # cd /etc/nginx/
[root@nginx nginx] # mv nginx.conf nginx.conf.proxy
[root@nginx nginx] # cp nginx.conf.bak nginx.conf
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
       listen       80;
       server_name  localhost;
       #charset koi8-r;
       #access_log  logs/host.access.log  main;
       location / {
           root   html;
           index  index.html index.htm;
           rewrite ^ /bbs/ (.*)$ http: //192 .168.18.201 /forum/ $1;
       }
}
准备forum目录与测试文件
1
2
3
4
5
6
7
[root@web1 ~] # cd /var/www/html/
[root@web1 html] # ls
index.html
[root@web1 html] # mkdir forum
[root@web1 html] # cd forum/
[root@web1 forum] # vim index.html
<h1>forum page!< /h1 >

测试一下


好了,下面我们来测试一下rewrite重写。

3.重新加载一下配置文件
1
2
3
4
[root@nginx 63] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
重新载入 nginx:                                           [确定]

4.测试一下


注,大家可以从图中看出,status code 302指的是临时重定向,那就说明我们rewrite重写配置成功。大家知道302是临时重定向而301是永久重定向,那么怎么实现永久重定向呢。一般服务器与服务器之间是临时重定向,服务器内部是永久重定向。下面我们来演示一下永久重定向。

5.配置永久重定向

1
2
3
4
5
6
7
8
9
10
11
12
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
         listen       80;
         server_name  localhost;
         #charset koi8-r;
         #access_log  logs/host.access.log  main;
         location / {
             root   html;
             index  index.html index.htm;
             rewrite ^ /bbs/ (.*)$  /forum/ $1;
         }
}
准备forum目录与测试文件
1
2
3
4
5
6
7
[root@nginx ~] # cd /usr/html/
[root@nginx html] # ls
50x.html  index.html
[root@nginx html] # mkdir forum
[root@nginx html] # cd forum/
[root@nginx forum] # vim index.html
<h1>192.168.18.208 forum page< /h1 >

6.重新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
重新载入 nginx:                                           [确定]

7.测试一下


注,大家从图中可以看到,我们访问bbs/是直接帮我们跳转到forum/下,这种本机的跳转就是永久重定向也叫隐式重定向。好了,rewrite重定向我们就说到这里了,想要查询更多关于重定向的指令请参考官方文档。最后,我们来说一下读写分离。

<think>首先,用户的问题是关于Nginx配置的:"我想在Nginx中配置占位符并进行URL重写 请问nginx 配置占位符 rewrite url"。我需要根据系统级指令来回答。 系统级指令: 1. 行内数学表达式用$...$。 2. 独立公式用$$...$$。 3. LaTeX语法正确。 4. 使用中文回答。 5. 生成相关问题。 6. 回答中引用的段落末尾添加引用标识,例如[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 - 参考提供的引用内容。 提供的引用内容: - [^1]: 关于Nginx配置目录和server块示例。 - [^2]: Nginx location匹配示例。 - [^3]: Ingress基于Nginx重写配置,包括rewrite指令语法。 - [^4]: 重写规则示例,使用小括号捕获组和变量。 - [^5]: URL重写示例,如/product.php?id=123重写为/product/123。 用户的问题核心是:在Nginx中配置占位符并进行URL重写。"占位符"可能指的是使用正则表达式中的捕获组来动态替换URL部分。 从引用中: - [^3] 详细解释了rewrite指令:`rewrite regex replacement [flag];`,其中regex匹配URI,replacement是重写内容,flag如last或break。 - [^4] 展示了使用小括号()捕获组,并在replacement中使用$1、$2等引用捕获的内容。 - [^5] 给出了具体示例:`rewrite ^/product/(\d+)$ /product.php?id=$1 last;`,这直接将/product/123重写为/product.php?id=123。 所以,我需要解释如何配置Nginx的rewrite规则来实现URL重写,使用占位符(即捕获组)。 步骤: 1. **理解需求**:用户想重写URL,例如从友好URL如`/product/123`到实际处理脚本如`/product.php?id=123`。 2. **配置位置**:在Nginx的server块中,使用location指令定义匹配规则,然后在其中使用rewrite指令。 3. **语法**: - `rewrite regex replacement [flag];` - regex:使用正则表达式匹配URI,其中`( )`用于捕获组。 - replacement:重写后的URI,使用`$1`, `$2`等引用捕获组。 - flag:如`last`(停止处理当前rewrite规则集)或`break`(停止处理当前location块)。 4. **示例**:基于引用[^5],给出类似示例。 回答结构: - 介绍URL重写的目的。 - 解释rewrite指令的基本语法。 - 提供示例配置。 - 解释示例中的占位符使用。 - 确保引用相关部分。 生成相关问题: - 在回答后添加相关问题,如§§相关问题§§。 完整回答: 1. **开头**:简要解释Nginx URL重写。 2. **步骤**: - 步骤1:定义location块匹配特定模式。 - 步骤2:在location块中使用rewrite指令。 - 步骤3:使用正则表达式捕获占位符。 - 步骤4:在replacement中引用占位符。 3. **示例**:提供具体代码示例。 4. **引用**:在解释时自然添加引用标识。 5. **相关问题**:最后生成2-3个相关问题。 相关问题想法: 1. 如何测试Nginx的rewrite规则? 2. rewrite规则中的不同flag有什么区别? 3. 如何处理更复杂的URL重写场景? 确保中文回答。</think>### Nginx 配置占位符与 URL 重写指南 在 Nginx 中配置 "占位符" 并进行 URL 重写,本质上是利用正则表达式的 **捕获组**(用小括号 `()` 定义)来动态匹配 URI 中的变量部分(如 ID、路径参数),并在重写时通过 `$1`, `$2` 等引用这些占位符。这常用于实现 SEO 友好的 URL(如 `/product/123` 重写为 `/product.php?id=123`)或路径规范化。以下是逐步配置方法,基于 Nginx 的 `rewrite` 指令实现。我将参考提供的引用内容确保可靠性。 --- #### 步骤 1: 理解 rewrite 指令语法 Nginx 的 `rewrite` 指令基本语法为: ``` rewrite regex replacement [flag]; ``` - **regex**:正则表达式,用于匹配请求的 URI。使用小括号 `()` 定义捕获组(占位符),例如 `(\d+)` 匹配数字。 - **replacement**:重写后的 URI,通过 `$1`, `$2` 等引用 regex 中的捕获组(`$1` 表示第一个 `()` 的内容)。 - **flag**:可选标志,如 `last`(重写后继续匹配其他规则)、`break`(停止处理当前规则集)、`redirect`(返回 302 重定向)或 `permanent`(返回 301 重定向)[^3]。 关键点:占位符通过正则表达式的捕获组实现,并在 `replacement` 中引用。例如,在 `^/product/(\d+)$` 中,`(\d+)` 是一个占位符,匹配数字序列,重写时用 `$1` 引用它[^4][^5]。 --- #### 步骤 2: 配置 location 块和 rewrite 规则 在 Nginx 配置文件(如 `/etc/nginx/conf.d/default.conf`)的 `server` 块中,添加 `location` 指令定义匹配范围,并在其中使用 `rewrite`。以下是常见场景的示例配置: **示例 1: 基本占位符重写(如 /product/123 到 /product.php?id=123)** ```nginx server { listen 80; server_name example.com; # 替换为你的域名或 IP location / { root /usr/share/nginx/html; index index.html; } # 使用占位符重写 URL location ~ ^/product/(\d+)$ { rewrite ^/product/(\d+)$ /product.php?id=$1 last; # $1 引用第一个捕获组 } } ``` - **解释**: - `location ~ ^/product/(\d+)$`:使用正则匹配 URI,如 `/product/123`。其中 `(\d+)` 是占位符,捕获数字部分。 - `rewrite ^/product/(\d+)$ /product.php?id=$1 last;`:将请求重写为 `/product.php?id=123`,`$1` 动态插入捕获的数字。`last` 标志表示重写后继续匹配其他规则。 - **效果**:用户访问 `http://example.com/product/123` 时,Nginx 内部处理为 `http://example.com/product.php?id=123`,URL 地址栏不变[^5]。 **示例 2: 多占位符重写(如 /category/5/item/42 到 /item.php?cat_id=5&item_id=42)** ```nginx server { listen 80; server_name example.com; location ~ ^/category/(\d+)/item/(\d+)$ { rewrite ^/category/(\d+)/item/(\d+)$ /item.php?cat_id=$1&item_id=$2 break; # $1 和 $2 引用两个占位符 } } ``` - **解释**: - `(\d+)` 定义两个占位符,分别匹配 `category/` 和 `item/` 后的数字。 - 重写时用 `$1` 和 `$2` 引用它们,`break` 标志确保停止处理当前规则集,避免循环[^3][^4]。 **示例 3: 带前缀的占位符重写(如 /api/users/100 到 /index.php?module=users&id=100)** ```nginx server { listen 80; server_name api.example.com; location ^~ /api/ { # ^~ 表示优先匹配此前缀 rewrite ^/api/(\w+)/(\d+)$ /index.php?module=$1&id=$2 last; } } ``` - **解释**:`(\w+)` 捕获字母数字字符串(如 "users"),`(\d+)` 捕获数字(如 "100"),重写时用 `$1` 和 `$2` 插入[^2][^4]。 --- #### 关键注意事项 1. **正则表达式语法**: - 使用 `()` 定义占位符,例如 `(\d+)` 匹配数字,`(\w+)` 匹配字母数字。 - 在 `replacement` 中,`$1` 引用第一个占位符,`$2` 引用第二个,依此类推[^4]。 2. **flag 选择**: - 用 `last` 或 `break` 避免重写循环(推荐在内部重写时使用)。 - 用 `redirect` 或 `permanent` 实现外部重定向(URL 地址栏会变化)[^3]。 3. **测试与调试**: - 修改配置后,运行 `nginx -t` 测试语法。 - 启用 `rewrite_log on;` 并在 `error_log` 中查看重写日志(如 `error_log logs/rewrite.log notice;`)[^4]。 4. **性能优化**: - 将重写规则放在精确匹配的 `location` 块中(如 `location ~` 或 `location ^~`),减少不必要的正则计算[^2]。 > 参考说明:NginxURL 重写常用于 Ingress 控制器或静态站点优化,本质是修改 `server` 块中的 `location` 指令。捕获组机制 (`$1`, `$2`) 允许动态处理路径参数,提升灵活性和可读性[^3][^5]。如果配置在 `conf.d` 目录下,确保重启 Nginx 生效(`systemctl restart nginx`)[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮生(FS)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值