功能,服务器通过扩展自定义命令,记录上游的服务器返回的特定响应头内容,记录到本地文件中
代码如下:
/* * 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 = 1024, 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 != 0){ headers = &r->headers_out.headers; for (n = 0; 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) == 0) { if (clcf->savefile.data == NULL){ return NGX_ERROR; } file.fd = ngx_open_file(clcf->savefile.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, 0600); 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(0)); 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 ", (u_char *) ho->value.data); (void) ngx_write_file(&file, out_buff.pos, out_buff.last - out_buff.pos, 0); 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