企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### POST_READ阶段[](http://tengine.taobao.org/book/chapter_12.html#post-read "永久链接至标题") POST_READ阶段是nginx处理请求流程中第一个可以添加模块函数的阶段,任何需要在接收完请求头之后立刻处理的逻辑可以在该阶段注册处理函数。nginx源码中只有realip模块在该阶段注册了函数,当nginx前端多了一个7层负载均衡层,并且客户端的真实ip被前端保存在请求头中时,该模块用来将客户端的ip替换为请求头中保存的值。realip模块之所以在POST_READ阶段执行的原因是它需要在其他模块执行之前悄悄的将客户端ip替换为真实值,而且它需要的信息仅仅只是请求头。一般很少有模块需要注册在POST_READ阶段,realip模块默认没有编译进nginx。 POST_READ阶段的checker函数是ngx_http_core_generic_phase,这个函数是nginx phase默认的checker函数,后面的PREACCESS phase也是用checker,下面对它做一下介绍: [](http:// "点击提交Issue,反馈你的意见...") ngx_int_t ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { ngx_int_t rc; /* * generic phase checker, * used by the post read and pre-access phases */ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "generic phase: %ui", r->phase_handler); rc = ph->handler(r); if (rc == NGX_OK) { r->phase_handler = ph->next; return NGX_AGAIN; } if (rc == NGX_DECLINED) { r->phase_handler++; return NGX_AGAIN; } if (rc == NGX_AGAIN || rc == NGX_DONE) { return NGX_OK; } /* rc == NGX_ERROR || rc == NGX_HTTP_... */ ngx_http_finalize_request(r, rc); return NGX_OK; } 这个函数逻辑非常简单,调用该phase注册的handler函数,需要注意的是该函数对handler返回值的处理,一般而言handler返回: <table class="docutils field-list" frame="void" rules="none" style="margin: 0px -0.5em; border: 0px; color: rgb(0, 0, 0); font-family: 'segoe UI', sans-serif; letter-spacing: -0.1599999964237213px; line-height: 24px; white-space: normal; background-color: rgb(255, 255, 255);"><colgroup><col class="field-name"/><col class="field-body"/></colgroup><tbody valign="top"><tr class="field-odd field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">NGX_OK:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">表示该阶段已经处理完成,需要转入下一个阶段;</td></tr><tr class="field-even field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">NG_DECLINED:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">表示需要转入本阶段的下一个handler继续处理;</td></tr><tr class="field-odd field"><th class="field-name" colspan="2" style="padding: 1px 8px 1px 5px; border: 0px !important;">NGX_AGAIN, NGX_DONE:</th></tr><tr class="field-odd field"><td style="padding: 1px 8px 1px 5px; border: 0px !important;"> </td><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">表示需要等待某个事件发生才能继续处理(比如等待网络IO),此时Nginx为了不阻塞其他请求的处理,必须中断当前请求的执行链,等待事件发生之后继续执行该handler;</td></tr><tr class="field-even field"><th class="field-name" style="padding: 1px 8px 1px 5px; border: 0px !important;">NGX_ERROR:</th><td class="field-body" style="padding: 1px 8px 1px 5px; border: 0px !important;">表示发生了错误,需要结束该请求。</td></tr></tbody></table> checker函数根据handler函数的不同返回值,给上一层的ngx_http_core_run_phases函数返回NGX_AGAIN或者NGX_OK,如果期望上一层继续执行后面的phase则需要确保checker函数不是返回NGX_OK,不同checker函数对handler函数的返回值处理还不太一样,开发模块时需要确保相应阶段的checker函数对返回值的处理在你的预期之内。