Nginx笔记之Rewrite规则

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx笔记之Rewrite规则相关的知识,希望对你有一定的参考价值。

nginx中Rewrite规则主要用于实现URL的重写。通过Rewrite规则,可以实现规范的URL、根据变量来做URL转向及选择配置。

Rewrite规则相关命令

  • break
  • if
  • return
  • rewrite
  • set

break命令

break的作用即完成当前规则集,后续不再处理rewrite命令。

if ($slow)
{
    limit_rate 10k;
    break;
}

if命令

if条件判断,判断一个条件是否符合,符合就执行代码段内的命令。Nginx内的if命令不支持嵌套,也不支持多一个条件处理(&&或||)

if命令是Rewrite规则内使用较多的一个命令,很多信息都可以作为if的条件进行判断。大致分为以下几种:

  1. 变量名是否为空
  2. 变量比较:=、!=
  3. 正则匹配
    1. 模糊匹配 ~*
    2. 完全匹配 ~
    3. 不匹配
      1. 不完全匹配 !~
      2. 不模糊匹配 !~*
  4. 文件是否存在 -f | !-f
  5. 目录是否存在 -d | !-d
  6. 文件或目录是否存在 -e | !-e
  7. 文件是否可执行 -x | !-x

例如:

if ($http_user_agent ~ MSIE)
{
    rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;] +)(?:;|$)")
{
    set $id $1;
}
if ($request_method = POST)
{
    return 405;
}
if (!-f $request_filename)
{
    break;
    proxy_pass http://127.0.0.1;
}
if ($slow)
{
    limit_rate 10k;
}
if ($invalid_referer)
{
    return 403;
}
if ($args ^~ post=140)
{
    rewrite ^ http://example.com/ permanent;
}

return命令

return命令用于结束规则的执行并返回状态码信息给客户端。常用的可用状态码包括:

  • 403 Forbidden,服务器拒绝执行
  • 404 Not Found,请求的资源为找到
  • 500 Internet Server Error,服务器遇到错误,导致无法完成对请求的处理(常出现在服务器的程序代码出现错误时)
  • 502 Bad Gateway,网关或代理无效
  • 503 Service Unabailable,服务器由于临时进行维护或过载导致无法处理请求
  • 504 Gateway Timeout,作为网关或代理的服务器处理请求时未能及时从上游服务器得到响应。

rewrite(核心)

作为rewrite规则内的核心命令,rewrite命令根据表达式来重定向URI,或者修改字符串。执行命令按其在配置文件内的顺序。

重写表达式子对相对路径有效;如果想匹配主机名,需要配置if命令

rewrite语法:rewrite regex replacement flag

rewrite命令支持的flag:

  • last 完成rewrite,类似于apache内的[L]标记
  • break 本条规则匹配后终止匹配,后续规则不在匹配
  • redirect 返回状态码302,表示临时性的重定向
  • permanent 返回状态码301,永久重定向

last和break用来实现URI重写,浏览器显示的URI地址不变,但服务器端访问的路径发生了变化;redirect和permanent用来实现URI跳转,浏览器会显示跳转后的URI地址。

last会在本条rewrite规则执行后重新在所在块内发起请求,而break则在本条规则匹配后终止匹配,因此last在某些情况下误使用将导致死循环。一般在根location中或直接在server标签中编写rewrite规则,推荐使用last;在非根location中使用break。例如:

# 对于location / {...}块而言,可以直接写内部的代码,不写location
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$1.mp3 last;
return 403;

location 、download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$1.mp3 break;
    return 403;
}

如果被替换的URI中含有参数(例如/app/test.php?id=5),默认参数会被自动附加到替换串上,我们可以通过在替换串的末尾加上?来解决这一问题。

rewrite ^/user/(.*)$ /show?user=$1? last;

# 末尾不加?
# rewrite ^/test(.*)$ http://www.aaa.com/home permanent;
# 对于访问http://www.aaa.com/test?id=5,跳转后将访问http://www.aaa.com/home?id=5

# 末尾加?
# rewrite ^/test(.*)$ http://www.aaa.com/home? permanent;
# 对于访问http://www.aaa.com/test?id=5,跳转后将访问http://www.aaa.com/home

set命令

set命令用于定义一个变量,还可以给变量进行赋值。配合if可以实现多条件。例如

if ($host ~* ^(.*?)\.aaa\.com$)
{
    set $var_test ‘1‘;
}
if ($host ~* ^localhost)
{
    set $var_test ‘1‘;
}
if ($var_test !~ ‘1‘)
{
    rewrite ^/(.*)$ http://www.aaa.com/ redirect;
}

Nginx与Apache的Rewrite规则实例对比

一般来说,,简单的nginx和apache的rewrite规则相差不大,只有小小修复即可实现兼容。

Apache Rewrite规则:

RewriteRule ^/(.*)$ http://www.aaa.com/$1 [L]

Nginx Rewrite规则:

rewrite ^/(.*)$ http://www.aaa.com/$1 last;

两者的细微区别

  • URL跳转方面
# nginx
# nginx要求给转换后的URL添加域名:http://$host
rewrite ^/(.*)$ http://www.aaa.com/$1/ permanent;

# apache
RewriteRule ^/(.*)$ /$1/ [R=301,L]
  • 变量名称
# apache引用变量
${HTTP_HOST}

# nginx引用变量
$host

两者的相似命令

apache nginx
RewriteCond if
RewriteRule rewrite
[R] redirect
[P] last
[R,L] redirect
[P,L] last
[PT,L] last

本文是一篇读书笔记,是对书内某个章节的知识整理,以防遗忘。

以上是关于Nginx笔记之Rewrite规则的主要内容,如果未能解决你的问题,请参考以下文章

Nginx 之 Rewrite 规则

nginx之rewrite规则未加引号导致检查nginx语法报错

Nginx学习笔记16rewrite之break

前端开发掌握nginx常用功能之rewrite

Nginx学习笔记17rewrite之last

Nginx rewrite配置规则