编写nginx模块记录指定的post表单数据
要编写一个nginx模块来记录指定的post表单数据,可以按照以下步骤:
- 在nginx的配置文件中添加一个新的location,用于匹配需要记录表单数据的请求。例如:
location /submit {
# TODO: add module configuration
}
- 在该location中添加一个新的指令,用于启用该模块。例如:
location /submit {
record_form_data on;
}
- 在模块代码中定义一个新的指令,用于配置需要记录的表单字段。例如:
static ngx_command_t ngx_http_record_form_data_commands[] = {
{
ngx_string("record_form_data_fields"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_http_record_form_data_fields,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};
- 实现ngx_http_record_form_data_fields指令的处理函数,用于解析配置指令中指定的表单字段。例如:
static char *ngx_http_record_form_data_fields(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
ngx_http_record_form_data_loc_conf_t *lcf = conf;
ngx_str_t *value = cf->args->elts;
ngx_uint_t i;
lcf->fields = ngx_array_create(cf->pool, cf->args->nelts, sizeof(ngx_str_t));
if (lcf->fields == NULL) {
return NGX_CONF_ERROR;
}
for (i = 1; i < cf->args->nelts; i++) {
ngx_str_t *field = ngx_array_push(lcf->fields);
if (field == NULL) {
return NGX_CONF_ERROR;
}
*field = value[i];
}
clcf->handler = ngx_http_record_form_data_handler;
return NGX_CONF_OK;
}
- 定义模块上下文结构体ngx_http_record_form_data_loc_conf_t,用于保存指定的表单字段。例如:
typedef struct {
ngx_array_t *fields;
} ngx_http_record_form_data_loc_conf_t;
- 实现ngx_http_record_form_data_handler处理函数,用于将指定的表单字段记录到nginx的日志中。例如:
static ngx_int_t ngx_http_record_form_data_handler(ngx_http_request_t *r) {
ngx_chain_t *cl;
ngx_buf_t *buf;
ngx_str_t str;
ngx_uint_t i, j;
ngx_http_record_form_data_loc_conf_t *lcf;
lcf = ngx_http_get_module_loc_conf(r, ngx_http_record_form_data_module);
if (lcf == NULL) {
return NGX_DECLINED;
}
if (r->method != NGX_HTTP_POST) {
return NGX_DECLINED;
}
if (r->headers_in.content_type.len < sizeof("application/x-www-form-urlencoded") - 1 ||
ngx_strncmp(r->headers_in.content_type.data, "application/x-www-form-urlencoded", sizeof("application/x-www-form-urlencoded") - 1) != 0) {
return NGX_DECLINED;
}
if (r->request_body == NULL || r->request_body->bufs == NULL) {
return NGX_DECLINED;
}
str.len = 0;
for (cl = r->request_body->bufs; cl; cl = cl->next) {
if (cl->buf->last_buf || cl->buf->last_in_chain) {
buf = cl->buf;
} else {
continue;
}
str.len += buf->last - buf->pos;
}
if (str.len == 0) {
return NGX_DECLINED;
}
str.data = ngx_pnalloc(r->pool, str.len);
if (str.data == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
i = 0;
for (cl = r->request_body->bufs; cl; cl = cl->next) {
if (cl->buf->last_buf || cl->buf->last_in_chain) {
buf = cl->buf;
} else {
continue;
}
ngx_memcpy(str.data + i, buf->pos, buf->last - buf->pos);
i += buf->last - buf->pos;
}
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "form data: %V", &str);
for (i = 0; i < lcf->fields->nelts; i++) {
ngx_str_t *field = &((ngx_str_t *)lcf->fields->elts)[i];
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "form field %V: ", field);
for (j = 0; j < str.len; j++) {
if (j + field->len <= str.len && ngx_strncmp(str.data + j, field->data, field->len) == 0 && (j == 0 || str.data[j - 1] == '&')) {
j += field->len;
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "%V", &str.data[j]);
break;
}
}
}
return NGX_DECLINED;
}
- 在ngx_http_record_form_data_module的ngx_http_module_t结构体中添加相应的回调函数。例如:
static ngx_http_module_t ngx_http_record_form_data_module_ctx = {
NULL, /* preconfiguration */
ngx_http_record_form_data_init, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_record_form_data_create_loc_conf, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_http_record_form_data_module = {
NGX_MODULE_V1,
&ngx_http_record_form_data_module_ctx, /* module context */
ngx_http_record_form_data_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
};
此时,当客户端发送一个POST请求到指定的location时,如果请求的Content-Type是application/x-www-form-urlencoded,则该模块会解析请求体中的表单数据,并记录指定的字段到nginx的日志中。
原文地址: https://www.cveoy.top/t/topic/bWQi 著作权归作者所有。请勿转载和采集!