要编写一个nginx模块来记录指定的post表单数据,可以按照以下步骤:

  1. 在nginx的配置文件中添加一个新的location,用于匹配需要记录表单数据的请求。例如:
location /submit {
    # TODO: add module configuration
}
  1. 在该location中添加一个新的指令,用于启用该模块。例如:
location /submit {
    record_form_data on;
}
  1. 在模块代码中定义一个新的指令,用于配置需要记录的表单字段。例如:
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
};
  1. 实现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;
}
  1. 定义模块上下文结构体ngx_http_record_form_data_loc_conf_t,用于保存指定的表单字段。例如:
typedef struct {
    ngx_array_t *fields;
} ngx_http_record_form_data_loc_conf_t;
  1. 实现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;
}
  1. 在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的日志中。

编写nginx模块记录指定的post表单数据

原文地址: https://www.cveoy.top/t/topic/bWQi 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录