概述
决定自己的HTTP模块如何起作用
- 一个HTTP请求会被许多个配置项控制,这是因为一个HTTP请求可以被许多个HTTP模块同时处理,所以肯定会有一个先后顺序的问题。
- 我们面临的问题:
- 我们希望自己的模块在哪个时刻开始处理请求?
- 我们是希望自己的模块对到达Nginx的所有请求都起作用,还是只对某一类请求(如URI匹配了location后表达式的请求)起作用?
- 定义第一个HTTP模块介入Nginx的方式
- 模块并不对所有的HTTP请求起作用。
- 在nginx.conf文件中的http{}、server{}或者location{}块内定义mytest配置项,如果一个用户请求通过主机域名、URI等匹配上了相应的配置块,而这个配置块下又具有mytest配置项,那么希望mytest模块开始处理请求。
- 在这种介入方式下,模块处理请求的顺序是固定的,即必须在HTTP框架定义的NGX_HTTP_CONTENT_PHASE阶段开始处理请求。
开始定义mytest模块
- 定义mytest配置项的处理
- 只需要定义一个ngx_command_t数组,并将mytest配置项出现后的解析方法设置为ngx_http_mytest:
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, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, ngx_null_command };
- ngx_http_mytest是ngx_command_t结构体中的set成员,当在某个配置块中出现mytest配置项时,Nginx将会调用ngx_http_mytest方法。
- 只需要定义一个ngx_command_t数组,并将mytest配置项出现后的解析方法设置为ngx_http_mytest:
- 实现ngx_http_mytest方法
static char * ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_loc_conf_t *clcf; /* 首先找到mytest配置项所属的配置块,clcf看上去像是location块内的数据结构,其实不然, * 它可以是main、src或者loc级别的配置项,也就是说,在每个http{}和server{}内也都有一个 * ngx_http_core_loc_conf结构体 */ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); /* HTTP框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段是,如果请求的主机域名、URL * 与mytest配置项所在的配置块相匹配,就将调用我们实现的ngx_http_mytest_handler方法处 * 理这个请求 * */ clcf->handler = ngx_http_mytest_handler; return NGX_CONF_OK; }
- 当Nginx接收完HTTP请求的头部信息时,就会调用HTTP框架处理请求,NGX_HTTP_CONTENT_PHASE阶段将有可能调用mytest模块处理请求。
- 在ngx_http_mytest方法中,定义了请求的处理方法为ngx_http_mytest_handler。
- HTTP框架共定义了11个阶段,第三方模块只能介入其中的7个阶段处理请求。11个阶段的定义如下:
typedef enum { // 在接收到完整的HTTP头部后处理的HTTP阶段 NGX_HTTP_POST_READ_PHASE = 0, /* 在还没有查询到URI匹配的location前,这时rewrite重写URL也作为一个独立的HTTP阶段 */ NGX_HTTP_SERVER_REWRITE_PHASE, /* 根据URI寻找匹配的location,这个阶段通常由ngx_http_core_module模块实现。 不建议其他HTTP模块重新定义这一阶段的行为。 */ NGX_HTTP_FIND_CONFIG_PHASE, /* NGX_HTTP_FIND_CONFIG_PHASE阶段后重写URL的意义与NGX_HTTP_SERVER_REWRITE_PHASE阶段不同 因为这两者会导致查找到不同的location块(location是与URI进行匹配的) */ NGX_HTTP_REWRITE_PHASE, /* 该阶段用于在rewrite重写URL后跳到NGX_HTTP_FIND_CONFIG_PHASE,找到与新的URI匹配的location。 这一阶段无法由第三方HTTP模块处理,仅由ngx_http_core_module模块使用 */ NGX_HTTP_POST_REWRITE_PHASE, // 处理NGX_HTTP_ACCESS_PHASE阶段前,HTTP模块可以介入的处理阶段 NGX_HTTP_PREACCESS_PHASE, // 这个阶段用于HTTP模块判断是否允许这个请求访问Nginx服务器 NGX_HTTP_ACCESS_PHASE, /* 当NGX_HTTP_ACCESS_PHASE阶段中HTTP模块的handler处理方法返回不允许访问的错误码时 (实际是NGX_HTTP_FORBIDDEN或者NGX_HTTP_UNAUTHORIZED),这个阶段负责构造拒绝服务的用户响应。 这个阶段实际上用于给NGX_HTTP_ACCESS_PHASE阶段收尾。 */ NGX_HTTP_POST_ACCESS_PHASE, /* 这个阶段完全是为try_files配置项而设立的。 当HTTP请求访问静态文件资源时,try_files配置项可以使这个请求顺序地访问多个静态文件资源。 如果某一次访问失败,则继续访问try_files中指定的下一个静态资源。 这个功能完全是在NGX_HTTP_TRY_FILES_PHASE阶段中实现的。 */ NGX_HTTP_PRECONTENT_PHASE, // 用于处理HTTP请求内容的阶段,这是大部分HTTP模块最喜欢介入的阶段 NGX_HTTP_CONTENT_PHASE, /* 处理完请求后记录日志的阶段。 ngx_http_log_module模块就在这个阶段中加入了一个handler处理方法, 使得每个HTTP请求处理完毕后会记录access_log日志 */ NGX_HTTP_LOG_PHASE } ngx_http_phases;
- 定义ngx_http_module_t接口
- 如果没有什么工作是必须在HTTP框架初始化时完成的,那就不必实现ngx_http_module_t的8个回调方法,定义方法如下:
static ngx_http_module_t ngx_http_mytest_module_ctx = { NULL, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ NULL, /* create location configuration */ NULL, /* merge location configuration */ };
- 如果没有什么工作是必须在HTTP框架初始化时完成的,那就不必实现ngx_http_module_t的8个回调方法,定义方法如下:
- 定义mytest模块
ngx_module_t ngx_http_mytest_module = { NGX_MODULE_V1, &ngx_http_mytest_module_ctx, /* module context */ ngx_http_mytest_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 };
至此,mytest模块在编译时将会被加入到ngx_modules全局数组中。Nginx在启动时,会调用所有模块的初始化回调方法,当然,这个例子中我们没有实现它们(也没有实现HTTP框架初始化时会调用的ngx_http_module_t中的8个方法)。
最后
以上就是清新大地为你收集整理的Nginx开发HTTP模块(四):定义自己的HTTP模块的全部内容,希望文章能够帮你解决Nginx开发HTTP模块(四):定义自己的HTTP模块所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复