nginx url 重写



NGINX rewrite rules are used to change entire or a part of the URL requested by a client. The main motive for changing an URL is to inform the clients that the resources they are looking for have changed its location apart from controlling the flow of executing pages in NGINX.

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

The return and rewrite directives in NGINX are used to rewrite URL. Both the directives perform the same function of rewriting URL. However, the rewrite directive is more powerful than the return directive since complex rewriting that requires parsing of URL can be done with rewrite directive only.

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





In this tutorial, we will explore how both return and rewrite directives are used in NGINX to change or rewrite the URL.

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

(NGINX Return directive)

The easiest and cleaner way to rewrite an URL can be done by using the return directive. The return directive must be declared in the server or location context by specifying the URL to be redirected.

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

(1. NGINX Return directive in Server context)

The return directive in server context is very useful in a situation where you have migrated your site to a new domain and you want to redirect all old URLs to the new domain.

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

Further, it also helps in canonicalization of URL by forcing your site to redirect to either www or non-www version.

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





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

The return directive in the above server context redirect URL destined to site www.olddomain.com to www.newdomain.com. As soon as NGINX receives an URL with www.olddomain.com, it stops processing the page and sends a 301 response code along with rewritten URL to the client.

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

The two variables used in the above return directive are $scheme and $request_uri. The variable $scheme is used to define scheme of the URL (http or https) and the variable $request_uri contains complete URI with parameters if any. Remember both the variable fetches this information from input URL while rewriting the URL.

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

(2. Return directive in Location context)

In some situation, you may want to redirect pages instead of redirecting domains. The return directive inside the location block enables you to redirect specific pages to a new location.

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

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

In the above example, whenever a request URI matches exactly with pattern /tutorial/learning-nginx, NGINX will redirect the same to the new location https://example.com/nginx/understanding-nginx/

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

You can also redirect everything for a specific path to a new location. The following example shows how to redirect all pages those falls under /tutorial to https://example.com/articles.

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

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

(NGINX Rewrite directive)

We can also use rewrite directive to rewrite URL in NGINX. Like return directive, rewrite directive can also be placed in server context as well as in location context.

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

The rewrite directive can perform complicated distinctions between URLs and fetch elements from the original URL that don’t have corresponding NGINX variables thereby making it more useful than return directive.

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

The syntax of rewrite directive is:

重写指令的语法为:

rewrite regex replacement-url [flag];
  • regex: The PCRE based regular expression that will be used to match against incoming request URI. regex :基于PCRE的正则表达式,将用于与传入请求URI匹配。
  • replacement-url: If the regular expression matches against the requested URI then the replacement string is used to change the requested URI. replace-url :如果正则表达式与请求的URI匹配,则使用替换字符串更改请求的URI。
  • flag: The value of flag decides if any more processing of rewrite directive is needed or not. flagflag的值决定是否需要对rewrite指令进行更多处理。

Remember, The rewrite directive can return only code 301 or 302. To return other codes, you need to include a return directive explicitly after the rewrite directive

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

(NGINX Rewrite directive examples)

Let us quickly check few rewrite rules to get you started with it starting from rewriting a simple html page to another URL:

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





(1. Rewrite static page)

Consider a scenario where you want to rewrite an URL for a page say https://example.com/nginx-tutorial to https://example.com/somePage.html. The rewrite directive to do the same is given in the following location block.

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

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

Explanation:

说明:

  • The location directive location = /nginx-tutorial tells us that the location block will only match with an URL containing the exact prefix which is /nginx-tutorial. location指令location = /nginx-tutorial告诉我们,location块将只与包含确切前缀/nginx-tutorial的URL匹配。
  • The NGINX will look for the pattern ^/nginx-tutorial?$ in the requested URL. NGINX将在请求的URL中查找模式^/nginx-tutorial?$
  • To define the pattern, the characters ^,? and $ are used and have special meaning.
  • ^ represents the beginning of the string to be matched. ^表示要匹配的字符串的开头。
  • $ represents the end of the string to be matched. $表示要匹配的字符串的结尾。
  • ? represents non greedy modifier. Non greedy modifier will stop searching for pattern once a match have been found. 表示非贪婪修饰符。 一旦找到匹配项,非贪婪修饰符将停止搜索模式。
  • If the requested URI contains the above pattern then somePage.html will be used as a replacement.
  • Since the rewrite rule ends with a break, the rewriting also stops, but the rewritten request is not passed to another location.

(2. Rewrite dynamic page)

Now consider a dynamic page https://www.example.com/user.php?id=11 where the dynamic part is id=11(userid). We want the URL to be rewritten to https://exampleshop.com/user/11. If you have 10 users then there is a need of 10 rewrite rules for every users if you follow the last method of rewriting URLs.

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

Instead, It is possible to capture elements of the URL in variables and use them to construct a single rewrite rule that will take care of all the dynamic pages.

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

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

Explanation:

说明:

  • The location directive location = /user tells NGINX to match the location block with an URL containing the exact prefix which is /user. location指令location = /user告诉NGINX将location块与包含确切前缀/user的URL进行匹配。
  • The NGINX will look for the pattern ^user/([0-9]+)/?$ in the requested URL. NGINX将在请求的URL中查找模式^user/([0-9]+)/?$
  • The regular expression within square bracket [0-9]+ contains a range of characters between 0 and 9. The + sign signifies matching one or more of the preceding characters. Without the + sign, the above regular expression will match with only 1 character like 5 or 8 but not with 25 or 44.
  • The parenthesis ( ) in the regular expression refers to the back-reference. The $1 in the replacement URL user.php?id=$1 refers to this back-reference. 正则表达式中的括号()表示反向引用。 替换URL user.php?id=$1引用此反向引用。

For example, if https://www.example.com/user/24 is the input URL then the user id 24 will match with the range in the back-reference resulting in the following substitution:

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

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

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

(3. Advance URL Rewriting)

Let us proceed with another example where we want the URL
https://www.example.com/user.php?user_name=john to be rewritten to https://www.example.com/user/login/john. Unlike previous rewrite rule, The dynamic part of the URL user_name=john now contains range of alphabetic characters. The rewrite rule for this scenario is given below:

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

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

Explanation:

说明:

  • The location directive location = /user/login/john tells NGINX to match the location block with an URL containing the exact prefix which is /user/login/john. location指令location = /user/login/john告诉NGINX将location块与包含/user/login/john的确切前缀的URL进行匹配。
  • The NGINX will look for the pattern ^user/login/([a-z]+)/?$ in the requested URL. NGINX将在请求的URL中查找模式^user/login/([az]+)/?$
  • The regular expression within square bracket [a-z]+ contains range of characters between a to z. The + sign signifies matching one or more of the preceding characters. Without + sign, the above regular expression will match with only 1 character like a or c but not with john or doe.
  • The parenthesis ( ) in the regular expression refers to the back-reference. The $1 in the replacement URL user.php?user_name=$1 refers to this back-reference. 正则表达式中的括号()表示反向引用。 替换URL user.php?user_name=$1引用此反向引用。

For example, if the input URL is https://www.example.com/user/login/john then the user name “john” will match with the range in the back-reference resulting in the following substitution:

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

https://www.example.com/user.php?user_name=john

https://www.example.com/user.php?user_name=john

(4. Rewrite with multiple back reference)

In this example, we will also find out how to rewrite an URL by using multiple backreferences. Let us assume the input URL is https://example.com/tutorial/linux/wordpress/file1 and we want to rewrite the URL to https://example.com/tutorial/linux/cms/file1.php.

在此示例中,我们还将找到如何通过使用多个反向引用来重写URL。 让我们假设输入URL是https://example.com/tutorial/linux/wordpress/file1并且我们想将该URL重写为https://example.com/tutorial/linux/cms/file1.php

If you closely look at the input URL, it starts with /tutorial, and somewhere later in the path the string wordpress needs to be replaced with string cms. Further, a file extension (php) also needs to be appended at the end of the filename.

如果您仔细查看输入URL,它以/tutorial开头,然后在路径中的某处以后,字符串wordpress需要替换为字符串cms。 此外,还需要在文件名的末尾附加文件扩展名(php)。

The rewrite rule for this scenario is given below:

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

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

Explanation:

说明:

  • The first back reference ^(/tutorial/.*) in the regular expression used to match any input URL starting with /tutorial/foo 正则表达式中的第一个后向引用^(/tutorial/.*)用于匹配以/tutorial/foo开头的任何输入URL
  • The second back reference (\w+) is used to capture the file name only without extension. 第二个后向引用(\w+)仅用于捕获文件名而没有扩展名。


(Summary)

You can now rewrite URL using either rewrite or return directive. The rewrite examples used in this tutorial are simple and easy to understand. You can now proceed with writing more complex rewrite rules!

现在,您可以使用rewrite或return指令重写URL。 本教程中使用的重写示例简单易懂。 您现在可以继续编写更复杂的重写规则!

翻译自: https://www.journaldev.com/26864/nginx-rewrite-url-rules

nginx url 重写