Проблемы с получением request body
tigran.bayburtsyan
nginx-forum at nginx.us
Mon Dec 1 13:35:35 UTC 2014
Привет.
Я пишу модуль для Nginx в котором будут обрабатываются POST запросы.
Нашел несколько opensource проектов в которых тоже обрабатываются запросы
такого типа.
Например https://github.com/calio/form-input-nginx-module .
Сделал этот функционал , но оно работает только на локальной среде. Если
пробую с какого то online сервера то ответ от Nginx пустой.
Как я представляю в remote сервере request_body приходит гораздо медленнее
чем на локале и где то возврашет ответ до исполнения хандлера
ngx_http_read_client_request_body(r,toxic_post_body_handler).
Покапал в интернете ничего нет по этой теме. Просмотрел коды у других
модулей вроде у меня тоже так же.
Вот мой код.
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <ngx_event.h>
............................... // Еше несколько
typedef struct {
char *key;
void(*callback)(const char *str, unsigned int str_length);
} toxic_request_callback;
typedef struct
{
unsigned done:1;
unsigned waiting_more_body:1;
unsigned body_end:1;
} toxic_ctx;
static char *ngx_http_toxic(ngx_conf_t *cf, void *post, void *data);
static ngx_conf_post_handler_pt ngx_http_toxic_p = ngx_http_toxic;
typedef struct {
ngx_str_t name;
} ngx_http_toxic_loc_conf_t;
static void * ngx_http_toxic_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_toxic_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_toxic_loc_conf_t));
if (conf == NULL) {
return NULL;
}
return conf;
}
static ngx_command_t ngx_http_toxic_commands[] = {
{ ngx_string("toxic"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_toxic_loc_conf_t, name),
&ngx_http_toxic_p },
ngx_null_command
};
static ngx_str_t toxic_string;
static ngx_http_module_t ngx_http_toxic_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_toxic_create_loc_conf, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_http_toxic_module = {
NGX_MODULE_V1,
&ngx_http_toxic_module_ctx, /* module context */
ngx_http_toxic_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_int_t
ngx_http_toxic_handler(ngx_http_request_t *r);
static ngx_int_t toxic_excecute(ngx_http_request_t *r, char *content_type)
{
char * base_str;
int base_len = 0;
....................................................... // функционал с
base_str и base_len
r->headers_out.content_type_len = strlen(content_type);
r->headers_out.content_type.data = (u_char *) content_type;
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = base_len;
ngx_http_send_header(r);
ngx_buf_t *b;
ngx_chain_t *out;
out = ngx_pcalloc(r->pool, sizeof(out));
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL) {
return 0;
}
out->buf = b;
out->next = NULL;
/* adjust the pointers of the buffer */
b->pos = (u_char*)base_str;
b->last = (u_char*)base_str + base_len;
b->memory = 1; /* this buffer is in memory */
b->last_buf = 1; /* this is the last buffer in the buffer chain */
/* send the buffer chain of response */
ngx_int_t rc;
rc = ngx_http_output_filter ( r , out );
while( rc == NGX_AGAIN ) {
if( out->next == NULL )
break;
rc = ngx_http_output_filter ( r , out->next );
out = out->next;
}
return NGX_DONE;
}
static void toxic_post_body_handler(ngx_http_request_t *r)
{
toxic_ctx *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_toxic_module);
ctx->done = 1;
#if defined(nginx_version) && nginx_version >= 8011
r->main->count--;
#endif
/* waiting_more_body my rewrite phase handler */
if (ctx->waiting_more_body) {
ctx->waiting_more_body = 0;
ngx_http_core_run_phases(r->main); // Думаю проблема здесь но не
представляю что делать
}
// предполагаю что здесь уже весь POST пришел
ngx_buf_t * buf;
ngx_chain_t * chain;
char *post_body= "";
int post_len=0;
chain = r->request_body->bufs;
while (chain) {
buf = chain->buf;
int len = buf->end - buf->start;
if(post_len > 0)
{
post_body = (char*)realloc(post_body, sizeof(char) * (len +
post_len));
strncat(post_body, (char *)buf->start, len);
}
else
{
post_body = (char*)malloc(sizeof(char) * len);
int i;
for(i=0;i<len;i++)
{
post_body[i] = buf->start[i];
}
post_body[len] = '\0';
}
post_len += len;
chain = chain->next;
}
............................ // функционал с post_body и post_len
}
/*
* Main handler function of the module.
*/
static ngx_int_t
ngx_http_toxic_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
toxic_ctx *ctx;
if ((r->method & (NGX_HTTP_POST|NGX_HTTP_PUT))) {
ctx = ngx_http_get_module_ctx(r, ngx_http_toxic_module);
if (ctx != NULL) {
if (ctx->done) {
return NGX_DECLINED;
}
return NGX_DONE;
}
ctx = ngx_pcalloc(r->pool, sizeof(toxic_ctx));
if (ctx == NULL) {
return NGX_ERROR;
}
ngx_http_set_ctx(r, ctx, ngx_http_toxic_module);
rc =
ngx_http_read_client_request_body(r,toxic_post_body_handler);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
if (rc == NGX_AGAIN) {
ctx->waiting_more_body = 1;
ngx_http_set_ctx(r, ctx, ngx_http_toxic_module);
return NGX_DONE;
}
}
ngx_http_finalize_request(r, toxic_excecute(r, "text/html"));
return NGX_OK;
}
/*
* Function for the directive toxic , it validates its value
* and copies it to a static variable to be printed later
*/
static char * ngx_http_toxic(ngx_conf_t *cf, void *post, void *data)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_toxic_handler;
ngx_str_t *name = data; // i.e., first field of
ngx_http_toxic_loc_conf_t
if (ngx_strcmp(name->data, "") == 0) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
Posted at Nginx Forum: http://forum.nginx.org/read.php?21,255240,255240#msg-255240
Подробная информация о списке рассылки nginx-ru