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

代码如下:

/*
* 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自定义模块记录上游服务器特定响应头的更多相关文章

  1. nginx自定义模块编写-根据post参数路由到不同服务器

    nginx可以轻松实现根据不同的url 或者 get参数来转发到不同的服务器,然而当我们需要根据http包体来进行请求路由时,nginx默认的配置规则就捉襟见肘了,但是没关系,nginx提供了强大的自 ...

  2. Nginx自定义模块编写:根据post参数路由到不同服务器

    Nginx自定义模块编写:根据post参数路由到不同服务器 2014-05-05 15:27 blogread IT技术博客 字号:T | T Nginx可以轻松实现根据不同的url 或者 get参数 ...

  3. nginx自定义模块编写-实时统计模块--转载

    原文:http://www.vimer.cn/2012/05/nginx%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E5%9D%97%E7%BC%96%E5%86%99- ...

  4. nginx系列10:通过upstream模块选择上游服务器和负载均衡策略round-robin

    upstream模块的使用方法 1,使用upstream和server指令来选择上游服务器 这两个指令的语法如下图: 示例: 2,对上游服务使用keepalive长连接 负载均衡策略round-rob ...

  5. servlet 服务器HTTP响应头设置示例(response用法)

    1,Location 用于重定向,和返回状态码302结合使用. 代码示例: response.setStatus(302); response.setHeader("location&quo ...

  6. nginx添加模块记录

    查看现有nginx的编译参数: [root@iZbp1d0dkjhfmxnxp7wuhmZ nginx-1.12.2]# nginx -Vnginx version: nginx/1.12.2buil ...

  7. nginx 与上游服务器建立连接的相关设置

    向上游服务建立联系 Syntax: proxy_connect_timeout time; #设置TCP三次握手超时时间,默认60秒:默认超时后报502错误 Default: proxy_connec ...

  8. nginx upstream模块

    upstream模块 upstream模块 (100%) nginx模块一般被分成三大类:handler.filter和upstream.前面的章节中,读者已经了解了handler.filter. 利 ...

  9. Nginx - upstream 模块及参数测试

    目录 - 1. 前言- 2. 配置示例及指令说明    - 2.1 配置示例    - 2.2 指令    - 2.3 upstream相关变量- 3. 参数配置及测试    - 3.1 max_fa ...

随机推荐

  1. oracle中 some、any、all 三者的区别及个人总结,归纳!

    any :如果是大于号时( a > b ),那么a中所有大于b中最小的那个数的值,就会被输出出来. 如果是小于号时( a < b ),那么a中所有小于b中最大的那个数的值,就会被输出出来. ...

  2. VC MFC 屏蔽ESC和ENTER键关闭对话框

    方法一: 窗体头文件中加入: protected: virtual BOOL PreTranslateMessage(MSG* pMsg); // PreTranslateMessage是消息在送给T ...

  3. prime算法求最小生成树(畅通工程再续)

    连着做了四道畅通工程的题,其实都是一个套路,转化为可以求最小生成树的形式求最小生成树即可 这道题需要注意: 1:因为满足路的长度在10到1000之间才能建路,所以不满足条件的路径长度可以初始化为无穷 ...

  4. js处理json的方法

    var json = "{id:"myid", url:"http://www.myurl.com"}"; var js= (new Fun ...

  5. Hadoop学习笔记01——Hadoop分布式文件系统

    Hadoop有一个称为HDFS的分布式系统,全称为Hadoop Distributed Filesystem. HDFS有块(block)的概念,默认为64MB,HDFS上的文件被划分为块大小的多个分 ...

  6. FileInputStream(字节流)与fileReader(字符流) 的区别

    FileInputStream 类 1 ) FileInputStream 类介绍: 以字节为单位的流处理.字节序列:二进制数据.与编码无关,不存在乱码问题. FileInputStream 类的主要 ...

  7. QListWidget的QComboBox下拉列表添加复选框及消息处理

    要在QComboBox下拉列表项中添加复选框,并进行消息处理,在网上搜索了很久没有找到太多有用的信息和实际的例子,但从中还是找到了一些提示性的资料,根据这些简短的介绍,最终实现了这个功能. QComb ...

  8. Netbeans搭建Android环境

    原文:Netbeans搭建Android环境 Netbeans环境的搭建主要依赖于NBAndroid插件,项目地址: http://www.nbandroid.org/p/installation.h ...

  9. Jsoup代码解读之四-parser

    Jsoup代码解读之四-parser 作为Java世界最好的HTML 解析库,Jsoup的parser实现非常具有代表性.这部分也是Jsoup最复杂的部分,需要一些数据结构.状态机乃至编译器的知识.好 ...

  10. HDU 3613 Best Reward(扩展KMP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3613 [题目大意] 一个字符串的价值定义为,当它是一个回文串的时候,价值为每个字符的价值的和,如果 ...