nginx自定义模块记录上游服务器特定响应头

功能,服务器通过扩展自定义命令,记录上游的服务器返回的特定响应头内容,记录到本地文件中

代码如下:

/*
* Copyright (C) Ciaos
*/ #include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h> typedef struct {
ngx_str_t header;
ngx_str_t savefile;
} ngx_http_tiaowuban_filter_conf_t; static void *ngx_http_tiaowuban_filter_create_conf(ngx_conf_t *cf);
static char *ngx_http_tiaowuban_filter_merge_conf(ngx_conf_t *cf, void *parent,void *child); static ngx_int_t ngx_http_tiaowuban_filter_init(ngx_conf_t *cf); static ngx_command_t ngx_http_tiaowuban_filter_commands[] = {
{ ngx_string("tiaowuban_header"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_tiaowuban_filter_conf_t, header),
NULL },
{ ngx_string("tiaowuban_savefile"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_tiaowuban_filter_conf_t, savefile),
NULL }, ngx_null_command
}; static ngx_http_module_t ngx_http_tiaowuban_filter_module_ctx = {
NULL, /* preconfiguration */
ngx_http_tiaowuban_filter_init, /* postconfiguration */ NULL, /* create main configuration */
NULL, /* init main configuration */ NULL, /* create server configuration */
NULL, /* merge server configuration */ ngx_http_tiaowuban_filter_create_conf, /* create location configration */
ngx_http_tiaowuban_filter_merge_conf /* merge location configration */
}; ngx_module_t ngx_http_tiaowuban_filter_module = {
NGX_MODULE_V1,
&ngx_http_tiaowuban_filter_module_ctx, /* module context */
ngx_http_tiaowuban_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
}; static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t
ngx_http_tiaowuban_filter_header_filter(ngx_http_request_t *r)
{
ngx_uint_t buffsize = , n;
ngx_table_elt_t *ho;
ngx_buf_t out_buff;
u_char buff[buffsize];
ngx_file_t file;
ngx_list_t *headers;
ngx_http_tiaowuban_filter_conf_t *clcf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_tiaowuban_filter_module);
if(clcf == NULL) {
return NGX_ERROR;
} if(clcf->header.len != ){
headers = &r->headers_out.headers;
for (n = ; n < headers->part.nelts; n++) {
ho = &((ngx_table_elt_t *)headers->part.elts)[n];
if (ngx_strncmp(ho->key.data, clcf->header.data, clcf->header.len) == ) {
if (clcf->savefile.data == NULL){
return NGX_ERROR;
}
file.fd = ngx_open_file(clcf->savefile.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, );
if (file.fd == NGX_INVALID_FILE) {
return NGX_ERROR;
}
file.log = r->connection->log; out_buff.pos = out_buff.last = buff;
out_buff.last = ngx_http_time(out_buff.last, time());
out_buff.last = ngx_snprintf(out_buff.last, r->connection->addr_text.len+1, "|%s", r->connection->addr_text.data);
buffsize -= out_buff.last - out_buff.pos;
out_buff.last = ngx_snprintf(out_buff.last, buffsize, "|%s\n", (u_char *) ho->value.data); (void) ngx_write_file(&file, out_buff.pos, out_buff.last - out_buff.pos, ); if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_file_n " \"%s\" failed", clcf->savefile.data);
}
}
}
} return ngx_http_next_header_filter(r);
} static ngx_int_t
ngx_http_tiaowuban_filter_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
return ngx_http_next_body_filter(r, in);
} static void *
ngx_http_tiaowuban_filter_create_conf(ngx_conf_t *cf)
{
ngx_http_tiaowuban_filter_conf_t *clcf; clcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_tiaowuban_filter_conf_t));
if (clcf == NULL) {
return NULL;
} return clcf;
} static char *
ngx_http_tiaowuban_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_tiaowuban_filter_conf_t *prev = parent;
ngx_http_tiaowuban_filter_conf_t *clcf = child; ngx_conf_merge_str_value(clcf->header, prev->header, "");
ngx_conf_merge_str_value(clcf->savefile, prev->savefile, ""); return NGX_CONF_OK;
} static ngx_int_t
ngx_http_tiaowuban_filter_init(ngx_conf_t *cf)
{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_tiaowuban_filter_header_filter; ngx_http_next_body_filter = ngx_http_top_body_filter;
ngx_http_top_body_filter = ngx_http_tiaowuban_filter_body_filter; return NGX_OK;
}

测试用例如下

use Test::Nginx::Socket;
repeat_each(1);
plan tests => 3 * repeat_each() * blocks() - 1; our $config = <<"_EOC_";
location /test {
tiaowuban_header "tiaowubanCtrl";
tiaowuban_savefile /usr/local/nginx/logs/tiaowuban.bill;
proxy_pass http://127.0.0.1/;
}
_EOC_ run_tests(); __DATA__ === TEST 1: upstream header one
--- http_config eval
"
server{
listen 80;
location / {
add_header tiaowubanCtrl \"testone\";
return 200 \"this is test one\";
}
}
"
--- config eval: $::config
--- request
GET /test
--- pre_remove_files eval
["/usr/local/nginx/logs/tiaowuban.bill"]
--- error_code: 200
--- response_headers
tiaowubanCtrl: testone
--- response_body_like: this is test one
--- output_files_like
/usr/local/nginx/logs/tiaowuban.bill: testone === TEST 2: upstream header two
--- http_config eval
"
server{
listen 80;
location / {
add_header tiaowubanCtrl \"testtwo\";
return 200 \"this is test two\";
}
}
"
--- config eval: $::config
--- request
GET /test
--- pre_remove_files eval
["/usr/local/nginx/logs/tiaowuban.bill"]
--- error_code: 200
--- response_headers
tiaowubanCtrl: testtwo
--- response_body_like: this is test two
--- output_files_like
/usr/local/nginx/logs/tiaowuban.bill: testtwo === TEST 3: upstream no header
//--- ONLY
--- http_config eval
"
server{
listen 80;
location / {
return 200 \"this is test three\";
}
}
"
--- config eval: $::config
--- request
GET /test
--- pre_remove_files eval
["/usr/local/nginx/logs/tiaowuban.bill"]
--- error_code: 200
--- response_body_like: this is test three
--- files_not_exist eval
["/usr/local/nginx/logs/tiaowuban.bill"]
--- timeout: 10

文件内容如下:

Wed, 12 Nov 2014 08:29:30 GMT|10.0.2.2|hello tiaowuban
Wed, 12 Nov 2014 08:30:20 GMT|10.0.2.2|hello tiaowuban
Wed, 12 Nov 2014 08:30:24 GMT|10.0.2.2|hello tiaowuban
Wed, 12 Nov 2014 08:30:43 GMT|10.0.2.2|hello tiaowuban
Wed, 12 Nov 2014 08:30:46 GMT|10.0.2.2|hello tiaowuban
上一篇:nginx log_format指令记录自定义响应头


下一篇:Java集合(续)