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自定义模块记录上游服务器特定响应头的更多相关文章
- nginx自定义模块编写-根据post参数路由到不同服务器
nginx可以轻松实现根据不同的url 或者 get参数来转发到不同的服务器,然而当我们需要根据http包体来进行请求路由时,nginx默认的配置规则就捉襟见肘了,但是没关系,nginx提供了强大的自 ...
- Nginx自定义模块编写:根据post参数路由到不同服务器
Nginx自定义模块编写:根据post参数路由到不同服务器 2014-05-05 15:27 blogread IT技术博客 字号:T | T Nginx可以轻松实现根据不同的url 或者 get参数 ...
- 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- ...
- nginx系列10:通过upstream模块选择上游服务器和负载均衡策略round-robin
upstream模块的使用方法 1,使用upstream和server指令来选择上游服务器 这两个指令的语法如下图: 示例: 2,对上游服务使用keepalive长连接 负载均衡策略round-rob ...
- servlet 服务器HTTP响应头设置示例(response用法)
1,Location 用于重定向,和返回状态码302结合使用. 代码示例: response.setStatus(302); response.setHeader("location&quo ...
- nginx添加模块记录
查看现有nginx的编译参数: [root@iZbp1d0dkjhfmxnxp7wuhmZ nginx-1.12.2]# nginx -Vnginx version: nginx/1.12.2buil ...
- nginx 与上游服务器建立连接的相关设置
向上游服务建立联系 Syntax: proxy_connect_timeout time; #设置TCP三次握手超时时间,默认60秒:默认超时后报502错误 Default: proxy_connec ...
- nginx upstream模块
upstream模块 upstream模块 (100%) nginx模块一般被分成三大类:handler.filter和upstream.前面的章节中,读者已经了解了handler.filter. 利 ...
- Nginx - upstream 模块及参数测试
目录 - 1. 前言- 2. 配置示例及指令说明 - 2.1 配置示例 - 2.2 指令 - 2.3 upstream相关变量- 3. 参数配置及测试 - 3.1 max_fa ...
随机推荐
- 小鱼提问2 属性访问器中get,set再用public修饰行吗,private呢?
/// <summary> /// 是否有一个用户正在连接服务器中 /// </summary> public bool IsConnectting { get { retur ...
- which 查看可执行文件的位置
我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. ...
- js命名空间的使用
js命名空间的使用: test.html 代码如下: <!DOCTYPE HTML><html lang="en-US"><head> & ...
- 学会了 C 语言真的可以开发出很多东西吗?
马里奥碰到花朵就变身. 什么是马里奥?一个装着 16 × 32 个小色块的长方形,其中一些色块填着颜色,另一些没有.什么是花?一个 16 × 16 的正方形.什么是「变身」?把马里奥这个方块里面代表衣 ...
- querySelector $() getElementBy区别
参考 http://stackoverflow.com/questions/14377590/queryselector-and-queryselectorall-vs-getelementsbycl ...
- 网络抓包--Wireshark
Wireshark 是一款非常棒的Unix和Windows上的开源网络协议分析器.它可以实时检测网络通讯数据,也可以检测其抓取的网络通讯数据快照文件.可以通过图形界面浏览这些数据,可以查看网络通讯数据 ...
- 谷歌日志库GLog 使用说明
1 引用头文件 加载库 #include <glog/include/logging.h> #pragma comment(lib,"libglog.lib") 2 初 ...
- POJ 3581 Sequence(后缀数组)
[题目链接] http://poj.org/problem?id=3581 [题目大意] 给出一个数列,将这个数列分成三段,每段分别翻转,使得其字典序最小,输出翻转后的数列. [题解] 首先,第一个翻 ...
- hdoj 5319 Painter(模拟题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5319 思路分析:假设颜色R表示为1,颜色B表示为2,颜色G表示为3,因为数据量较小,采用暴力解法即可, ...
- 自己定义标签中tagsupport的一些方法
TagSupport生命周期 TagSupport类分别实现了Tag与IterationTag界面,其预设的回传值是:doStartTag()回传 SKIP_BODY.EVAL_BODY_INCLUD ...