1. ngx_http_output_header_filter_pt / ngx_http_output_body_filter_pt
phase机制可以让nginx模块插入自己的http请求的处理步骤。但它不是唯一可以这样做的机制。另外一个机制是所谓的ngx_http_output_header_filter_pt/ngx_http_output_body_filter_pt函数栈。
// ngx_http.c
ngx_http_output_header_filter_pt ngx_http_top_header_filter;
ngx_http_output_body_filter_pt ngx_http_top_body_filter;
http请求的header部分和body部分可以分开处理,所以对应ngx_http_output_header_filter_pt和ngx_http_output_body_filter_pt两个栈。
这里先以header部分的处理为例说明。
简单地说,全局变量ngx_http_top_header_filter是栈的顶端。NGX_HTTP_MODULE类型的模块可以向这个栈推入自己的处理函数。如下,ngx_http_headers_filter_module模块就将自己的处理函数ngx_http_headers_filter推入栈顶(变量ngx_http_next_header_filter指向原来的栈顶,新的栈顶指向模块的处理函数)。
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
ngx_int_t ngx_http_headers_filter_init(ngx_conf_t *cf)
{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_headers_filter;
}
最后,所有的处理函数都入栈后的情况就类似下图。虚线框内的处理函数组成一个调用栈,全局变量ngx_http_top_header_filter指向栈顶。这时,栈外的函数就可以通过ngx_http_top_header_filter调用这个函数栈了,比如图中的ngx_http_send_header()。

与header部分的处理类似,body部分的处理得到的调用函数栈如下图。ngx_http_top_body_filter是栈顶。栈外的函数ngx_http_output_filter()通过ngx_http_top_body_filter调用函数栈。

2. ngx_http_static_handler
ngx_http_static_module模块负责处理静态文件请求的模块。它向NGX_HTTP_CONTENT_PHASE阶段注册处理函数ngx_http_static_handler()。
ngx_http_static_handler() 负责发送回应消息。
- 调用ngx_http_send_header()。它调用header部分的函数调用栈。
- 调用ngx_http_output_filter()。它调用body部分的函数调用栈。栈底的函数ngx_http_write_filter()。
++ ngx_http_write_filter()调用ngx_linux_send_file_chain(),最终调用ngx_writev(),通过ngx_connection_t的socket发送静态文件的内容。

网友评论