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 ...
随机推荐
- android中ScrollView和GridView/ListView共存时,ScrollView不在顶部的解决方法
listView.setFocusable(false); gridView.setFocusable(false); 这个必须在代码中写,xml文件中设置不起作用 原文:http://stackov ...
- latex 常用小结
在写论文,甚至有些课程的报告的时候,latex是常用的工具.这篇博文简单的记录了latex常用的一些内容. 1 基本模块 没用过latex的读者,最想问的问题莫过于latex的 “hello worl ...
- maven 常用命令及操作(转)
Maven库: http://repo2.maven.org/maven2/ Maven依赖查询: http://mvnrepository.com/ Maven常用命令: 1. 创建Maven的普通 ...
- return和break的区别
/* Name:return和break的区别 Copyright: By.不懂网络 Author: Yangbin Date:2014年2月25日 02:13:22 Description:以下代码 ...
- 从头编译ARM交叉编译环境
首先Cygwin需安装基本的命令 例如make binutils gcc 还有diffutils 没有他会报找不到cmp命令 这些都可以在setup.exe中找到 编译gcc时,需要注意一个原则:不要 ...
- node 上传文件 路径 重命名等问题
最近在学习node,想做一个简单的网站.首先想到的是上传文件的功能,查了下,发现有一个formidable模块,操作方便,便拿来尝试了一下,结果很纠结. 下载安装的就不用说了,用npm即可.说一下,自 ...
- spring+hibernate删除单条记录的几种方法
spring+hibernate删除单条记录的几种方法
- Java基础—ClassLoader的理解(转)
默认的三个类加载器 Java默认是有三个ClassLoader,按层次关系从上到下依次是: Bootstrap ClassLoader Ext ClassLoader System ClassLoad ...
- MyEclipse13中修改Servlet.java源代码
Servlet.java源代码想要修改的步骤,与低版本的不同废话少说,直接来步骤: 1,在myEclipse的安装目录中搜索com.genuitec.eclipse.wizards文件,如图:选择co ...
- jar 命令使用详解
各位看官,由于本人首次学习java,对编译java 还有很多问题. jar命令详解 本人总结 jar -c [创建档案] v[输出详细信息] m[添加清单文件] f[指定文件名] 主要 ...