【Nginx】开发一个简单的HTTP模块
当master进程fork出若干个workr子进程后,每一个worker子进程都会在自己的for死循环中不断调用事件模块:
for ( ;; ) {
....
ngx_process_events_and_timers(cycle); /* 调用事件模块 */
....
}
location /name {
test;
}
struct ngx_module_s {
ngx_uint_t ctx_index; /* 当前模块在同类模块中的序号 */
ngx_uint_t index; /* 当前模块在ngx_modules数组中的序号 */ ngx_uint_t spare0; /* 保留 */
ngx_uint_t spare1; /* 保留 */
ngx_uint_t spare2; /* 保留 */
ngx_uint_t spare3; /* 保留 */ ngx_uint_t version; /* 模块版本号,眼下为1 */ void *ctx; /* 指向特定类型模块的公共接口 */
ngx_command_t *commands; /* 用于处理配置文件nginx.conf中的配置项 */
ngx_uint_t type; /* 当前模块类型 */ /* 下面7个函数指针表示7个运行点,这些运行点将在Nginx启动和退出过程中被调用
* 假设不须要则设置为NULL
*/
ngx_int_t (*init_master)(ngx_log_t *log); /* 从未被调用,设为NULL */ ngx_int_t (*init_module)(ngx_cycle_t *cycle); /* 启动worker子进程前调用 */ ngx_int_t (*init_process)(ngx_cycle_t *cycle);/* 启动worker子进程后调用 */
ngx_int_t (*init_thread)(ngx_cycle_t *cycle); /* 从未被调用,设为NULL */
void (*exit_thread)(ngx_cycle_t *cycle); /* 从未被调用,设为NULL */
void (*exit_process)(ngx_cycle_t *cycle);/* worker子进程推出前调用 */ void (*exit_master)(ngx_cycle_t *cycle); /* master进程退出前调用 */ /* 下面全为保留字段 */
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
typedef struct {
ngx_int_t (*preconfiguration)(ngx_conf_t *cf); // 解析配置文件前调用
ngx_int_t (*postconfiguration)(ngx_conf_t *cf); // 解析完配置文件后调用 void *(*create_main_conf)(ngx_conf_t *cf); // 创建存储直属于http{}的配置项的结构体
char *(*init_main_conf)(ngx_conf_t *cf, void *conf); // 初始化main级别配置项 void *(*create_srv_conf)(ngx_conf_t *cf); // 创建存储直属于srv{}的配置项的结构体
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf); // 合并main级别和srv级别的同名配置项 void *(*create_loc_conf)(ngx_conf_t *cf); // 创建存储直属于loc{}的配置项的结构体
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf); // 合并srv级别和loc级别的同名配置项
} ngx_http_module_t;
struct ngx_command_s {
ngx_str_t name; // 配置项名称
ngx_uint_t type; // 配置项类型,包含该配置项能够出现的位置和能够携带參数的个数 // 出现name配置项后,调用此方法解析配置项參数
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf; // 配置文件里的偏移量,确定将该配置项放入哪个存储结构体中
ngx_uint_t offset; // 将该配置项放在存储结构体的哪个字段
void *post; // 配置项读取后的处理方法
};
static ngx_command_t ngx_http_mytest_commands[] = {
{
ngx_string("mytest"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS,
ngx_http_mytest, // 出现mytest配置项时,ngx_http_mytest函数被调用
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL,
},
ngx_null_command // 以一个空的ngx_command_t作为结尾
};
static char* ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf; // 找到mytest配置项所属的配置块
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); // 设置处理请求的方法,HTTP框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段时
// 假设主机域名、URI和mytest模块所在配置块名称同样,就会调用函数ngx_http_mytest_handler
clcf->handler = ngx_http_mytest_handler; return NGX_CONF_OK;
}
static ngx_http_module_t ngx_http_mytest_module_ctx = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
ngx_module_t ngx_http_mytest_module = {
NGX_MODULE_V1, // 0,0,0,0,0,0,1
&ngx_http_mytest_module_ctx,
ngx_http_mytest_commands,
NGX_HTTP_MODULE, // 定义模块类型 /* Nginx在启动和退出时会调用以下7个回调方法 */
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING, // 0,0,0,0,0,0,0,0,保留字段
};
// 请求的全部信息都存入ngx_http_request_t结构体中
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r)
{
// 请求的方法必须为GET或者HEAD
if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)))
return NGX_HTTP_NOT_ALLOWED; // 丢弃请求中的包体
ngx_int_t rc = ngx_http_discard_request_body(r);
if (rc != NGX_OK)
return rc; ngx_str_t type = ngx_string("text/plain");
ngx_str_t response = ngx_string("Hello World!"); // 包体内容 // 设置响应的HTTP头部
r->headers_out.status = NGX_HTTP_OK; // 返回的响应码
r->headers_out.content_length_n = response.len; // 响应包体长度
r->headers_out.content_type = type; // Content-Type rc = ngx_http_send_header(r); // 发送HTTP头部
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
return rc; // 假设响应不包括包体,则在此处能够直接返回rc // 分配响应包体空间,由于是异步发送,所以不要从栈中获得空间
ngx_buf_t *b = ngx_create_temp_buf(r->pool, response.len); if (b == NULL)
return NGX_HTTP_INTERNAL_SERVER_ERROR; ngx_memcpy(b->pos, response.data, response.len);
b->last = b->pos + response.len; // 指向数据末尾
b->last_buf = 1; // 声明这是最后一块缓冲区 ngx_chain_t out;
out.buf = b;
out.next = NULL; return ngx_http_output_filter(r, &out); // 向用户发送响应包
}
ngx_addon_name=ngx_http_mytest_module
HTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_module.c"
- ngx_addon_name:模块名称
- HTTP_MODULES:保存全部的HTTP模块名称,以空格符分隔
- NGX_ADDON_SRCS:新增模块的源码路径,变量ngx_addon_dir稍后说明
【Nginx】开发一个简单的HTTP模块的更多相关文章
- 用Verilog语言实现一个简单的MII模块
项目中要求简单地测试一下基于FPGA的模拟平台的RJ45网口,也就是需要实现一个MII或者RMII模块.看了一下官方网口PHY芯片的官方文档,还是感觉上手有点障碍,想在网络上找些参考代码看看,最后只在 ...
- Python开发一个简单的BBS论坛
项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...
- 如何开发一个简单的HTML5 Canvas 小游戏
原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...
- 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务
[源码下载] 重新想象 Windows 8 Store Apps (64) - 后台任务: 开发一个简单的后台任务 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后 ...
- 一个简单的AMD模块加载器
一个简单的AMD模块加载器 参考 https://github.com/JsAaron/NodeJs-Demo/tree/master/require PS Aaron大大的比我的完整 PS 这不是一 ...
- Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状)
Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状) 本篇博客来给大家介绍怎样使用Lua这门语言来开发一个简单的小游戏-记数字踩白块. 游戏的流程是这种:在界面上生成5个数1~5字并显 ...
- 作业1开发一个简单的python计算器
开发一个简单的python计算器 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568 ...
- 通过Nginx实现一个简单的网站维护通知页面
原文:https://www.zhyd.me/article/106 在网站发版时,总会有那么一小段时间服务是访问不通的,一般用户看到的都会是一个502的错误页面 那么可以通过nginx实现一个简单的 ...
- django学习-11.开发一个简单的醉得意菜单和人均支付金额查询页面
1.前言 刚好最近跟技术部门的[产品人员+UI人员+测试人员],组成了一桌可以去公司楼下醉得意餐厅吃饭的小team. 所以为了实现这些主要点餐功能: 提高每天中午点餐效率,把点餐时间由20分钟优化为1 ...
随机推荐
- thinkphp URL规则、URL伪静态、URL路由、URL重写、URL生成(十五)
原文:thinkphp URL规则.URL伪静态.URL路由.URL重写.URL生成(十五) 本章节:详细介绍thinkphp URL规则.URL伪静态.URL路由.URL重写.URL生成 一.URL ...
- Java读取本地文件,并显示在JSP文件中
当我们初学IMG标签时,我们知道通过设置img标签的src属性,能够在页面中显示想要展示的图片.其中src的值,可以是磁盘目录上的绝对,也可以是项目下的相对路径,还可以是网络上的图片路径.在存 ...
- iptables 小结
最近工作上一个作业用到了iptables命令,主要进行端口映射,在网上查了好多资料,尽管有很多例子,但还是整了好几天才整明白.在这里将学习到的知识总结一下.以下均属个人见解.(有一些是从网络中总结的, ...
- JavaEE session机制
JavaEE session机制 Http协议: 在讲session之前,必须说下Http协议,HTTP是一个client和server端请求和应答的标准(TCP).由HTTPclient发起一个请求 ...
- oracle 之 内存—鞭辟近里(四)
oracle 之 内存—鞭辟近里(四) 今天是2013-07-11日,首先我非常感谢我的哥们也是我的网友杨工,非常感谢他能在大数据库内帮我执行一下我所需要的信息.就是他说的网络真是一个互助友爱的平台. ...
- 浏览器url传参中文时得到null的解决方法
在写一个中文参数需求的时候遇到了以下问题,经过半天的测试和各种编码,以及网上一些有用没用的资料尝试终于解决 比如下面的url地址:http://travel.widget.baike.com:8 ...
- hdu 4888 Redraw Beautiful Drawings 最大流
好难好难,将行列当成X和Y,源汇点连接各自的X,Y集,容量为行列的和,相当于从源点流向每一行,然后分配流量给每一列,最后流入汇点,这样执意要推断最后是否满流,就知道有没有解,而解就是每一行流向每一列多 ...
- WASP_百度百科
WASP_百度百科 WASP
- 祖国版SoloWheel:Airwheel爱尔威火星车 拆箱&上手经验_运动户外_晒物广场_什么值得买
http://m.baidu.com/from=844b/bd_page_type=1/ssid=0/uid=3151E6C0905477A13653132D762BB6FB/pu=sz%401320 ...
- ASP.NET MVC 4高级编程(第4版)
<ASP.NET MVC 4高级编程(第4版)> 基本信息 作者: (美)Jon Galloway Phil Haack Brad Wilson K. Scott All ...