我正在尝试编写一个 nginx 模块,它将过滤掉任何大小大于 1000KB 的资源的 GET 请求。我按照教程操作,模块编译并安装正常。但是我认为模块没有在传入请求上被调用。该模块由标头和正文过滤器组成,它们将检查传出请求的内容大小,如果大于 1000KB,它将清除响应正文并重定向到我将在防火墙中限制的不同端口。我使用了一些日志记录语句,但我在日志中看不到任何东西,因此我认为它没有被调用。我附上了完整的源代码
#include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> typedef struct { ngx_str_t download_filter; } ngx_http_download_conf_t; static void *ngx_http_download_create_conf(ngx_conf_t *cf); static ngx_int_t ngx_http_download_filter_init(ngx_conf_t *cf); static ngx_int_t ngx_http_download_header_filter(ngx_http_request_t *r); static ngx_int_t ngx_http_download_body_filter(ngx_http_request_t *r, ngx_chain_t *in); //static char *ngx_http_download_module( ngx_conf_t *cf, ngx_command_t *cmd, void *conf); //static u_char ngx_download_filter_module[] = "download filter"; static ngx_command_t ngx_download_filter_module_commands[] = { { ngx_string("download_filter"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_conf_set_str_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_download_conf_t, download_filter), NULL }, ngx_null_command }; static ngx_http_module_t ngx_http_download_filter_module_ctx = { NULL, /* preconfiguration */ ngx_http_download_filter_init, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_download_create_conf, /* create location configuration */ NULL /* merge location configuration */ }; ngx_module_t ngx_http_download_filter_module = { NGX_MODULE_V1, &ngx_http_download_filter_module_ctx, /* module context */ ngx_download_filter_module_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 }; static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t ngx_http_download_filter_init(ngx_conf_t *cf) { printf("hello world: inside init function\n"); ngx_http_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_download_header_filter; ngx_http_next_body_filter = ngx_http_top_body_filter; ngx_http_top_body_filter = ngx_http_download_body_filter; return NGX_OK; } static ngx_int_t ngx_http_download_header_filter( ngx_http_request_t *r) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "inside the header filter"); printf("inside header filter hello world\n"); ngx_str_t new_location= ngx_string("http://localhost:5000/flake.jpg"); if ( r->headers_out.content_length_n > 1000 && r->headers_out.status == NGX_HTTP_OK ) { r->headers_out.status = NGX_HTTP_MOVED_TEMPORARILY; r->headers_out.content_type.len = 0; r->headers_out.location->value.data = new_location.data; r->headers_out.location->value.len = new_location.len; ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); } r->headers_out.status = NGX_HTTP_MOVED_TEMPORARILY; return ngx_http_next_header_filter(r); } static ngx_int_t ngx_http_download_body_filter ( ngx_http_request_t *r, ngx_chain_t *in ) { if ( r->headers_out.content_length_n > 1000 && r->headers_out.status == NGX_HTTP_OK ) { r->discard_body = 0; return ngx_http_next_body_filter(r, in); } return ngx_http_next_body_filter(r, in); } static void * ngx_http_download_create_conf(ngx_conf_t *cf) { ngx_http_download_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_download_conf_t)); if (conf == NULL) { return NULL; } /* * set by ngx_pcalloc(): * * conf->before_body = { 0, NULL }; * conf->after_body = { 0, NULL }; * conf->types = { NULL }; * conf->types_keys = NULL; */ return conf; }
我的 nginx 配置使用了该download_filter
指令。以下是代码片段。
http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /tmp/log/access.log main; error_log /tmp/log/error.log info; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; download_filter;
当我启动 nginx 时,当我看到“hello world,inside init function”字符串时,模块就会初始化。
我遗漏了什么导致过滤器停止运行?我这里不使用处理程序,因为我不需要提供任何服务,只需让 nginx 完成工作并在提供服务之前使用过滤器即可。我需要处理程序吗?如果是,我该如何制作一个仅提供内容并让过滤器完成工作的处理程序。