4.Nginx Rewrite 相关功能
rewrite 是 nginx 服务器的重要功能之一,用于实现 URL 的重写,URL 的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问,另外还可以在一定程度上提高网站的安全性
基于 ngx_http_rewrite_module 模块解析和处理 rewrite 请求,依赖 PCRE,因此编译之前要先安装 PCRE 库
ngx_http_rewrite_module 模块指令
ngx_http_rewrite_module 模块指令:if、set、break、return、rewrite、rewrite_log
下文统称为 rewrite 指令集
if 指令
条件判断,根据判断结果选择不同的 nginx 配置,可以配置在 server 或 location 块中,只能做单次判断,不支持使用 if else 这样的多重判断
1 | if (condition) {...} |
使用正则表达式对变量进行匹配,匹配成功时条件为 true,否则为 fasle,变量与表达式之间使用以下符号链接:
1 | = # 变量和字符串比较,相等为true |
示例:
1 | location /main { |
set 指令
变量赋值:set $var value
,value 可以是字符串,可以是变量,也可以是两者结合
范例:
1 | location /main { |
break 指令
break 用于 server、location、if
break 的作用是中断重定向,具体表现就是:
- server 或 if 中使用 break:break 后面的 rewrite 指令集全部失效,注意 location 不属于 rewrite 指令集,location 之外的 break 影响不到 location 内的指令
- location 中使用 break:不影响此 location 中后面的所有指令,一般搭配 rewrite 指令使用,直接将重定向的结果返回给客户端
break 和 last
两者通常都搭配 rewrite 指令使用,区别在于:
break 不会再去匹配其他 location,而是直接将重定向的结果返回给客户端,而 last 则继续重定,返回最后一个 location 的匹配结果给客户端
示例 1:break
1 | location /last { |
示例 2:last
1 | location /test1 { |
return 指令
完成对请求的处理,直接向客户端返回响应状态码,return 后面的所有指令都不被执行
语法: return code [text];
return code URL;
return URL;
默认值: —
上下文: server, location, if
rewrite_log 指令
设置是否记录 ngx_http_rewrite_module 模块日志记录到 error_log 日志文件当中
语法: rewrite_log on | off;
默认值: rewrite_log off;
上下文: http, server, location, if
rewrite 指令
通过正则表达式的匹配来改变 URI,可以同时存在一个或多个指令,按照顺序依次对 URI 进行匹配,rewrite 主要是针对用户请求的 URL 或者是 URI 做具体处理
语法: rewrite regex replacement [flag];
默认值: —
上下文: server, location, if
注意:如果在同一级配置块中存在多个 rewrite 规则,那么会自上而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,隐含有循环机制,但不超过 10 次;如果超过,提示 500 响应码,[flag]所表示的标志位用于控制此循环机制
要注意避免出现超过十次以及 URL 重写后返回错误的给用户
如果替换后的 URL 是以 http://或 https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向 301
302:浏览器不会缓存当前域名的解析记录
301:浏览器会缓存永久重定向的 DNS 解析记录
flag
rewrtie 有四种不同的 flag,分别是 redirect(临时重定向 302)、permanent(永久重定向 301)、break 和 last。其中前两种是跳转型的 flag,后两种是代理型
- 跳转型指由客户端浏览器重新对新地址进行请求
- 代理型是在 WEB 服务器内部实现跳转
正则表达式
1 | . # 匹配除换行符以外的任意字符 |
案例:自动跳转 https
1 | if ($scheme = http ){ # 如果没有加条件判断,会导致死循环 |
案例:判断文件是否存在
1 | if (!-e $request_filename) { |
防盗链
防盗链基于客户端携带的 referer 实现,referer 是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer 就是之前的那个网站域名,正常的 referer 信息有以下几种
1 | none # 请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息 |
实现防盗链
基于访问安全考虑,nginx 支持通过 ngx_http_referer_module 模块,检查访问请求的 referer 信息是否有效实现防盗链功能
1 | location /images { |
Referer 请求头为指定值时,内嵌变量$invalid_referer 被设置为空字符串, 否则这个变量会被置成“1”。查找匹配时不区分大小写