① 模块涉及的指令
② 基本简介
rewrite模块会根据'PCRE正则'匹配'重写URI'
③ break
疑惑点: 结束'该作用域'下剩余的指令,还是'只是该rewrite模块的'指令?
1)配置demo
2)不带参数请求
3)带参数请求
- 由于URL中'&、&'不转义,curl请求最好加上'单引号',如果想使用'shell变量'则使用"双引号"
-
- 遗留:带参数同时配置中的'break'关闭看看效果
-
- 效果:整个请求就'被终止'了,后续的指令都'不'执行了,直接返回'404'
④ if
- if指令'掌握'两个点:'自定义[set]'和'内置(模块提供)'变量和'正则'形式
-
- 掌握:if (condition) {} 中'condition'的场景
-
- 遗留点:匹配后'不停止'?
- ++++++++++++++ '官方'案例 ++++++++++++++
-
- $request_filename:当前'连接请求'的文件路径,由'root'或'alias指令'与URI请求生成
- if ( $http_cookie ~* "name=wzj") -->cookie'数据太大',优点不明显
-
- if (remotr_addr ~* ^172\.25\.2\.*) -->限定'部分ip'访问
-
- ++++++++++++ server块中 ++++++++++++
-
- if ($request_uri ~ /vnc/include/(.+)) {
- set $parms $1;
- # 体会这个'含义',个人感觉是终止'server中执行rewrite的'阶段
- break;
- }
-
- location /vnc {
- proxy_pass http://www.wzj.com/$parms
- }
⑤ return
思考:'error_page' 和 'return'的优先级?
- 需求1: http'跳转'到https
-
- server {
- listen 80;
- server_name www.wzj.com;
- return 301 https://$http_host$request_uri;
- }
-
- +++++++++++++++ "分割线" +++++++++++++++
-
- 需求2:临时'调试'
-
- return 200 $name $request_uri;
-
- return 200 '{"name":"aming","id":"100"}'; # 返回json的形式
-
- +++++++++++++++ "分割线" +++++++++++++++
-
- 需求3:请求后缀'过滤'
-
- location ~ .*\.(sh|bash)?$ {
- return 403;
- # deny all;
- }
-
- +++++++++++++++ "分割线" +++++++++++++++
-
- 需求4:网站被黑了,凡是在'百度点击到本网站'的请求,全部都跳转到了一个'赌博'网站
-
- if ($http_referer ~ 'baidu.com') {
- return 200 "<html><script>window.location.href='//$host$request_uri';</script></html>";
- }
⑥ rewrite
- [1]. 在一个 URL 请求中,rewrite 如果'匹配到' regex,那么 URL 就会'替换'成 replacement
-
- [2]. 如果'不考虑' flag,匹配规则'多个rewrite'是'顺序执行'的,即使匹配到了,仍然'会继续'匹配下去
-
- [3]. 如果 replacement 包含 "http://", "https://", or "$scheme",那么匹配会'立即终止',并直接'重定向地址'给客户端
-
- ++++++++++ 'rewrite'哪些是重定向,哪些是'内部'转发 ++++++++++
-
- 1、涉及'https'、'http'、'$scheme' 都是重定向
-
- rewrite ... https|http|$scheme 这三种,默认是'redirect(302)',自己指定'permanent(301)'
-
- 特点:一旦匹配上,立即终止'处理','直接返回'给客户端'301、302',不再做后续'location'等操作,但是'content'还会执行
-
- 细节点:客户端的'地址栏'会发生变化 -->原因:浏览器根据'301、302'的状态码+'Location'响应头再发一次请求
-
- curl -Lv 查看详细'交互'过程
-
- 2、如果'replacement'不是上述的,或者不是返回给客户端'301、302'响应状态码,则是内部跳转
遗留点:rewrite是否'跨域'、客户端'地址栏'的变化、发生了'几次'请求、是否记录'跳转'的日志?
1)案例一
重写的字符串 '带http://'、不带'flag'
2)案例二
- 重写的字符串 '不带'http://,也不带'flag'
-
- 说明:相对于'root资源'目录
3) nginx rewrite 中last break flag区别
- ++++++++++++++++++"假定rewrite在location中"++++++++++++++++++
-
- [1]. last 和 break一样 它们都会'终止'此 location 中'其它rewrite模块指令'的执行
-
- [2]. 但是 last 立即发起'新一轮'的 location 匹配 而 break 则'不会'
-
- 补充: 'break'跳过'当前的rewrite'阶段,并执行本请求'输出'阶段
-
- ++++++++++++++++++++++++"分割线"++++++++++++++++++++++++
-
- [1]. flag 参数'如果'是 'redirect' 或 'permanent',那么处理就相对简单,立刻'中止规则匹配',进行 302 或 301 跳转
-
- [2]. 如果在 location 中配置 'flag 是 last',立刻'跳出本 location' 的匹配,同时会顺序'继续搜寻其他' location 的匹配,如果还'没匹配'到,还会继续'搜寻本' location
-
- [3]. 而 break '跳出本' location 后就'不会再匹配'其它 location 了
- 1. 如果'rewrite'同一个上下文由多个这样的规则:无'https、http、$scheme',也无'flag'标识
-
- 2. 匹配会按照'rewrite'指令出现的'先后'顺序依次进行,匹配到一个后'不会终止',而是继续往下匹配,直到返回'最后一个匹配上'的为止
+++++++++++++++++"分割线1"+++++++++++++++++
+++++++++++++++++"分割线2"+++++++++++++++++
- +++++++++++ "思考:二者访问的区别?" +++++++++++
-
- curl -iL http://rewrite.wzj.com/b/ -->"匹配到 location /" --> 'rewrite ^/a /b last;'
-
- curl -iL http://rewrite.wzj.com/b -->"location = /b"的精确匹配
+++++++++++++++++"分割线3"+++++++++++++++++
- 请求: http//rewrite.wzj.com/break/xx
-
- 输出: 'break page'
-
- 分析:
-
- 1. break是'跳过当前请求'的rewrite阶段,并'继续执行本请求'的'其他'阶段
-
- 2. 很明显,对于/break 对应的'content阶段'的输出为 echo "break page"
-
- 3. content阶段,可以简单理解为'产生数据输出的阶段',
-
- 4. echo指令也是'运行在content阶段',一般情况下content阶段只能对应一个输出指令,如同一个location'配置两个echo',最终只会有一个echo指令被执行
-
- 5. 当然如果你把'/break/'里的'echo 指令注释',然后再次访问/break/xx会'报404'
-
- 6. 虽然/break/xx'被重定向'到/test/xx,但是break指令'不会重新开启一个新的请求'继续匹配,所以nginx是'不会匹配到下面'的/test/这个location
-
- 7. 在echo指令'被注释'的情况下,/break/ 这location里'只能执行'nginx默认的content指令,即'尝试找/test/xx这个html页面'并输出起内容,事实上,这个页面'不存在',所以会报404的错误。
-
- ++++++++++++++ "分割线" ++++++++++++++
-
- 请求: http//rewrite.wzj.com/last/xx
-
- 输出: 'test page'
-
- 分析:
-
- 1. last与break最大的'不同'是,last会'重新发起'一个新请求,并'重新匹配'location
-
- 2. 所以对于/last,重新匹配请求以后'会匹配到/test/',所以最终'对应的content阶段'的输出是test page;
4) 死循环场景
5)查询参数
- 1. rewrite /a.html /new permanent -->重定向'带原始参数'的地址
-
- 2. rewrite /a.html /new? permanent -->重定向'不带'参数
-
- 3. rewrite /a.html /new?age=18 permanent -->重定向'追加'查询参数
-
- 4. rewrite /a.html /new?id=$arg_id&name=$arg_name? permanent -->重定向只'带指定'参数
return, rewrite, and try_files对比 辅助参考
⑦ rewrite_log
error.log开启'notice'级别,默认是'error'
⑧ set
细节点: 除了'变量$args'可以被'修改'以外,其'对应的子变量值'都只能'被查看'而'不能'进行修改
⑨ uninitialized_variable_warn
⑩ 遗留
- 1. 使用 alias 指令时,必须使用 last;
-
- 2. 使用 proxy_pass 指令时,则必须使用break
二 高级正则
① 普通补获
捕获 (exp) :匹配exp,并捕获文本到'自动命名$1、$2、...$9'的组里 --> "常见"
- +++++++++++ 'http跳转到https' +++++++++++
-
- server {
- listen 80;
- server_name www.wzj.com ;
- rewrite ^(.*) http://www.wzj.com$1 permanent;
- }
② 命名捕获
- (?<name>exp):匹配exp,并'捕获文本'到名称为'name的组'里,也可以写成(?'name'exp)
-
- 说明:能'看懂'即可
③ 非补获
- 1. 语法:(?:pattern)
-
- 2. 解读:'非获取匹配','匹配'pattern但'不获取'匹配结果,'不进行存储'供以后使用
-
- 3. 这在使用或字符"(|)"来组合一个'模式'的'各个部分'是很有用
-
- 4. 例如:'industr(?:y|ies)'就是一个比'industry|industries'更简略的表达式
-
- ++++++++++ "案例讲解" ++++++++++
-
- if ($uri ~* \.(?:html|css|js|json)$){
- proxy_pass http://static/wzj.com
- }
-
- +++++++++ nginx自行对"/"处理 +++++++++
-
- ~* ^\/wzj\/(.+?\.(?:html|css|js))$
-
- 说明:'/'不需要跟'shell'正则一样转义,nginx会'自行'处理
④ 零宽度断言
- 四个'非捕获组'用于匹配pattern'或者'不匹配pattern位置'之前'或'之后'的内容,匹配的结果'不包括'pattern
-
- 补充:(?#comment),这种类型的分组'不对'正则表达式的处理产生任何影响,用于'提供注释'让人阅读
1)案例一
- location ~* (?!.*/wzj/favicon).*(\.ico)$ {
- rewrite ^(.*) http://rewrite.wzj.com/static/wzj/favicon/favicon.ico permanent;
- # 备注:rewrite 'https://' --> 所以下面'return 301'不会执行
- return 301;
- }
- [1]. $request_uri 是'待匹配'的字符串
-
- http://rewrite.wzj.com'/aa/bb/cc.ico'
-
- http://rewrite.wzj.com'/wzj/favicon/favicon.ico'
-
- http://rewrite.wzj.com'/wzj/favicon/favicon.txt'
-
- [2]. (?!.*/wzj/favicon).*(\.ico)$ 是'正则模式'
遗留点:'回溯'的过程?
⑤ 贪婪和非贪婪模式
三 rewrite案例 遗留
常见情形
websocket官方配置 -->专栏
internal官方文档应用场景
nginx的重定向和内部转发location @ internal
rewrite其它域名、内部请求
nginx常见的rewrite规则、location稍后补充下
- 1. 执行server块的rewrite指令
-
- 2. 执行location匹配
-
- 3. 执行选定的location中的rewrite指令
-
-