在 Nginx 中,Handler 和 Filter 是两种不同的模块扩展方式,它们的作用、执行时机和使用场景有显著区别。理解它们的差异对于设计和实现自定义模块非常重要。
1. Handler 模块
作用
-
Handler 模块用于处理 HTTP 请求的核心逻辑,例如生成响应内容、转发请求、返回静态文件等。
-
它是请求处理的主要入口,决定了请求的最终响应内容。
执行时机
-
Handler 模块在 Nginx 的请求处理阶段(Phase)中执行,具体阶段包括:
-
NGX_HTTP_SERVER_REWRITE_PHASE
:服务器级别的重写。 -
NGX_HTTP_FIND_CONFIG_PHASE
:查找匹配的 location 配置。 -
NGX_HTTP_REWRITE_PHASE
:location 级别的重写。 -
NGX_HTTP_POST_REWRITE_PHASE
:重写后的处理。 -
NGX_HTTP_PREACCESS_PHASE
:访问控制前的处理。 -
NGX_HTTP_ACCESS_PHASE
:访问控制(如权限检查)。 -
NGX_HTTP_POST_ACCESS_PHASE
:访问控制后的处理。 -
NGX_HTTP_CONTENT_PHASE
:生成响应内容(最常用的阶段)。 -
NGX_HTTP_LOG_PHASE
:记录日志。
-
特点
-
直接生成响应:Handler 模块可以直接生成 HTTP 响应内容(如返回 HTML、JSON 等)。
-
独占性:一个请求通常只能由一个 Handler 模块处理(除非显式调用其他 Handler)。
-
适合场景:实现核心业务逻辑,如动态内容生成、反向代理、静态文件服务等。
示例
-
静态文件模块(
ngx_http_static_module
):返回静态文件内容。 -
反向代理模块(
ngx_http_proxy_module
):将请求转发到后端服务器。
2. Filter 模块
作用
-
Filter 模块用于对 HTTP 响应内容进行加工或修改,例如压缩、添加前缀、修改响应头等。
-
它是请求处理的辅助工具,通常不直接生成响应内容。
执行时机
-
Filter 模块在 Handler 模块生成响应内容后执行,具体分为两个阶段:
-
Header Filter:处理响应头(
ngx_http_top_header_filter
)。 -
Body Filter:处理响应体(
ngx_http_top_body_filter
)。
-
特点
-
链式调用:多个 Filter 模块可以依次对响应内容进行处理。
-
非独占性:一个请求可以由多个 Filter 模块处理。
-
适合场景:对响应内容进行加工,如 Gzip 压缩、响应头修改、内容替换等。
示例
-
Gzip 压缩模块(
ngx_http_gzip_filter_module
):对响应内容进行 Gzip 压缩。 -
响应头修改模块:添加或修改 HTTP 响应头。
3. Handler 和 Filter 的区别
特性 | Handler 模块 | Filter 模块 |
---|---|---|
作用 | 处理请求的核心逻辑,生成响应内容。 | 对响应内容进行加工或修改。 |
执行时机 | 在请求处理阶段(如 NGX_HTTP_CONTENT_PHASE )。 | 在响应内容生成后(Header Filter 和 Body Filter)。 |
独占性 | 一个请求通常由一个 Handler 处理。 | 一个请求可以由多个 Filter 处理。 |
链式调用 | 不支持链式调用。 | 支持链式调用。 |
适合场景 | 动态内容生成、反向代理、静态文件服务等。 | 响应内容压缩、修改响应头、内容替换等。 |
4. 如何选择 Handler 还是 Filter
-
使用 Handler 的场景:
-
需要生成动态内容(如返回 JSON、HTML)。
-
需要实现反向代理或负载均衡。
-
需要直接控制请求的响应逻辑。
-
-
使用 Filter 的场景:
-
需要对响应内容进行加工(如压缩、加密)。
-
需要修改响应头或添加额外信息。
-
需要对响应内容进行替换或过滤。
-
5. 示例对比
Handler 模块示例
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r) {
ngx_str_t response = ngx_string("Hello, World!");
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = response.len;
ngx_http_send_header(r);
ngx_http_output_filter(r, &response);
return NGX_OK;
}
Filter 模块示例
static ngx_int_t ngx_http_hello_body_filter(ngx_http_request_t *r, ngx_chain_t *in) {
ngx_chain_t *cl;
for (cl = in; cl; cl = cl->next) {
// 修改响应内容
ngx_buf_t *b = cl->buf;
if (b->pos && b->last > b->pos) {
ngx_memcpy(b->pos, "Hello, Filter!", 14);
b->last = b->pos + 14;
}
}
return ngx_http_next_body_filter(r, in);
}
总结
-
Handler 模块:用于生成响应内容,适合实现核心业务逻辑。
-
Filter 模块:用于加工响应内容,适合对响应进行修改或增强。
-
选择 Handler 还是 Filter 取决于具体的需求:如果需要直接生成响应内容,使用 Handler;如果需要对现有响应内容进行加工,使用 Filter。