nginx-0.0.1-2003-02-11-19:42:23 import

This commit is contained in:
Igor Sysoev 2003-02-11 16:42:23 +00:00
parent 1e7ec9dcd2
commit 0a9d145c66
5 changed files with 154 additions and 351 deletions

View File

@ -55,6 +55,8 @@ struct ngx_hunk_s {
ngx_file_t *file; ngx_file_t *file;
}; };
typedef struct ngx_chain_s ngx_chain_t; typedef struct ngx_chain_s ngx_chain_t;
struct ngx_chain_s { struct ngx_chain_s {
ngx_hunk_t *hunk; ngx_hunk_t *hunk;
@ -62,6 +64,9 @@ struct ngx_chain_s {
}; };
#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR
ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size, ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
int before, int after); int before, int after);

View File

@ -141,6 +141,8 @@ int ngx_http_static_handler(ngx_http_request_t *r)
if (r->header_only) if (r->header_only)
return rc; return rc;
#if 0
h->type = NGX_HUNK_FILE|NGX_HUNK_LAST; h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
h->pos.file = 0; h->pos.file = 0;
h->last.file = ngx_file_size(r->file.info); h->last.file = ngx_file_size(r->file.info);
@ -152,5 +154,42 @@ int ngx_http_static_handler(ngx_http_request_t *r)
ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc); ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc);
#else
#define BLK 10000
{
int i, s;
s = ngx_file_size(r->file.info);
for (i = 0; i < s; i += BLK) {
ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)),
NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)),
NGX_HTTP_INTERNAL_SERVER_ERROR);
h->type = NGX_HUNK_FILE;
if (s - i <= BLK) {
h->type |= NGX_HUNK_LAST;
}
h->pos.file = i;
h->last.file = i + BLK;
if (h->last.file > s) {
h->last.file = s;
}
h->file->fd = r->file.fd;
h->file->log = r->connection->log;
rc = ngx_http_output_filter(r, h);
ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc);
}
}
#endif
return rc; return rc;
} }

View File

@ -57,7 +57,6 @@ ngx_module_t ngx_http_output_filter_module = {
}; };
#if 1
#define next_filter ngx_http_output_filter_module_ctx.next_output_body_filter #define next_filter ngx_http_output_filter_module_ctx.next_output_body_filter
@ -67,6 +66,7 @@ ngx_module_t ngx_http_output_filter_module = {
|| ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \ || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \
&& (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))) && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))))
int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
{ {
int rc; int rc;
@ -84,8 +84,9 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
sizeof(ngx_http_output_filter_ctx_t)); sizeof(ngx_http_output_filter_ctx_t));
} }
/* the incoming chain ctx->in is empty */ /* the short path for the case when the chain ctx->incoming is empty
if (ctx->in == NULL) { and there is no hunk or the hunk does not require the copy */
if (ctx->incoming == NULL) {
if (hunk == NULL) { if (hunk == NULL) {
return next_filter(r, NULL); return next_filter(r, NULL);
@ -98,91 +99,53 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
return next_filter(r, &ctx->out); return next_filter(r, &ctx->out);
} }
}
/* we need to copy the incoming hunk to our hunk */ /* add the incoming hunk to the chain ctx->incoming */
if (hunk) {
/* allocate ctx->hunk if it's needed */ /* the output of the only hunk is common case so we have
if (ctx->hunk == NULL) { special chain entry ctx->in for it */
if (ctx->incoming == NULL) {
ctx->in.hunk = hunk;
ctx->in.next = NULL;
ctx->incoming = &ctx->in;
conf = (ngx_http_output_filter_conf_t *) } else {
ngx_http_get_module_loc_conf(r->main ? r->main : r, for (ce = ctx->incoming; ce->next; ce = ce->next) {
ngx_http_output_filter_module); /* void */ ;
}
if (hunk->type & NGX_HUNK_LAST) { ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR);
size = hunk->last.mem - hunk->pos.mem; }
if (size > conf->hunk_size) { }
size = conf->hunk_size;
}
} else { /* allocate our hunk if it's needed */
if (ctx->hunk == NULL) {
conf = (ngx_http_output_filter_conf_t *)
ngx_http_get_module_loc_conf(r->main ? r->main : r,
ngx_http_output_filter_module);
if (hunk->type & NGX_HUNK_LAST) {
size = hunk->last.mem - hunk->pos.mem;
if (size > conf->hunk_size) {
size = conf->hunk_size; size = conf->hunk_size;
} }
ngx_test_null(ctx->hunk, } else {
ngx_create_temp_hunk(r->pool, size, 50, 50), size = conf->hunk_size;
NGX_ERROR);
ctx->hunk->type |= NGX_HUNK_RECYCLED;
} }
/* copy the incoming hunk or its part to our hunk ngx_test_null(ctx->hunk,
and pass it to the next filter */ ngx_create_temp_hunk(r->pool, size, 50, 50),
NGX_ERROR);
do { ctx->hunk->type |= NGX_HUNK_RECYCLED;
rc = ngx_http_output_filter_copy_hunk(ctx->hunk, hunk);
if (rc == NGX_ERROR) {
return rc;
}
#if (NGX_FILE_AIO_READ)
if (rc == NGX_AGAIN) {
/* add the incoming hunk to the incoming chain */
ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR);
return rc;
}
#endif
ctx->out.hunk = ctx->hunk;
ctx->out.next = NULL;
rc = next_filter(r, &ctx->out);
if (rc == NGX_ERROR) {
return rc;
}
if (rc == NGX_AGAIN) {
/* add the incoming hunk to the incoming chain */
ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR);
return rc;
}
/* NGX_OK */
/* set our hunk free */
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
/* repeat until we will have copied the whole incoming hunk */
} while (hunk->pos.mem < hunk->last.mem);
return NGX_OK;
}
/* the incoming chain ctx->in is not empty */
/* add the incoming hunk to the incoming chain */
if (hunk) {
for (ce = ctx->in; ce->next; ce = ce->next) {
/* void */ ;
}
ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR);
}
/* our hunk is still busy */ /* our hunk is still busy */
if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { } else if (ctx->hunk->pos.mem < ctx->hunk->last.mem) {
rc = next_filter(r, NULL); rc = next_filter(r, NULL);
if (rc == NGX_ERROR || rc == NGX_AGAIN) { if (rc == NGX_ERROR || rc == NGX_AGAIN) {
@ -190,6 +153,8 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
} }
/* NGX_OK */ /* NGX_OK */
/* set our hunk free */
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
} }
@ -197,10 +162,10 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
pe = NULL; pe = NULL;
#endif #endif
/* process the incoming chain ctx->in */ /* process the chain ctx->incoming */
do { do {
/* find the hunks that do not need to be copied ... */ /* find the hunks that do not need to be copied ... */
for (ce = ctx->in; ce; ce = ce->next) { for (ce = ctx->incoming; ce; ce = ce->next) {
if (need_to_copy(r, ce->hunk)) { if (need_to_copy(r, ce->hunk)) {
break; break;
} }
@ -208,11 +173,11 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
} }
/* ... and pass them to the next filter */ /* ... and pass them to the next filter */
if (ctx->in != ce) { if (ctx->incoming != ce) {
ctx->out.hunk = ctx->in->hunk; ctx->out.hunk = ctx->incoming->hunk;
ctx->out.next = ctx->in->next; ctx->out.next = ctx->incoming->next;
ctx->in = ce; ctx->incoming = ce;
pe->next = NULL; pe->next = NULL;
rc = next_filter(r, &ctx->out); rc = next_filter(r, &ctx->out);
@ -222,16 +187,16 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
} }
/* NGX_OK */ /* NGX_OK */
if (ctx->in == NULL) { if (ctx->incoming == NULL) {
return rc; return rc;
} }
} }
/* copy the first hunk or its part from the chain ctx->incoming
/* copy the first hunk or its part from the incoming chain ctx->in
to our hunk and pass it to the next filter */ to our hunk and pass it to the next filter */
do { do {
rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); rc = ngx_http_output_filter_copy_hunk(ctx->hunk,
ctx->incoming->hunk);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
return rc; return rc;
@ -259,243 +224,19 @@ int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
/* repeat until we will have copied the whole first hunk from /* repeat until we will have copied the whole first hunk from
the incoming chain ctx->in */ the chain ctx->incoming */
} while (ctx->in->hunk->pos.mem < ctx->in->hunk->last.mem); } while (ctx->incoming->hunk->pos.mem < ctx->incoming->hunk->last.mem);
/* delete the completed hunk from the incoming chain */ /* delete the completed hunk from the incoming chain */
ctx->in = ctx->in->next; ctx->incoming = ctx->incoming->next;
/* repeat until we will have processed the whole incoming chain ctx->in */ /* repeat until we will have processed the whole chain ctx->incoming */
} while (ctx->in); } while (ctx->incoming);
return NGX_OK; return NGX_OK;
} }
#else
int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk)
{
int rc, once;
u_int flags;
size_t size;
ngx_chain_t *ce;
ngx_http_output_filter_ctx_t *ctx;
ngx_http_output_filter_conf_t *conf;
ctx = (ngx_http_output_filter_ctx_t *)
ngx_http_get_module_ctx(r->main ? r->main : r,
ngx_http_output_filter_module);
if (ctx == NULL) {
ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module,
sizeof(ngx_http_output_filter_ctx_t));
}
if (hunk && (hunk->type & NGX_HUNK_LAST)) {
ctx->last = 1;
}
#if (NGX_SUPPRESS_WARN)
rc = NGX_ALERT;
#endif
for (once = 1; once || ctx->in; once = 0) {
/* input chain is not empty */
if (ctx->in) {
/* add hunk to input chain */
if (once && hunk) {
for (ce = ctx->in; ce->next; ce = ce->next) {
/* void */ ;
}
ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR);
}
/* our hunk is still busy */
if (ctx->hunk->pos.mem < ctx->hunk->last.mem) {
rc = ngx_http_output_filter_module_ctx.
next_output_body_filter(r, NULL);
/* our hunk is free */
} else {
ctx->out.hunk = ctx->hunk;
/* XXX: should we check hunk type before copy it ? */
rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk);
#if (NGX_FILE_AIO_READ)
if (rc == NGX_AGAIN) {
return rc;
}
#endif
if (rc == NGX_ERROR) {
return rc;
}
/* NGX_OK */
/* whole hunk is copied so we send to next filter chain part
up to next hunk that need to be copied */
if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) {
ctx->out.next = ctx->in->next;
for (ce = ctx->in->next; ce; ce = ce->next) {
if (ce->hunk->type & NGX_HUNK_FILE) {
break;
}
if ((ce->hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))
&& (r->filter & NGX_HTTP_FILTER_NEED_TEMP))
{
break;
}
}
ctx->out.next = ce;
} else {
ctx->out.next = NULL;
}
rc = ngx_http_output_filter_module_ctx.
next_output_body_filter(r, &ctx->out);
}
/* delete completed hunks from input chain */
for (ce = ctx->in; ce; ce = ce->next) {
if (ce->hunk->pos.file == ce->hunk->last.file) {
ctx->in = ce->next;
}
}
if (rc == NGX_OK && ctx->hunk) {
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
} else {
return rc;
}
/* input chain is empty */
} else {
if (hunk == NULL) {
rc = ngx_http_output_filter_module_ctx.
next_output_body_filter(r, NULL);
} else {
/* we need to copy hunk to our hunk */
if (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)
&& (hunk->type & NGX_HUNK_FILE))
|| ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)
&& (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))
) {
/* out hunk is still busy */
if (ctx->hunk && ctx->hunk->pos.mem < ctx->hunk->last.mem) {
ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
NGX_ERROR);
rc = ngx_http_output_filter_module_ctx.
next_output_body_filter(r, NULL);
} else {
if (ctx->hunk == NULL) {
conf = (ngx_http_output_filter_conf_t *)
ngx_http_get_module_loc_conf(
r->main ? r->main : r,
ngx_http_output_filter_module);
if (hunk->type & NGX_HUNK_LAST) {
size = hunk->last.mem - hunk->pos.mem;
if (size > conf->hunk_size) {
size = conf->hunk_size;
}
} else {
size = conf->hunk_size;
}
ngx_test_null(ctx->hunk,
ngx_create_temp_hunk(r->pool, size,
50, 50),
NGX_ERROR);
ctx->hunk->type |= NGX_HUNK_RECYCLED;
rc = ngx_http_output_filter_copy_hunk(ctx->hunk,
hunk);
#if (NGX_FILE_AIO_READ)
if (rc == NGX_AGAIN) {
/* add hunk to input chain */
ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
NGX_ERROR);
return rc;
}
#endif
if (rc == NGX_ERROR) {
return rc;
}
if (hunk->pos.mem < hunk->last.mem) {
ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
NGX_ERROR);
}
ctx->out.hunk = ctx->hunk;
ctx->out.next = NULL;
rc = ngx_http_output_filter_module_ctx.
next_output_body_filter(r, &ctx->out);
}
}
} else {
ctx->out.hunk = hunk;
ctx->out.next = NULL;
rc = ngx_http_output_filter_module_ctx.
next_output_body_filter(r, &ctx->out);
}
}
}
/* set free our hunk if operation has completed */
if (rc == NGX_OK && ctx->hunk) {
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
}
}
#if (NGX_SUPPRESS_WARN)
if (rc == NGX_ALERT) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"ngx_http_output_filter: rc == NGX_ALERT");
return NGX_ERROR;
}
#endif
if (rc == NGX_OK && ctx->last) {
return NGX_OK;
}
if (rc == NGX_OK) {
if (ctx->hunk) { /* XXX: double upper code ? */
ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start;
}
#if (NGX_LEVEL_EVENT)
ngx_del_event(r->connection->write, NGX_WRITE_EVENT);
#endif
}
return rc;
}
#endif
static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src) static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src)
{ {
ssize_t n, size; ssize_t n, size;
@ -510,16 +251,23 @@ static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src)
if (n == NGX_ERROR) { if (n == NGX_ERROR) {
return n; return n;
}
#if (NGX_FILE_AIO_READ) #if (NGX_FILE_AIO_READ)
} else if (n == NGX_AGAIN) {
if (n == NGX_AGAIN) {
return n; return n;
}
#endif #endif
} else { if (n != size) {
ngx_assert((n == size), /* void */ ; , src->file->log, ngx_log_error(NGX_LOG_ALERT, src->file->log, 0,
ngx_read_file_n " reads only %d of %d" _ ngx_read_file_n " reads only %d of %d from file",
n _ size); n, size);
if (n == 0) {
return NGX_ERROR;
}
} }
src->pos.mem += n; src->pos.mem += n;

View File

@ -18,9 +18,10 @@ typedef struct {
typedef struct { typedef struct {
ngx_hunk_t *hunk; ngx_hunk_t *hunk; /* the temporary hunk to copy */
ngx_chain_t *in; ngx_chain_t *incoming;
ngx_chain_t out; ngx_chain_t in; /* one chain entry for input */
ngx_chain_t out; /* one chain entry for output */
} ngx_http_output_filter_ctx_t; } ngx_http_output_filter_ctx_t;

View File

@ -57,9 +57,9 @@ ngx_module_t ngx_http_write_filter_module = {
int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
{ {
int last; int last;
off_t size, flush; off_t size, flush;
ngx_chain_t *ch, **prev, *chain; ngx_chain_t *ce, **le, *chain;
ngx_http_write_filter_ctx_t *ctx; ngx_http_write_filter_ctx_t *ctx;
ngx_http_write_filter_conf_t *conf; ngx_http_write_filter_conf_t *conf;
@ -74,51 +74,51 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
size = flush = 0; size = flush = 0;
last = 0; last = 0;
prev = &ctx->out; le = &ctx->out;
/* find size, flush point and last link of saved chain */ /* find the size, the flush point and the last entry of saved chain */
for (ch = ctx->out; ch; ch = ch->next) { for (ce = ctx->out; ce; ce = ce->next) {
prev = &ch->next; le = &ce->next;
size += ch->hunk->last.file - ch->hunk->pos.file; size += ce->hunk->last.file - ce->hunk->pos.file;
#if (NGX_DEBUG_WRITE_FILTER) #if (NGX_DEBUG_WRITE_FILTER0)
ngx_log_debug(r->connection->log, "write filter: old chunk: %x " ngx_log_debug(r->connection->log, "write filter: old chunk: %x "
QX_FMT " " QD_FMT _ QX_FMT " " QD_FMT _
ch->hunk->type _ ch->hunk->pos.file _ ce->hunk->type _ ce->hunk->pos.file _
ch->hunk->last.file - ch->hunk->pos.file); ce->hunk->last.file - ce->hunk->pos.file);
#endif #endif
if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
flush = size; flush = size;
} }
if (ch->hunk->type & NGX_HUNK_LAST) { if (ce->hunk->type & NGX_HUNK_LAST) {
last = 1; last = 1;
} }
} }
/* add new chain to existent one */ /* add the new chain to the existent one */
for (/* void */; in; in = in->next) { for (/* void */; in; in = in->next) {
ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR); ngx_test_null(ce, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR);
ch->hunk = in->hunk; ce->hunk = in->hunk;
ch->next = NULL; ce->next = NULL;
*prev = ch; *le = ce;
prev = &ch->next; le = &ce->next;
size += ch->hunk->last.file - ch->hunk->pos.file; size += ce->hunk->last.file - ce->hunk->pos.file;
#if (NGX_DEBUG_WRITE_FILTER) #if (NGX_DEBUG_WRITE_FILTER0)
ngx_log_debug(r->connection->log, "write filter: new chunk: %x " ngx_log_debug(r->connection->log, "write filter: new hunk: %x "
QX_FMT " " QD_FMT _ QX_FMT " " QD_FMT _
ch->hunk->type _ ch->hunk->pos.file _ ce->hunk->type _ ce->hunk->pos.file _
ch->hunk->last.file - ch->hunk->pos.file); ce->hunk->last.file - ce->hunk->pos.file);
#endif #endif
if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) {
flush = size; flush = size;
} }
if (ch->hunk->type & NGX_HUNK_LAST) { if (ce->hunk->type & NGX_HUNK_LAST) {
last = 1; last = 1;
} }
} }
@ -127,25 +127,35 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_http_get_module_loc_conf(r->main ? r->main : r, ngx_http_get_module_loc_conf(r->main ? r->main : r,
ngx_http_write_filter_module); ngx_http_write_filter_module);
#if (NGX_DEBUG_WRITE_FILTER) #if (NGX_DEBUG_WRITE_FILTER0)
ngx_log_debug(r->connection->log, "write filter: last:%d flush:%d" _ ngx_log_debug(r->connection->log, "write filter: last:%d flush:%d" _
last _ flush); last _ flush);
#endif #endif
/* avoid the output if there is no last hunk, no flush point and
size of the hunks is smaller then 'write_buffer' */
if (!last && flush == 0 && size < conf->buffer_output) { if (!last && flush == 0 && size < conf->buffer_output) {
return NGX_OK; return NGX_OK;
} }
chain = ngx_event_write(r->connection, ctx->out, flush); chain = ngx_event_write(r->connection, ctx->out, flush);
if (chain == (ngx_chain_t *) -1) {
#if (NGX_DEBUG_WRITE_FILTER)
ngx_log_debug(r->connection->log, "write filter %x" _ chain);
#endif
if (chain == NGX_CHAIN_ERROR) {
return NGX_ERROR; return NGX_ERROR;
} }
ctx->out = chain; ctx->out = chain;
ngx_log_debug(r->connection->log, "write filter %x" _ chain); if (chain == NULL) {
return NGX_OK;
return (chain ? NGX_AGAIN : NGX_OK); } else {
return NGX_AGAIN;
}
} }