Nginx重写URL规则示例
NGINX重写规则用于更改客户端请求的全部或者部分URL。
更改URL的主要动机是告知客户端,他们所寻找的资源已经改变了其位置,除了控制NGINX中执行页面的流程。
NGINX中的return
和rewrite
指令用于重写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停止解析更多的重写条件,即使在下一个位置匹配时也是如此!