NGINX重写规则被用来改变客户端要求的URL的全部或部分。改变URL的主要动机是告知客户端,他们正在寻找的资源除了控制NGINX中执行页面的流程之外,还改变了其位置。NGINX中的返回
和重写
指令被用来重写URL。这两个指令都执行重写URL的相同功能。然而,重写指令比返回指令更强大,因为需要解析URL的复杂重写可以用重写指令来完成。
NGINX返回指令
返回指令必须在服务器
或 位置背景中声明,指定要重定向的 URL。
NGINX 返回指令在服务器环境中
在服务器背景下,返回指令非常有用,如果您已将您的网站迁移到一个新的域名,并且您希望将所有旧的 URL 重定向到新的域名。
1server {
2 listen 80;
3 server_name www.olddomain.com;
4 return 301 $scheme://www.newdomain.com$request_uri;
5}
在上面的服务器背景下,返回指令将网站的 URL 重定向到 www.olddomain.com. 当 NGINX 收到与 www.olddomain.com 相关的 URL 时,它会停止处理页面并向客户端发送一个 301 响应代码以及重写 URL。上面的返回指令中使用的两种变量是 $scheme 和 $request_uri。 变量 $scheme 用于定义 URL 方案(http 或 https),而变量 $request_uri 则包含完整的 URI 参数。
返回指令在位置背景下
在某些情况下,您可能希望重定向页面而不是重定向域. 位置块中的返回指令允许您重定向特定页面到新的位置。
1location = /tutorial/learning-nginx {
2 return 301 $scheme://example.com/nginx/understanding-nginx
3}
在上面的示例中,每当请求 URI 与模式 /tutorial/learning-nginx
完全匹配时,NGINX 都会将其重定向到新的位置 https://example.com/nginx/understanding-nginx/
您也可以重定向所有内容以获得特定路径到新的位置。 下面的示例显示如何重定向所有页面,这些页面属于 /tutorial
到 https://example.com/articles
。
1location /tutorial {
2 return 301 $scheme://example.com/articles
3}
NGINX 重写指令
我们还可以使用重写指令在NGINX中重写URL。像返回指令一样,重写指令也可以放在服务器环境中以及位置环境中。重写指令可以对URL进行复杂的区别,并从原始URL中获取没有相应的NGINX变量的元素,从而使其比返回指令更有用。
1rewrite regex replacement-url [flag];
- regex:基于PCRE的正规表达式,将用于对应到来的请求URI
- replacement-url:如果正规表达式与所请求的URI相匹配,则使用替换字符串来更改所请求的URI
- flag:旗的值决定是否需要进一步处理重写指令
请记住,重写指令只能返回301或302代码。
NGINX 重写指令示例
让我们快速检查一些重写规则,让您从重写一个简单的HTML页面开始到另一个URL:
1、重写静态页面
考虑一个场景,你想重写一个网页的URL说 https://example.com/nginx-tutorial
到 https://example.com/somePage.html
. 重写指令做同样是在下面的位置块。
1server {
2 ...
3 ...
4 location = /nginx-tutorial
5 {
6 rewrite ^/nginx-tutorial?$ /somePage.html break;
7 }
8 ...
9 ...
10}
** 解释:**
- 位置指令
location = /nginx-tutorial
告诉我们,位置块只会匹配包含准确前缀/nginx-tutorial
的 URL - NGINX 将搜索所请求的 URL
中的模式
^/nginx-tutorial?$
- 为了定义模式,字符 ^,?和 $ 都被用来使用,并且具有特殊含义
- **^**代表要匹配的字符串的开始
- ** **代表要匹配的字符串的尽头 ?? 代表非贪婪的修改器。
2、重写动态页面
现在考虑一个动态页面 https://www.exampleshop.com/user.php?id=11
动态部分是 id=11(userid)
. 我们希望 URL 被重写为 https://exampleshop.com/user/11
. 如果你有 10 个用户,那么每位用户需要 10 个重写规则,如果你遵循重写 URL 的最后方法。相反,可以捕捉 URL 元素的变量,并使用它们来构建一个单一的重写规则,这将照顾所有动态页面。
1server {
2 ...
3 ...
4 location = /user.php
5 {
6 rewrite user.php?id=$1 ^user/([0-9]+)/?$ break;
7 }
8 ...
9 ...
10}
** 解释:**
- 位置指令
location = /user
告诉 NGINX 将位置块与包含准确前缀/user
的 URL 匹配 - NGINX 将搜索所请求的 URL 中的模式
^user/([0-9]+)/?$
- 方位列表中的正规表达式 [0-9]+ 包含 0 和 9 之间的字符范围。 + 标志意味着匹配一个或多个前面的字符。 没有 + 标志,上面的正规表达式只匹配 1 个字符,如 5 或 8 但不匹配 25 或 44.
- 正规表达式中的 parenthesis ( ) 指向后方参考。 替代 URL `user.phpid?=$1
例如,如果 https://www.example.com/user/24
是输入 URL,那么用户 id 24 将与返回参考中的范围相匹配,从而产生以下替代: https://www.example.com/user.php?id=24
3、预先重写URL
让我们继续用另一个例子,我们希望URL https://www.example.com/user.php?user_name=john
重写到 https://www.example.com/user/login/john
。 与以前的重写规则不同,URL user_name=john
的动态部分现在包含字母字符的范围。 此场景的重写规则是以下:
1server {
2 ...
3 ...
4 location = /user.php
5 {
6 rewrite user.php?user_name=$1 ^user/login/([a-z]+)/?$ break;
7 }
8 ...
9 ...
10 }
** 解释:**
- 位置指令
location = /user/login/john
告诉 NGINX 将位置块与包含准确前缀/user/login/john
的 URL 匹配. - NGINX 将搜索所请求的 URL 中的模式
^user/login/([a-z]+)/?$
- 正规表达式中的方块(a-z]+ 包含从 a 到 z 的字符范围。 + 标志意味着匹配一个或多个前面的字符. 没有 + 标志,上述正规表达式只会匹配 1 个字符,如 c 或 c,但不会匹配 john 或 doe
- 正规表达式中的 parenthesis ( ) 会
例如,如果输入的 URL 是 https://www.example.com/user/login/john
,那么用户名john
将匹配返回参考中的范围,从而产生以下替代: https://www.example.com/user.php?user_name=john
4、重写多重回归引用
在这个例子中,我们还会发现如何使用多个后引用来重写 URL。假设输入 URL 是 https://example.com/tutorial/linux/wordpress/file1
,我们还想重写 URL 到 https://example.com/tutorial/linux/cms/file1.php
. 如果您仔细观察输入 URL,它开始于 /tutorial
,然后在路径中的某个地方,字符串 wordpress 需要被字符串 cms 取代。 此外,文件扩展(php)也需要附加到文件名的末尾。 这个场景的重写规则如下:
1server {
2 ...
3 ...
4 location /tutorial
5 {
6 rewrite ^(/tutorial/.*)/wordpress/(\w+)\.?.*$ $1/cms/$2.php last;
7 }
8 ...
9 ...
10 }
** 解释:**
- 通常表达式中的第一个返回引用
^(/tutorial/.*)
用于匹配任何输入 URL 从/tutorial/foo
开始的 - 第二个返回引用
(\w+)
用于仅捕捉文件名而没有扩展 - 上面的两个返回引用用于使用 $1 和 $2 的替换 URL
- 最后一个关键字指示 NGINX 停止对更多重写条件的解析,即使在下一个位置匹配!
摘要
您现在可以使用重写或返回指令重写URL。本教程中使用的重写示例简单易懂。您现在可以继续写更复杂的重写规则!