Nginx 重写 URL 规则示例

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/ 您也可以重定向所有内容以获得特定路径到新的位置。 下面的示例显示如何重定向所有页面,这些页面属于 /tutorialhttps://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-tutorialhttps://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。本教程中使用的重写示例简单易懂。您现在可以继续写更复杂的重写规则!

Published At
Categories with 技术
Tagged with
comments powered by Disqus