3. Handlers
接下来我们把模块的细节放到显微镜下面来看,它们到底怎么运行的。
3.1. 剖析Handler(非代理)
Anatomy of a Handler (Non-proxying)
Handler一般做4件事:获取location配置;生成合适的响应;发送响应头;发送响应体。Handler有一个参数,即请求结构体。请求结构体包含很多关于客户请求的有用信息,比如说请求方法,URI,请求头等等。我们一个个地来看。
3.1.1. 获取location配置
这部分很简单。只需要调用
ngx_http_get_module_loc_conf,传入当前请求的结构体和模块定义即可。下面是我的circle gif handler的相关部分:
static ngx_int_t
ngx_http_circle_gif_handler(ngx_http_request_t *r)
{
ngx_http_circle_gif_loc_conf_t *cglcf;
cglcf = ngx_http_get_module_loc_conf(r, ngx_http_circle_gif_module);
...
现在我们就可以访问之前在合并函数中设置的所有变量了。
3.1.2. 生成响应
ngx_http_circle_gif_handler(ngx_http_request_t *r)
先来探讨一下参数
ngx_http_request_t
这才是模块真正干活的地方,很有趣哦。
这里要用到请求结构体,主要是这些结构体成员:
typedef struct {
...
/* the memory pool, used in the ngx_palloc functions */
ngx_pool_t *pool;
ngx_str_t uri;
ngx_str_t args;
ngx_http_headers_in_t headers_in;
ngx_http_headers_out_t headers_out;
...
} ngx_http_request_t;
uri 是请求的路径, e.g. "/query.cgi".
args 请求串参数中问号后面的参数 (e.g. "name=john").
headers_in 包含有很多有用的东西,比如说cookie啊,浏览器信息啊什么的,但是许多模块可能用不到这些东东。如果你感兴趣的话,可以参看
http/ngx_http_request.h 。
对于生成输出,这些信息应该是够了。完整的
ngx_http_request_t结构体定义在
http/ngx_http_request.h。
3.1.3. 发送响应头
响应头存放在结构体
headers_out中,它的引用存放在请求结构体中。 Handler设置相应的响应头的值,然后调用
ngx_http_send_header(r)。
headers_out中比较有用的是:
typedef stuct {
...
ngx_uint_t status;
size_t content_type_len;
ngx_str_t content_type;
ngx_table_elt_t *content_encoding;
off_t content_length_n;
time_t date_time;
time_t last_modified_time;
..
} ngx_http_headers_out_t;
(剩下的可以在
http/ngx_http_request.h找到。)
举例来说,如果一个模块要设置Content-Type 为 "image/gif", Content-Length 为 100, 并返回 HTTP 200 OK 的响应, 代码应当是这样的:
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = 100;
r->headers_out.content_type.len = sizeof("image/gif") - 1;
r->headers_out.content_type.data = (u_char *) "image/gif";
ngx_http_send_header(r);
上面的HTTP headers设定方式针对大多数参数都是有效的。但一些头部(headers)的变量设定要比上面的例子要麻烦;比如,
content_encoding 它还含有类型
(ngx_table_elt_t*), 所以必须先为此分配空间。可以用一个叫做
ngx_list_push的函数来做,它传入一个
ngx_list_t(与数组类似),返回一个list中的新成员(类型是
ngx_table_elt_t)。下面的代码设置了Content-Encoding为"deflate"并发送了响应头:
r->headers_out.content_encoding = ngx_list_push(&r->headers_out.headers);
if (r->headers_out.content_encoding == NULL) {
return NGX_ERROR;
}
r->headers_out.content_encoding->hash = 1;
r->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1;
r->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding";
r->headers_out.content_encoding->value.len = sizeof("deflate") - 1;
r->headers_out.content_encoding->value.data = (u_char *) "deflate";
ngx_http_send_header(r);
当头部有多个值时,这个机制常常被用到。它(理论上讲)使得过滤模块添加、删除某个值而保留其他值的时候更加容易,在操纵字符串的时候,不需要把字符串重新排序。
3.1.4. 发送响应体(Sending the body)
现在模块已经生成了一个响应,并存放在了内存中。接下来它需要将这个响应分配给一个特定的缓冲区,然后把这个缓冲区加入到链表,然后调用链表中“发送响应体(send body)”的函数。
链表在这里起什么作用呢?Nginx 中,handler模块(其实filter模块也是)生成响应到buffer中是同时完成的;链表中的每个元素都有指向下一个元素的指针,如果是NULL 则说明链表到头了。简单起见,我们假设只有一个buffer。
首先,模块需要先声明buffer和链表:
ngx_buf_t *b;
ngx_chain_t out;
接着,需要给buffer分配空间,并将我们的响应数据指向它:
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Failed to allocate response buffer.");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
b->pos = some_bytes; /* first position in memory of the data */
b->last = some_bytes + some_bytes_length; /* last position */
b->memory = 1; /* content is in read-only memory */
/* (i.e., filters should copy it rather than rewrite in place) */
b->last_buf = 1; /* there will be no more buffers in the request */
现在就可以把数据挂在链表上了:
out.buf = b;
out.next = NULL;
最后,我们发送这个响应体,返回值是链表在一次调用后的状态:
return ngx_http_output_filter(r, &out);
Buffer链是Nginx IO模型中的关键部分,你得比较熟悉它的工作方式。
引用
问: 为什么buffer还需要有个`last_buf`变量啊,我们不是可以通过判断next是否是NULL来知道哪个是链表的最末端了吗?
答: 链表可能是不完整的,比如说,当有多个buffer的时候,并不是所有的buffer都属于当前的请求和响应。所以有些buffer可能是buffer链表的表尾,但是不是请求的结束。这给我们引入了接下来的内容……
分享到:
相关推荐
nginx-http-flv-module 是由 nginx 开发社区创建的一个第三方模块,用于在 Nginx 上实现 HTTP 直播(HTTP Live Streaming,HLS)和FLV格式的视频流。FLV(Flash Video)是 Adobe Flash 平台广泛使用的视频格式,...
本资源提供的是一款针对Windows平台的Nginx,其中已经集成了`nginx-http-flv-module`模块,这个模块主要用于支持HTTP实时流(HTTP Live Streaming, HLS)和Flash视频流(Flash Video, FLV)。现在我们将深入探讨这一...
Nginx-RTMP是Nginx的一个扩展模块,由Adobe Systems开发,用于支持Real-Time Messaging Protocol (RTMP)。RTMP是一种协议,常用于在线流媒体传输,如视频直播服务。Nginx-RTMP模块允许Nginx接收来自Flash Player或...
nginx sticky是nginx的module,可以实现基于cookie的负载均衡。 下载后,在编译安装nginx时,用--add-module... ./configure --prefix=/usr/local/nginx-1.6.0 --add-module=../nginx-sticky-module-1.25 --without-...
**Nginx-RTMP 模块详解** Nginx-RTMP 模块是 Nginx 的一个扩展,用于处理 Real-Time Messaging Protocol (RTMP) 流,它允许 Nginx 作为 RTMP 服务器运行,支持直播和点播服务。这个源码包 "nginx-rtmp-module-...
cp -r ../nginx-upload-module-2.3.0 nginx-1.21.x/ cd nginx-1.21.x/ ./configure --add-module=../nginx-upload-module-2.3.0 \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-pcre make ...
在windows 7 64位 环境下使用nginx的nginx-http-flv-module搭建flv视频流播放所有的安装包,参考:https://blog.csdn.net/qq_33071429/article/details/102628008
标题中的"nginx-1.19.3_nginx-http-flv-module.rar"表明这是一个关于Nginx服务器的软件包,特别地,它包含了Nginx的1.19.3版本,并且已经集成了`nginx-http-flv-module`模块。这个模块是用于支持HTTP FLV(Flash ...
--> nginx-1.21.6 ======================== 在网上查找半天都只有教程,没有可免费下载的版本,深知没有积分遍地找资源的痛苦,无奈之下只好自己按照教程一步一个坑编译出来的,供大家免费下载使用。(无毒放心使用...
这个"asp.netcore-runtime-3.1.rar"压缩包包含的是ASP.NET Core 3.1运行时的组件,它允许你在Linux系统上运行ASP.NET Core 3.1的应用程序。在本例中,我们将关注如何在CentOS操作系统上部署和安装这些组件。 首先,...
此资源有两个文件,含 nginx-upstream-jvm-route 和 nginx 对应版本,都是tar.gz文件。 安装方法网上很多就不写了,亲测可用。 不用担心版本不匹配造成安装失败,再浪费积分去到处下载尝试的烦恼。 此资源有两个文件...
3. **nginx-http-flv-module**: 这是Nginx的一个第三方模块,由社区开发,用于支持HTTP FLV直播。它提供了处理RTMP流并将它们转化为适应HTTP的FLV流的能力,让客户端可以无插件播放。 4. **编译过程**: 在Windows上...
`nginx-http-flv-module`是Nginx的一个第三方模块,由张洪君开发,用于处理FLV格式的流媒体数据。通过这个模块,Nginx可以支持RTMP协议,实现实时流媒体的推拉流,为Flash Player和其他支持RTMP的客户端提供服务。...
在给定的压缩包文件中,"使用必看.txt"可能包含了编译和使用过程中的注意事项,而"nginx-rtmp.zip"可能是包含了RTMP模块的源代码,这在搭建流媒体服务器时也会用到,因为HTTP FLV Module通常与RTMP模块结合使用,为...
【标题】"nginx-upstream-jvm-route-1.15" 涉及的核心知识点是Nginx的upstream模块与JVM路由的整合,特别针对Nginx 1.15版本。这个项目旨在解决在配置Nginx时遇到的特定错误提示“nginx: [emerg] invalid parameter ...
Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为route (a)客户端首次发起访问请求,nginx接收后,发现...
在 `nginx-sticky-module-ng-1.2.6` 压缩包中,通常包含以下组件: 1. `src`: 这是源代码目录,包含了模块的核心代码,如 `ngx_http_sticky_module.c`,它是实现会话保持功能的主要源文件。 2. `config`: 配置脚本...
1、nginx-http-flv-module(windows可执行程序,含http-flv-module:1.2.7,nginx 1.19.3) 2、不要放置于中文路径下,否则无法启动 3、说明文档,请下载查看。
1. 采用nginx最新版编译,包含最新的nginx-http-flv-module,以及基础模块openssl、prce、zlib 2. 整体打包,已配置好nginx.conf的http-flv直播流,以及http web环境。无需任何配置即可使用 3. 自带windows的服务...
而nginx-rtmp-module则是一个额外的Nginx模块,它增加了对Real-Time Messaging Protocol (RTMP)的支持,使Nginx能够作为RTMP服务器接收并分发直播流。 1. **HTTP FLV 模块详解** HTTP FLV模块使得Nginx可以处理FLV...