数据结构
ngx_http_request_t{
ngx_http_headers_in_t headers_in; //存放分析后的request headers
ngx_http_headers_out_t headers_out; //存放待发送的response headers
ngx_chain_t *out; //response headers序列化后,放在这里
}
typedef struct {
ngx_list_t headers;
ngx_table_elt_t *host;
ngx_table_elt_t *connection;
...
ngx_table_elt_t *user_agent;
ngx_table_elt_t *content_length;
ngx_table_elt_t *content_type;
ngx_table_elt_t *transfer_encoding;
ngx_table_elt_t *upgrade;
ngx_table_elt_t *keep_alive;
...
ngx_array_t x_forwarded_for;
ngx_array_t cookies;
ngx_str_t server;
off_t content_length_n;
time_t keep_alive_n;
unsigned connection_type:2;
unsigned chunked:1;
...
} ngx_http_headers_in_t;
typedef struct {
ngx_list_t headers;
ngx_list_t trailers;
ngx_uint_t status;
ngx_str_t status_line;
ngx_table_elt_t *server;
ngx_table_elt_t *date;
ngx_table_elt_t *content_length;
ngx_table_elt_t *content_encoding;
ngx_table_elt_t *location;
ngx_table_elt_t *last_modified;
ngx_table_elt_t *www_authenticate;
ngx_table_elt_t *expires;
ngx_table_elt_t *etag;
size_t content_type_len;
ngx_str_t content_type;
ngx_str_t charset;
u_char *content_type_lowcase;
ngx_uint_t content_type_hash;
ngx_array_t cache_control;
ngx_array_t link;
off_t content_length_n;
off_t content_offset;
time_t date_time;
time_t last_modified_time;
} ngx_http_headers_out_t;
typedef struct {
ngx_uint_t hash;
ngx_str_t key;
ngx_str_t value;
u_char *lowcase_key;
} ngx_table_elt_t;
header filter
逻辑结构
header filter是一个函数调用系列,用来处理response头部,其逻辑上如下:
//filer1()->filter2()->filter3()->filter4()
filter1 {
...
return filter2();
}
filter2() {
...
return filter3();
}
filter3() {
...
return filter4();
}
实现
实现上,在模块初始化时,用全局变量ngx_http_top_header_filter和模块局部变量ngx_http_top_header_filter相互迭代,构建调用链,例子如下:
//ngx_http.c 全局变量
ngx_http_output_header_filter_pt ngx_http_top_header_filter;
//filter1.c
static ngx_http_output_header_filter_pt ngx_http_next_header_filter; //局部变量
filter1() {
...
return ngx_http_next_header_filter();
}
filter1_init(ngx_conf_t *cf) {
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = filter1;
}
//filter2.c
static ngx_http_output_header_filter_pt ngx_http_next_header_filter; //局部变量
filter2() {
...
return ngx_http_next_header_filter();
}
filter2_init(ngx_conf_t *cf) {
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = filter2;
}
//ngx_http_core_module.c
//调用所有的header filter
ngx_http_send_header() {
return ngx_http_top_header_filer();
}
ngx_http_top_header_filter是调用链的开始,ngx_http_header_filter_module是结束,该模块把头部汇总到一个buffer中,挂到request->out上。
处理request头部
ngx_http_process_request_headers(r)
{
for(;;) {
ngx_http_parse_header_line(r)
h = ngx_list_push(&r->headers_in.headers); //分配一个ngx_table_elt_t
hh = ngx_hash_find(&cmcf->headers_in_hash,h);// 头部识别,是否注册了
if (hh && hh->handler(r, h, hh) != NGX_OK) { //合法检查,赋值给r->headers_out.<头部名词>,理解头部意思
...
}
}
}
cmcf->headers_in_hash是系统内置的头部hash表。
处理response头部
ngx_http_send_header()开始调用header filter,这些filter把header放在r->headers_out中;最后一个filter(ngx_http_header_filter)把这些header写入缓冲区,放到ngx_chain_t结构中,然后赋给r->out。(btw: 后面的流程ngx_http_output_filter()把body数据挂在r->out后面,并发送出去)。