一 try_files、content阶段、outfilter再探
① 哪些人适合阅读
适合: 拿nginx作为'静态服务器'网站'前端'人员必备,后端程序员可以'选择性的忽略' 备注: 该篇一个'阶段性'的总结,后续'不再'探讨该部分 补充: 按照'try_files'、'content'阶段的'模块指令'的'执行顺序'讲解 强调: 本文'不具有实际意义',只是试图从'应用层现象'来解读运行机制
① 相关博客系列
备注:学习要有一个'过程',不可能'一蹴而就',下面的博客记录了我的'成长史',某一个时刻就'豁然开朗'
root、alias、index、try_files关系指令再探
precontent阶段的模块学习 核心try_files指令
content阶段index和autoindex模块学习
content阶段static模块学习
filter模块处理
章亦春大神的nginx权威参考
③ content阶段涉及模块指令处理顺序
1) 本次'只探讨'try-files、content阶段,附加'filter'系列模块 2) content 阶段是'所有请求处理阶段中'最为'重要'的一个 特点: 因为运行在'这个阶段'配置指令一般都肩负着生成"内容(content)"并输出'HTTP 响应'的使命 强调: 当存在"content handler 内容处理程序"的指令时,'静态资源服务模块'并'不会'起作用 3) 绝大多数 'nginx 模块'在向 'content 阶段' 主动'注册配置指令'时 重点: 本质上是在'当前的 location 配置块'中'注册'所谓的"内容处理程序(content handler)" 常见: ngx_echo模块 ["echo指令"]、ngx_proxy ["proxy_pass"] 强调: [1]、每一个 location 只能有一个"内容处理程序" [2]、当在 location 中同时'使用多个模块'的 content 阶段指令时 [3]、只有'其中一个模块'能成功注册"内容处理程序" 4) 如果location中'没有'使用在 content 阶段'注册的'模块指令,也即没有'content handler' [1]、处理权便'自动'落到了在 content 阶段"垫底"的那 '3个'静态资源服务模块 [2]、首先运行的 'ngx_index' 和 'ngx_autoindex' 模块 特点: 如果'当前请求的uri'是'以 / 结尾',就会使用对应'index'和'autoindex'指令 [3]、否则直接'弃权',将处理权转给了最后运行的 'ngx_static' 模块 特点: ngx_static 模块根据 '(root|alias) 指令'将'请求$uri' 映射为'文件系统'路径 备注: 这个模块主要实现'服务静态文件'的功能,也是nginx作为'web服务器'的核心 [4]、在确认'磁盘中'文件'存在'后,将它们的内容分别作为响应体输出,并自动设置'相应'响应头 备注: 如果'文件不存在',则返回'404',这才是'资源不存在' 5) 有的'模块'指令是'默认提供的',有的模块'没有指定',则'跳过'这个模块 备注:有些指令作用'对应地方'也能改变'11个阶段' 6) nginx '变量'则经常扮演着在'指令间'乃至'模块间'传递'小份数据'的角色 7) ngx_index、ngx_autoindex、ngx_static模块执行'顺序'和'处理特点'对比: [1]、ngx_index 和 ngx_autoindex 模块都'只会'作用于那些$uri以'/结尾'的请求 [2]、对于'不以/结尾的请求'则会直接'忽略',同时把处理权移交给'ngx_static 模块' [3]、而'ngx_static 模块'则刚好相反,直接'忽略'那些 $uri 以 '/ 结尾'的请求 1、'真正'把相应的'内容(正常|异常)'发送出去,还是得靠这个 'ngx_static 模块'来完成 2、所作的操作:即把'该文件的内容'作为响应体数据输出,并设置相应的'响应头'
④ try_files指令再探
知识铺垫
1)precontent'阶段': 特点: 这个阶段'专门'用于实现标准配置指令'try_files'的功能,'不'支持nginx模块注册处理程序 默认: '没有'指定'try_files',所以'precontent'阶段默认'不存在' 2) 语法: try_files file1 file2 ... '(uri|=code)' 本文: 对'try_files'各种行为的探究 备注: 支持'@location'这种'uri' 补充: 这里的'file1 ,file(n-1)'等指的是'资源对象(file|directory)' 最佳实践: try_files $uri $uri/ @wzj; 3) 细节点:'try_files'通过'alias|root'、'$uri'、'location'来判断文件系统对象是否存在 4) 探究案例: [1]、文件资源'存在' [2]、文件'不'存在,'目录资源'存在 [3]、前'N-1'个都不存在,'uri|=code'进行匹配 备注: 读者应该'注意'各个案例的'前提条件[上下文]' 观察: 'debug日志'输出,并'分析'
案例1:try_files file '文件'存在时,使用'content handler'和'默认content'行为'对比'实验
+++++++++++++++++++++ "分割线" +++++++++++++++++++++ 案例2: try_files file '目录资源对象'存在时 备注: 使用'content handler'和'默认content'行为'对比'实验
++++++++++++++++ "分析过程" ++++++++++++++++ 1) nginx 在 try-files 阶段发现'第一个参数 /wzj' 对应的'文件 file'不存在 2) 就会转向检查'第二个参数 /wzj/'对应的'文件系统对象' 3) 由于'此目录'存在,并且'$uri'不是以'/'结尾的 细节: 此时nginx就会把当前请求'uri 改写'为第'二个参数的值(不带末尾/)',即$uri为'/wzj' 注意: try_files '原始'参数值是 /wzj/,但 try_files 会自动'去除末尾'的'斜杠/'字符 4) 由于是一个'目录'资源,nginx会进行'301重定向',并返回'Location: $uri/' 过程:此时$uri不是以'/'结尾,所以'index、autoindex'指令对应的模块不起作用,ngx_static处理 强调: [1]、实际'try_files 非internal命中',还是会向下'处理','index、autoindex'被忽略 [2]、ngx_static会不是以'/'结尾的'$uri'映射的'文件'或'目录'做不同处理 备注: 理解上可以认为'约等于' 'rewrite ^ $uri/ permanent;'这种'相对'重定向 5) 接着'基于新的url',从客户端重新发起'重定向'请求 6) 在'try_files'由于'第二个参数 /wzj/'匹配判断是'目录',并且$uri是以'/'结尾 7) 此时转交到'ngx_index'模块,由于'此时映射的系统文件不存在',继续'ngx_autoindex'模块 8) 由于上述处理'/'结尾的'$uri'的两个模块没作用,'ngx_static'模块又处理不了以'/'结尾$uri 9) 此时返回'默认'内置的'403'的页面
说明: 下面的是'重定向'请求的'error.log'日志 备注: 同时给出了'$uri以/'结尾,并且'try_files directory'匹配的场景
对比实验: 基于'案例2',前提'条件不变',修改'相对重定向'的策略,观察结果
双层nginx 转发下的 try_files 指令 301 返回错误的 location 地址 try_files导致301
对比实验: 基于'案例2',前提'条件不变',使用'content handler' 强调: 1) 即使是'try_files $uri/'判断'目录资源存在',也会继续进行'content'阶段的处理 2) 所不同的是经过模块注册的'content handler',还是'nginx内置默认的content'
对比实验: 基于'案例2',前提'条件不变',基于'Location 301'使用'exact location'
案例3: 最后一个'uri'起作用 备注: 1) '普通uri' --> '$args'会丢失 --> 'rewrite ^ /java? last' 2) '命名location' --> '$args'不会丢失 --> 'rewrite ^ /java last' 1) try_files 指令本质上只是'有条件'地改写当前'请求的 URI' 2) 这里说的"条件"其实就是文件系统上的'对象(file|directory)是否存在' 3) 当"条件"都不满足时,它就会无条件地发起一个指定的"内部跳转" 备注: 除了无条件地发起'内部跳转'之外, try_files指令还支持直接返回指定状态码'HTTP 错误页'
案例4: 最后一个'=code'起作用,观察'add_header'行为 说明: 从语义上来说,一般使用'404'返回指定状态码的 'HTTP 错误页' 思考: try_files可以指定'哪些'状态码? 备注: 自己尝试过'401'、'301(没有Location)'、使用'20(0|6)'不报错但'阻塞'、'204'是ok 遗留: 如果指定'error_page' 相同'状态码'是否能补获? --> "会"
⑤ index指令再探
思考1: 什么场景会触发'index'指令的执行? --> 假定在一个'location'内 前提: 没有其它模块注册'content handler',并且'$request_uri'以'/'结尾 [1]、'$request_uri'中以'/'结尾,但'没有'指定'try_files' 补充: 'try_files directory'映射系统资源'存在',虽然会改变'$uri',但是会去掉末尾的'/' 强调: 上述是'触发 index'的充分不必要条件,并不意味着'index ...'能命中,只是'有机会'执行 附加: ngx_index 和 ngx_autoindex 模块都只会作用于那些 '$request_uri以/结尾'的请求 思考2: index指令是'如何执行'的? [1]、依次判定'指定的首页文件'是否存在? --> 基于'(root|alias)'判定 [2]、如果全都'不存在'则进行'ngx_autoindex'模块,要不返回'文件列表',要么返回'403' [3]、如果存在'指定的首页文件',则基于该'$uri$index_value'发起'internal'内部跳转 备注: 此时index 后续的'value'不再执行,并且'该次内部请求'的'后续阶段'也不再执行 问题1: 为什么我配置的'index'首页却不生效? 原因: 1) 由于'location'优先级原因,进不到之前的'location'中导致异常 2) index 指定的'首页' 场景: 'ngx_index 模块'主要用于在'文件系统目录中'自动查找'指定的首页'文件 思考: 如何才能真正'设置首页'与我们的'预期相符'呢? 案例: 1)案例1:'index .. 匹配不上',观察行为 --> 才有可能轮到'autoindex'指令执行 2)案例2:'index .. 匹配上',只使用一个'location'观察行为 3)案例3:'index .. 匹配上','定义新的 location',观察匹配行为
merge_slashes
1) 'try_files directory[/kafka/]' 改变了'$uri',同时导致301 'Location $uri/' 2) 继续发起请求'/kafka/'进行'index index.html'匹配,'文件'存在 3) index改变'$uri'为'/kafka/index.html',此时不以'/'结尾,autoindex即使配置也无法处理 4) 最后交给'ngx_static'处理
与'案例1'的对比实验: 由于'location的'优先级,导致非预期的'首页'
与'案例1'的对比实验: index 配置的值以'/'结尾,同时'autonindex on'开启观察 1) 第一次'index /wzj/' 查找系统资源为'目录' 强调: 只有'index file'匹配,才会改变'$uri' 2) 导致'$uri'变为'/kafka/wzj/',继续进行'internal'重定向行为 官方: 只有'index (file|dir)'不存在,才会执行'autoindex',index'优先级'高 大白话: 只要'index (file|dir)'匹配上,永远不会执行'autoindex' 3) 通过'add_header或error.log'观察 说明: 'index dir'场景
与上述的'对比'实验: 配置文件'不变',改变'前提条件',请求url'不变' 说明: 注意'autoindex on'执行的'条件',是一个'备胎'
上一篇:(十五)Flask覆写wsgi