编写http模块

开发一个简单的http模块

如何调用http模块

这里写图片描述

准备工作

ngx_http_mytest_module
ngx_http_mytest_module.c需要定义一个名称,以便在configure时显示是否执行成功。

整型的封装

ngx_int_t封装有符号整型,使用ngx_uint_t 封装无符号整型。

ngx_str_t数据结构

typedef struct{
    size_t len;
    u_char *data;
}ngx_str_t;

ngx_list_t数据结构

typedef struct ngx_list_part_s ngx_list_part_t;

struct ngx_list_part_s{
    void *elts; //指向数组的起始地址
    ngx_uint_t nelts; //表示数组中已经使用了多少个元素
    ngx_list_part_t *next; //下一个链表元素的地址
}

typedef struct{
    ngx_list_part_t *last; //指向链表的最后一个数组元素
    ngx_list_part_t part; //链表的首个数组元素
    size_t size;//限制用户要存储的一个数据所占用的字节数必须小于或等于size
    ngx_uint_t nalloc; //每个ngx_list_part_t数组的容量
    ngx_pool_t *pool; //管理内存分配的内存池对象
}ngx_list_t; //整个链表

ngx_table_elt_t数据结构

typedef struct{
    ngx_uint_t hash;
    ngx_str_t key;
    ngx_str_t value;
    u_char *lowcase_key;
}ngx_table_elt_t;

ngx_buf_t数据结构

本质上是一些指针成员和标志位

ngx_chain_t数据结构

ngx_chain_t是与ngx_buf_t配合使用的链表数据结构

typedef struct ngx_chain_s ngx_chain_t;
struct ngx_chain_s{
    ngx_buf_t *buf;
    ngx_chain_t *next;
}

将自己的http模块编译进nginx

源代码全部放到一个目录下,同时编写一个文件用于通知nginx如何编译本模块,这个文件名必须为config。
在configure脚本执行时加入参数 –add-module=PATH

不满足要求时,直接修改objs/Makefile 和 objs/ngx_modules.c文件

config文件的写法

只想开发一个http模块,需要定义一下3个变量

ngx_addon_names:仅在configure时使用,一般为模块名称
HTTP_MODLUES:保存所有的HTTP模块名称,每个模块有空格符相连
    "$HTTP_MODLUES ngx_http_mytest_module"
NGX_ADDON_SRCS:新模块的源代码
    可以使用$ngx_addon_dir 等价于configure时的--addon-module=PATH

利用configure脚本将定制的模块加入到nginx中

configure中的两行脚本负责将第三方模块加入到nginx

. auto/modules
. auto/make

直接修改Makefile文件

在执行完configure后,对生成的objs/ngx_modules.c和objs/Makefile文件直接进行修改。

http模块的数据结构

定义http模块:
ngx_module_t ngx_http_mytest_module;

ngx_uint_t ctx_index; //表示在一类模块中的序号
ngx_uint_t index; //表示在ngx_modules数组中的序号
void *ctx;指向特定类型模块的公共接口
ngx_command_t *commands; //commands将处理nginx.conf中的配置项
ngx_uint_t type;//该模块的类型,在nginx官方中,取值为以下NGX_HTTP_MODULENGX_CORE_MODULENGX_CONF_MODULENGX_EVENT_MODULENGX_MAIL_MODULE

定义自己的http模块

此处的示例:

  • 不希望模块对所有的http请求起作用
  • 在nginx文件中的http{}、server{}、location{}块内定义mytest配置项,如果一个用户请求通过主机域名、URI等匹配上了相应的配置块,配置块下又有相应的mytest配置项,那么希望mytest模块开始处理请求
  • 首先,定义mytest配置项的处理 (常用NGX_HTTP_CONTENT_PHASE)
  • 定义模块

处理用户请求

在出现mytest配置项时,ngx_http_mytest方法或被调用,这时将ngx_http_core_loc_conf_t结构的handler成员指定我ngx_http_mytest_handler,在接收完http请求头部后,会调用handler指向的方法

handler 成员的原型ngx_http_mytest_handler_handler_pt

typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);

处理方法的返回值

http中相应包的返回码,包括了在/src/http/ngx_http_request.h文件中定义好的宏。

获取URI和参数

可以在ngx_http_request_t类型参数的r 中取得

获取http头部

struct ngx_http_request_s{
    ...
    ngx_buf_t *header_in; //未解析
    ngx_http_headers_in_t headers_in;//解析
    ...
}

获取http包体

http框架提供一种方法异步地接收包体
ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,ngx_http_client_body_handler_pt post_handler);

发送响应

发送http头部

ngx_int_t ngx_http_send_header(ngx_http_request_t *r);

将内存中的字符串作为包体发送

ngx_int_t ngx_http_output_filter(ngx_http_request_t *r,ngx_chain_t *in);

“Hello World”示例

这里写图片描述
这里写图片描述

将磁盘文件作为包体发送

如何发送磁盘文件

这里写图片描述
发送文件与内存数据的不同在于 如何设置ngx_buf_t
in_file为1表示缓冲区发送的是文件

清理文件句柄

typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t;

用户多线程下载和断点续传

range协议

用c++编写http模块

编译方式的修改

  • 修改configure相关脚本
  • 修改configure执行完毕后生成的Makefile文件(推荐)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值