前言

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(六)扩展的更多相关文章

  1. nginx安装扩展 sub_filter&http_ssl_module

    nginx之所以轻,因为默认没有安装各种各样的扩展: nginx安装扩展插件: 下面列出两个可能会用到的插件 一.sub_filter内容过滤器,这个在nginx做http转发的时候会很常用 1.下载 ...

  2. nginx+php+扩展件安装实践版

    一.安装各种软件包 yum -y install wget git vim lrzsz unzip zip gcc make gd-devel bzip2 bzip2-devel libcurl li ...

  3. Centos安装Memcached和(Nginx)Memcache扩展详细教程

    下载memadmin,下载地址:http://www.junopen.com/memadmin/ 并在IIS新建站点. 测试地址:http://wap.yousawang.com/mem , 1.重启 ...

  4. Nginx(四)-- Nginx的扩展-OpenRestry

    1. OpenResty 安装及使用 OpenResty 是一个通过 Lua 扩展 Nginx 实现的可伸缩的 Web 平台,内部集成了大量精良的 Lua 库.第三方模块以及大多数的依赖项.用于方便地 ...

  5. Nginx Google 扩展

    安装配置详见: https://github.com/cuber/ngx_http_google_filter_module/blob/master/README.zh-CN.md tenginx详见 ...

  6. nginx功能扩展整理

    0.基本负载均衡配置 编辑/etc/nginx/nginx.conf,加入负载平衡配置: http { upstream tomcat { server localhost:8080; server ...

  7. Nginx(六):Nginx HTTP负载均衡和反向代理的配置与优化

    一.什么是负载均衡和反向代理 随着网站访问量的快速增长,单台服务器已经无法承担大量用户的并发访问,必须釆用多台服务器协同工作,以提高计算机系统的处理能力和计算强度,满足当前业务量的需求.而如何在完成同 ...

  8. iOS学习笔记46-Swift(六)扩展

    一.Swift扩展 扩展就是向一个已有的类.结构体或枚举类型添加新功能,这包括在没有权限获取原始源代码的情况下扩展类型的能力.扩展和 Objective-C中的分类(category)类似,但是它要比 ...

  9. tomcat+nginx 横向扩展

    1.分别在电脑上部署两个tomcat tomcat1  tomcat2 2.不是nginx 并启动 输入 localhost 并进入nginx欢迎界面,证明部署成功 3.修改nginx 配置 ngin ...

随机推荐

  1. 读书笔记汇总 --- 用Python写网络爬虫

    本系列记录并分享:学习利用Python写网络爬虫的过程. 书目信息 Link 书名: 用Python写网络爬虫 作者: [澳]理查德 劳森(Richard Lawson) 原版名称: web scra ...

  2. Qt库的静态编译

    一.准备软件1. MinGW     (C:\Qt\MinGW)http://pan.baidu.com/share/link?shareid=174269&uk=673227135这个文件解 ...

  3. python 读写INI配置文件

    # -*- coding: utf-8 -*-import ConfigParserimport os '''读写配置文件的类[section]logpath = D:\log\imageminsiz ...

  4. 使用SqlDataAdapter时,需要注意的几点

    1.SqlDataAdapter内部通过SqlDataReader获取数据,而默认情况下SqlDataReader不能获知其查询语句对应的数据库表名,所以下面的代码: string strConn,s ...

  5. 1048: [HAOI2007]分割矩阵 - BZOJ

    Description 将一个a*b的数字矩阵进行如下分割:将原矩阵沿某一条直线分割成两个矩阵,再将生成的两个矩阵继续如此分割(当然也可以只分割其中的一个),这样分割了(n-1)次后,原矩阵被分割成了 ...

  6. [转载]async & await 的前世今生

    async 和 await 出现在C# 5.0之后,给并行编程带来了不少的方便,特别是当在MVC中的Action也变成async之后,有点开始什么都是async的味道了.但是这也给我们编程埋下了一些隐 ...

  7. 团体程序设计天梯赛-练习集L1-022. 奇偶分家

    L1-022. 奇偶分家 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定N个正整数,请统计奇数和偶数各有多少个? 输入格式 ...

  8. PowerDesigner(五)-概念数据模型(CDM生成LDM,PDM和OOM)

    概念数据模型 概念数据模型(Conceptual Data Model,CDM):表达的是数据整体逻辑结构,该结构独立于任何软件和数据存储结构,即它只是系统分析人员,应用程序设计人员,维护人员和用户之 ...

  9. 关于DataTables一些小结

    最近项目中使用了DataTables,故小结了一下. 导入CSS文件<link rel="stylesheet" href="<%=base %>/js ...

  10. 【mysql的设计与优化专题(3)】字段类型与合理的选择字段类型

    本篇博客稍微有点长,它实际上包括两个内容:一是mysql字段类型的介绍,二是在mysql建表过程中是如何正确选择这些字段类型; 字段类型 数值 MySQL 的数值数据类型可以大致划分为两个类别,一个是 ...