NGINX(六)扩展
2015-10-09 14:42
211 查看
前言
nginx模块化设计, 添加扩展模块变得容易, 下面开发一个非常简单的扩展模块, 实现返回http请求的头部内容, 配置标记是ping_pong, 配置在NGX_HTTP_LOC_CONF中.HTTP处理阶段
nginx处理http请求分为很多的阶段, 下面列出了所有阶段, 服务器接收到完http请求头部内容后, 会依次执行各个阶段, 执行顺序按照全局ngx_modules数组中的顺序进行. ngxin如何知道我们的模块是http处理的一个阶段呢, 阶段模块在初始化时, 要将自己注册进模块列表中, 后面我们自己模块代码会有体现.typedef enum { NGX_HTTP_POST_READ_PHASE = 0, NGX_HTTP_SERVER_REWRITE_PHASE, NGX_HTTP_FIND_CONFIG_PHASE, NGX_HTTP_REWRITE_PHASE, NGX_HTTP_POST_REWRITE_PHASE, NGX_HTTP_PREACCESS_PHASE, NGX_HTTP_ACCESS_PHASE, NGX_HTTP_POST_ACCESS_PHASE, NGX_HTTP_TRY_FILES_PHASE, /*http请求内容处理, 生成内容, 过滤操作, 我们要实现的简单扩展就注册在这个阶段*/ NGX_HTTP_CONTENT_PHASE, NGX_HTTP_LOG_PHASE } ngx_http_phases; /* *http请求头部接收完之后, 会执行ngx_http_core_run_phases函数, 函数遍历所有阶段进行执行. */ void ngx_http_core_run_phases(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_phase_handler_t *ph; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); ph = cmcf->phase_engine.handlers; while (ph[r->phase_handler].checker) { /*执行每个阶段的回调函数*/ rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]); /*一旦有阶段返回NGX_OK标记, 则立即返回, 后面的阶段不再执行*/ if (rc == NGX_OK) { return; } } }
ps : 各个阶段具体处理什么参考博客 http://blog.csdn.net/fengmo_q/article/details/8594610
编译选项
--with-http_ping_pong_module
编译配置:
1.1.auto/options中添加--with-http_ping_pong_module) HTTP_PING_PONG=YES ;;
2.2.auto/modules中添加
if [ $HTTP_PING_PONG = YES ]; then HTTP_MODULES="$HTTP_MODULES $HTTP_PING_PONG_MODULE" HTTP_SRCS="$HTTP_SRCS src/http/modules/ngx_http_ping_pong_module.c" fi
3.3.auto/sources中添加
HTTP_PING_PONG_MODULE=ngx_http_ping_pong_module HTTP_PING_PONG_SRCS=src/http/modules/ngx_http_ping_pong_module.c
nginx.conf中配置示例
server { listen 88; location /test { ping_pong on; } }
完整ngx_http_ping_pong_module.c
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static ngx_int_t ngx_http_ping_pong_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_ping_pong_init(ngx_conf_t *cf); static char* ngx_http_ping_pong_set_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void* ngx_http_ping_pong_create_loc_conf(ngx_conf_t *cf); typedef struct{ ngx_int_t ping_pong; }ngx_http_ping_pong_loc_conf_t; static ngx_command_t ngx_http_ping_pong_commands[] = { { ngx_string("ping_pong"), NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_http_ping_pong_set_conf, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_ping_pong_loc_conf_t, ping_pong), NULL }, ngx_null_command }; ngx_http_module_t ngx_http_ping_pong_module_ctx = { NULL, /* preconfiguration */ ngx_http_ping_pong_init, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_ping_pong_create_loc_conf, /* create location configuration */ NULL /* merge location configuration */ }; ngx_module_t ngx_http_ping_pong_module = { NGX_MODULE_V1, &ngx_http_ping_pong_module_ctx, /* module context */ ngx_http_ping_pong_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_int_t ngx_http_ping_pong_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t* b; ngx_chain_t out; ngx_uint_t content_length = 0; u_char ngx_ping_pong_string[1024] = {0}; ngx_http_ping_pong_loc_conf_t* lcf; /*获取并检查是否配置了ping_pong标记*/ lcf = ngx_http_get_module_loc_conf(r, ngx_http_ping_pong_module); if (lcf->ping_pong == NGX_CONF_UNSET) { /*如果没有进行配置, 则继续执行后面阶段*/ return NGX_DECLINED; } /* 格式化输出的内容 */ ngx_sprintf(ngx_ping_pong_string, "%V:%V,%V,%V %V:%V", &r->method_name, &r->uri, &r->args, &r->request_line, &r->headers_in.host->key, &r->headers_in.host->value); content_length = ngx_strlen(ngx_ping_pong_string); /*丢弃请求内容, 用不到*/ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) return rc; ngx_str_set(&r->headers_out.content_type, "text/html"); b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; out.buf = b; out.next = NULL; /*构造一个输出buf*/ b->pos = ngx_ping_pong_string; b->last = ngx_ping_pong_string + content_length; b->memory = 1; b->last_buf = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; /*http响应头部返回给客户端*/ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) return rc; /*http响应内容返回给客户端*/ return ngx_http_output_filter(r, &out); } /* *由于我们配置非常简单, 因此这里其实不用单独写set函数的, 可以直接将ngx_conf_set_flag_slot配置到command配置中 */ static char* ngx_http_ping_pong_set_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char* rv = ngx_conf_set_flag_slot(cf, cmd, conf); return rv; } /* *初始化配置 */ static void* ngx_http_ping_pong_create_loc_conf(ngx_conf_t *cf) { ngx_http_ping_pong_loc_conf_t* lcf = NULL; lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ping_pong_loc_conf_t)); if (lcf == NULL) { return NULL; } lcf->ping_pong = NGX_CONF_UNSET; return lcf; } /* *模块初始化时, 将阶段处理的回调函数注册进相应的阶段 */ static ngx_int_t ngx_http_ping_pong_init(ngx_conf_t *cf) { ngx_http_handler_pt *h; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); /*每个阶段都有一个处理函数的数组, 将我们执行的函数放入数组中*/ h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); if (h == NULL) { return NGX_ERROR; } *h = ngx_http_ping_pong_handler; return NGX_OK; }
相关文章推荐
- NGINX(五)模块
- NGINX(四)配置解析
- NGINX(三)HASH表
- NGINX(二)内存池
- NGINX(一)内存结构
- nginx优化
- Nginx隐藏版本号
- nginx的真实IP
- nginx的log配置
- 上传文件被nginx全部缓存的问题
- ubuntu下使用apt方式安装、卸载nginx
- nginx、fastCGI、php-fpm关系梳理(转)
- CentOS 下安装Nginx
- nginx 安装sticky遇到的问题
- 搭建Nginx+Java环境
- Nginx/LVS/HAProxy负载均衡软件的优缺点详解
- Nginx 四种分配方式
- Nginx基本配置、性能优化指南
- 用nginx图片缓存服务器
- nginx重新加载配置