Nginx重写URL规则示例

时间:2020-02-23 14:41:07  来源:igfitidea点击:

NGINX重写规则用于更改客户端请求的全部或者部分URL。
更改URL的主要动机是告知客户端,他们所寻找的资源已经改变了其位置,除了控制NGINX中执行页面的流程。

NGINX中的returnrewrite指令用于重写URL。
这两个指令执行相同的重写URL功能。
但是,rewrite指令比return指令功能更强大,因为需要URL解析的复杂重写只能用rewrite指令完成。

在本教程中,我们将探讨如何在NGINX中同时使用return和rewrite指令来更改或者重写URL。

NGINX return指令

可以使用return指令来完成最简单,更简洁的URL重写方法。
必须通过指定要重定向的URL在服务器或者位置上下文中声明return指令。

1. Server上下文中的NGINX Return指令

服务器上下文中的return指令在将站点迁移到新域并且要将所有旧URL重定向到新域的情况下非常有用。

此外,它还通过强制您的重定向到www或者非www版本来帮助规范URL。

server {
      listen 80;
      server_name www.oldtheitroad.com;
      return 301 $scheme://www.newtheitroad.com$request_uri;
}

上述服务器上下文中的return指令将目的地为www.oldtheitroad.com的URL重定向到www.newtheitroad.com。
NGINX一旦收到www.oldtheitroad.com的URL,就会停止处理页面,并向客户端发送301响应代码以及重写的URL。

以上return指令中使用的两个变量是$scheme和$request_uri。
变量$scheme用于定义URL的方案(http或者https),变量$request_uri包含带有参数的完整URI(如果有)。
请记住,在重写URL时,两个变量都将从输入URL中获取此信息。

2. Location上下文中的return指令

在某些情况下,您可能希望重定向页面而不是重定向域。
通过location块内的return指令,您可以将特定页面重定向到新位置。

location = /tutorial/learning-nginx {
   return 301 $scheme://example.com/nginx/understanding-nginx
}

在上面的示例中,每当请求URI与模式/tutorial/learning-nginx完全匹配时,NGINX会将其重定向到新位置https://example.com/nginx/understanding-nginx /

您还可以将特定路径的所有内容重定向到新位置。
以下示例说明如何将所有在/tutorial下的页面重定向到https://example.com/articles。

location /tutorial {
   return 301 $scheme://example.com/articles
}

NGINX rewrite指令

我们还可以使用rewrite指令在NGINX中重写URL。
像return指令一样,rewrite指令也可以放置在服务器上下文以及位置上下文中。

rewrite指令可以对URL和从原始URL中获取的,没有相应NGINX变量的元素进行复杂的区分,从而使其比return指令更有用。

重写指令的语法为:

rewrite regex replacement-url [flag];
  • regex:基于PCRE的正则表达式,将用于与传入请求URI匹配。

  • replace-url:如果正则表达式与请求的URI匹配,则使用替换字符串更改请求的URI。

  • flag:flag的值决定是否需要对rewrite指令进行更多处理。

请记住,rewrite指令只能返回代码301或者302。
要返回其他代码,您需要在rewrite指令之后显式包括一个return指令。

NGINX Rewrite指令示例

让我们快速检查一些重写规则,以从简单HTML页面重写为另一个URL开始:

1.重写静态页面

考虑一种情况,您想将页面的URL重写为https://example.com/nginx-tutorial到https://example.com/somePage.html。
以下位置块中给出了执行相同操作的重写指令。

server {
        ...
        ...
        location = /nginx-tutorial 
        { 
          rewrite ^/nginx-tutorial?$/somePage.html break; 
        }
        ...
        ...
}

说明:

  • 位置指令location =/nginx-tutorial告诉我们,位置块将仅与包含确切前缀为/nginx-tutorial的URL匹配。

  • NGINX将在请求的URL中寻找模式" ^/nginx-tutorial?$"。

  • 要定义模式,请使用字符^,?。和$被使用并具有特殊含义。

  • ^表示要匹配的字符串的开头。

  • $表示要匹配的字符串的结尾。

  • ?表示非贪婪修饰符。
    一旦找到匹配项,非贪婪修饰符将停止搜索模式。

  • 如果请求的URI包含上述模式,则将使用somePage.html进行替换。

  • 由于重写规则以中断结尾,因此重写也将停止,但是重写的请求不会传递到另一个位置。

2.重写动态页面

现在考虑一个动态页面" https://www.example.com/user.php?id=11",其中动态部分是" id = 11(userid)"。
我们希望将该URL重写为https://exampleshop.com/user/11。
如果您有10个用户,则按照最后一种重写URL的方法,每个用户都需要10个重写规则。

取而代之的是,可以捕获变量中URL的元素,并使用它们来构造单个重写规则,该规则将处理所有动态页面。

server {
        ...
        ...
        location = /user.php 
        { 
          rewrite user.php?id= ^user/([0-9]+)/?$break; 
        }
        ...
        ...
}

说明:

  • 位置指令" location =/user"告诉NGINX将位置块与包含确切前缀"/user"的URL进行匹配。

  • NGINX将在请求的URL中查找模式^ user /([0-9] +)/?$

  • 方括号[0-9] +中的正则表达式包含0到9之间的一系列字符。
    +号表示匹配前面的一个或者多个字符。
    如果没有+号,则上述正则表达式将仅与1个字符(如5或者8)匹配,而与25或者44不匹配。

  • 正则表达式中的括号()表示反向引用。
    替换URL" user.php?id = $1"中的$1引用此反向引用。

例如,如果输入URL为https://www.example.com/user/24,则用户ID 24将与反向引用中的范围匹配,从而导致以下替换:

https://www.example.com/user.php?id=24

3.高级URL重写

让我们继续另一个示例,我们希望将URLhttps://www.example.com/user.php?user_name = john重写为https://www.example.com/user/login/john
与以前的重写规则不同,URLuser_name = john的动态部分现在包含字母字符范围。
下面给出了此方案的重写规则:

server {
        ...
        ...
        location = /user.php 
          { 
              rewrite user.php?user_name= ^user/login/([a-z]+)/?$break;           
          }
        ...
        ...
}

说明:

  • 位置指令" location =/user/login/john"告诉NGINX将位置块与包含确切前缀"/user/login/john"的URL进行匹配。

  • NGINX将在请求的URL中查找模式^ user/login /([[a-z] +)/?$

  • 方括号[a-z] +中的正则表达式包含a到z之间的字符范围。
    +号表示匹配前面的一个或者多个字符。
    如果没有+号,则上述正则表达式将仅与1个字符(如a或者c)匹配,而与john或者doe不匹配。

  • 正则表达式中的括号()表示反向引用。
    替换URL" user.php?user_name = $1"中的$1引用此反向引用。

例如,如果输入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)。

下面给出了此方案的重写规则:

server {
        ...
        ...
        location /tutorial
        {
           rewrite ^(/tutorial/.*)/wordpress/(\w+)\.?.*$/cms/.php last;
        }
        ...
        ...
}

说明:

  • 正则表达式中的第一个后向引用^(/tutorial /.*)用于匹配以/tutorial/foo开头的任何输入URL。

  • 第二个后引用(\ w +)仅用于捕获不带扩展名的文件名。

  • 上面的两个反向引用在替换URL中使用$1和$2

  • 最后一个关键字指示NGINX停止解析更多的重写条件,即使在下一个位置匹配时也是如此!