# HG changeset patch # User Igor Sysoev # Date 1228683600 -10800 # Node ID e7dbea1ee115c746298309e05501fc13ce942547 # Parent f64d9e30046c0e3576098dad99c8f2aa0d4aa1b7 nginx 0.7.25 *) Change: in subrequest processing. *) Change: now POSTs without "Content-Length" header line are allowed. *) Bugfix: now the "limit_req" and "limit_conn" directives log a prohibition reason. *) Bugfix: in the "delete" parameter of the "geo" directive. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,16 @@ +Changes with nginx 0.7.25 08 Dec 2008 + + *) Change: in subrequest processing. + + *) Change: now POSTs without "Content-Length" header line are allowed. + + *) Bugfix: now the "limit_req" and "limit_conn" directives log a + prohibition reason. + + *) Bugfix: in the "delete" parameter of the "geo" directive. + + Changes with nginx 0.7.24 01 Dec 2008 *) Feature: the "if_modified_since" directive. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,17 @@ +Изменения в nginx 0.7.25 08.12.2008 + + *) Изменение: в обработке подзапросов. + + *) Изменение: теперь разрешаются POST'ы без строки "Content-Length" в + заголовке запроса. + + *) Исправление: теперь директивы limit_req и limit_conn указывают + причину запрета запроса. + + *) Исправление: в параметре delete директивы geo. + + Изменения в nginx 0.7.24 01.12.2008 *) Добавление: директива if_modified_since. diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VERSION "0.7.24" +#define NGINX_VERSION "0.7.25" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_radix_tree.c b/src/core/ngx_radix_tree.c --- a/src/core/ngx_radix_tree.c +++ b/src/core/ngx_radix_tree.c @@ -42,13 +42,13 @@ ngx_radix_tree_create(ngx_pool_t *pool, } /* - * The preallocation the first nodes: 0, 1, 00, 01, 10, 11, 000, 001, etc. - * increases the TLB hits even if for the first lookup iterations. - * On the 32-bit platforms the 7 preallocated bits takes continuous 4K, - * 8 - 8K, 9 - 16K, etc. On the 64-bit platforms the 6 preallocated bits + * Preallocation of first nodes : 0, 1, 00, 01, 10, 11, 000, 001, etc. + * increases TLB hits even if for first lookup iterations. + * On 32-bit platforms the 7 preallocated bits takes continuous 4K, + * 8 - 8K, 9 - 16K, etc. On 64-bit platforms the 6 preallocated bits * takes continuous 4K, 7 - 8K, 8 - 16K, etc. There is no sense to * to preallocate more than one page, because further preallocation - * distributes the only bit per page. Instead, the random insertion + * distributes the only bit per page. Instead, a random insertion * may distribute several bits per page. * * Thus, by default we preallocate maximum diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c --- a/src/http/modules/ngx_http_addition_filter_module.c +++ b/src/http/modules/ngx_http_addition_filter_module.c @@ -151,10 +151,10 @@ ngx_http_addition_body_filter(ngx_http_r ctx->before_body_sent = 1; if (conf->before_body.len) { - rc = ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0); - - if (rc == NGX_ERROR || rc == NGX_DONE) { - return rc; + if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0) + != NGX_OK) + { + return NGX_ERROR; } } } @@ -180,10 +180,10 @@ ngx_http_addition_body_filter(ngx_http_r return rc; } - rc = ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0); - - if (rc == NGX_ERROR || rc == NGX_DONE) { - return rc; + if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0) + != NGX_OK) + { + return NGX_ERROR; } ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -299,6 +299,11 @@ ngx_http_autoindex_handler(ngx_http_requ if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_de_info_n " \"%s\" failed", filename); + + if (err == NGX_EACCES) { + continue; + } + return ngx_http_autoindex_error(r, &dir, &path); } diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -666,8 +666,9 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "no network \"%V\" to delete", net); - return NGX_CONF_OK; } + + return NGX_CONF_OK; } } diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c @@ -38,8 +38,8 @@ typedef struct { static void ngx_http_limit_req_delay(ngx_http_request_t *r); -static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lzcf, - ngx_uint_t hash, u_char *data, size_t len, ngx_http_limit_req_node_t **lzp); +static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, + ngx_uint_t hash, u_char *data, size_t len, ngx_http_limit_req_node_t **lrp); static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n); @@ -115,20 +115,20 @@ ngx_http_limit_req_handler(ngx_http_requ ngx_rbtree_node_t *node; ngx_http_variable_value_t *vv; ngx_http_limit_req_ctx_t *ctx; - ngx_http_limit_req_node_t *lz; - ngx_http_limit_req_conf_t *lzcf; + ngx_http_limit_req_node_t *lr; + ngx_http_limit_req_conf_t *lrcf; if (r->main->limit_req_set) { return NGX_DECLINED; } - lzcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module); + lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module); - if (lzcf->shm_zone == NULL) { + if (lrcf->shm_zone == NULL) { return NGX_DECLINED; } - ctx = lzcf->shm_zone->data; + ctx = lrcf->shm_zone->data; vv = ngx_http_get_indexed_variable(r, ctx->index); @@ -158,14 +158,14 @@ ngx_http_limit_req_handler(ngx_http_requ ngx_http_limit_req_expire(ctx, 1); - rc = ngx_http_limit_req_lookup(lzcf, hash, vv->data, len, &lz); + rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr); - if (lz) { - ngx_queue_remove(&lz->queue); + if (lr) { + ngx_queue_remove(&lr->queue); - ngx_queue_insert_head(ctx->queue, &lz->queue); + ngx_queue_insert_head(ctx->queue, &lr->queue); - excess = lz->excess; + excess = lr->excess; } else { excess = 0; @@ -178,8 +178,8 @@ ngx_http_limit_req_handler(ngx_http_requ ngx_shmtx_unlock(&ctx->shpool->mutex); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "limiting requests, excess: %ui.%03ui", - excess / 1000, excess % 1000); + "limiting requests, excess: %ui.%03ui by zone \"%V\"", + excess / 1000, excess % 1000, &lrcf->shm_zone->name); return NGX_HTTP_SERVICE_UNAVAILABLE; } @@ -187,13 +187,13 @@ ngx_http_limit_req_handler(ngx_http_requ if (rc == NGX_AGAIN) { ngx_shmtx_unlock(&ctx->shpool->mutex); - if (lzcf->nodelay) { + if (lrcf->nodelay) { return NGX_DECLINED; } ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, - "delaying request, excess: %ui.%03ui", - excess / 1000, excess % 1000); + "delaying request, excess: %ui.%03ui, by zone \"%V\"", + excess / 1000, excess % 1000, &lrcf->shm_zone->name); if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -224,24 +224,29 @@ ngx_http_limit_req_handler(ngx_http_requ node = ngx_slab_alloc_locked(ctx->shpool, n); if (node == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); + + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "could not allocate memory in zone \"%V\"", + &lrcf->shm_zone->name); + return NGX_HTTP_SERVICE_UNAVAILABLE; } } - lz = (ngx_http_limit_req_node_t *) &node->color; + lr = (ngx_http_limit_req_node_t *) &node->color; node->key = hash; - lz->len = (u_char) len; + lr->len = (u_char) len; tp = ngx_timeofday(); - lz->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); + lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); - lz->excess = 0; - ngx_memcpy(lz->data, vv->data, len); + lr->excess = 0; + ngx_memcpy(lr->data, vv->data, len); ngx_rbtree_insert(ctx->rbtree, node); - ngx_queue_insert_head(ctx->queue, &lz->queue); + ngx_queue_insert_head(ctx->queue, &lr->queue); done: @@ -274,7 +279,7 @@ ngx_http_limit_req_rbtree_insert_value(n ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { ngx_rbtree_node_t **p; - ngx_http_limit_req_node_t *lzn, *lznt; + ngx_http_limit_req_node_t *lrn, *lrnt; for ( ;; ) { @@ -288,10 +293,10 @@ ngx_http_limit_req_rbtree_insert_value(n } else { /* node->key == temp->key */ - lzn = (ngx_http_limit_req_node_t *) &node->color; - lznt = (ngx_http_limit_req_node_t *) &temp->color; + lrn = (ngx_http_limit_req_node_t *) &node->color; + lrnt = (ngx_http_limit_req_node_t *) &temp->color; - p = (ngx_memn2cmp(lzn->data, lznt->data, lzn->len, lznt->len) < 0) + p = (ngx_memn2cmp(lrn->data, lrnt->data, lrn->len, lrnt->len) < 0) ? &temp->left : &temp->right; } @@ -311,8 +316,8 @@ ngx_http_limit_req_rbtree_insert_value(n static ngx_int_t -ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lzcf, ngx_uint_t hash, - u_char *data, size_t len, ngx_http_limit_req_node_t **lzp) +ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, + u_char *data, size_t len, ngx_http_limit_req_node_t **lrp) { ngx_int_t rc, excess; ngx_time_t *tp; @@ -320,9 +325,9 @@ ngx_http_limit_req_lookup(ngx_http_limit ngx_msec_int_t ms; ngx_rbtree_node_t *node, *sentinel; ngx_http_limit_req_ctx_t *ctx; - ngx_http_limit_req_node_t *lz; + ngx_http_limit_req_node_t *lr; - ctx = lzcf->shm_zone->data; + ctx = lrcf->shm_zone->data; node = ctx->rbtree->root; sentinel = ctx->rbtree->sentinel; @@ -342,29 +347,29 @@ ngx_http_limit_req_lookup(ngx_http_limit /* hash == node->key */ do { - lz = (ngx_http_limit_req_node_t *) &node->color; + lr = (ngx_http_limit_req_node_t *) &node->color; - rc = ngx_memn2cmp(data, lz->data, len, (size_t) lz->len); + rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); if (rc == 0) { tp = ngx_timeofday(); now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); - ms = (ngx_msec_int_t) (now - lz->last); + ms = (ngx_msec_int_t) (now - lr->last); - excess = lz->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; + excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; if (excess < 0) { excess = 0; } - lz->excess = excess; - lz->last = now; + lr->excess = excess; + lr->last = now; - *lzp = lz; + *lrp = lr; - if ((ngx_uint_t) excess > lzcf->burst) { + if ((ngx_uint_t) excess > lrcf->burst) { return NGX_BUSY; } @@ -382,7 +387,7 @@ ngx_http_limit_req_lookup(ngx_http_limit break; } - *lzp = NULL; + *lrp = NULL; return NGX_DECLINED; } @@ -397,7 +402,7 @@ ngx_http_limit_req_expire(ngx_http_limit ngx_queue_t *q; ngx_msec_int_t ms; ngx_rbtree_node_t *node; - ngx_http_limit_req_node_t *lz; + ngx_http_limit_req_node_t *lr; tp = ngx_timeofday(); @@ -417,18 +422,18 @@ ngx_http_limit_req_expire(ngx_http_limit q = ngx_queue_last(ctx->queue); - lz = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); + lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); if (n++ != 0) { - ms = (ngx_msec_int_t) (now - lz->last); + ms = (ngx_msec_int_t) (now - lr->last); ms = ngx_abs(ms); if (ms < 60000) { return; } - excess = lz->excess - ctx->rate * ms / 1000; + excess = lr->excess - ctx->rate * ms / 1000; if (excess > 0) { return; @@ -438,7 +443,7 @@ ngx_http_limit_req_expire(ngx_http_limit ngx_queue_remove(q); node = (ngx_rbtree_node_t *) - ((u_char *) lz - offsetof(ngx_rbtree_node_t, color)); + ((u_char *) lr - offsetof(ngx_rbtree_node_t, color)); ngx_rbtree_delete(ctx->rbtree, node); @@ -513,7 +518,7 @@ ngx_http_limit_req_create_conf(ngx_conf_ * set by ngx_pcalloc(): * * conf->shm_zone = NULL; - * conf->burst = 0.0; + * conf->burst = 0; * conf->nodelay = 0; */ @@ -671,13 +676,13 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, static char * ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_limit_req_conf_t *lzcf = conf; + ngx_http_limit_req_conf_t *lrcf = conf; ngx_int_t burst; ngx_str_t *value, s; ngx_uint_t i; - if (lzcf->shm_zone) { + if (lrcf->shm_zone) { return "is duplicate"; } @@ -692,9 +697,9 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c s.len = value[i].len - 5; s.data = value[i].data + 5; - lzcf->shm_zone = ngx_shared_memory_add(cf, &s, 0, + lrcf->shm_zone = ngx_shared_memory_add(cf, &s, 0, &ngx_http_limit_req_module); - if (lzcf->shm_zone == NULL) { + if (lrcf->shm_zone == NULL) { return NGX_CONF_ERROR; } @@ -714,7 +719,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c } if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) { - lzcf->nodelay = 1; + lrcf->nodelay = 1; continue; } @@ -723,21 +728,21 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c return NGX_CONF_ERROR; } - if (lzcf->shm_zone == NULL) { + if (lrcf->shm_zone == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%V\" must have \"zone\" parameter", &cmd->name); return NGX_CONF_ERROR; } - if (lzcf->shm_zone->data == NULL) { + if (lrcf->shm_zone->data == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unknown limit_req_zone \"%V\"", - &lzcf->shm_zone->name); + &lrcf->shm_zone->name); return NGX_CONF_ERROR; } - lzcf->burst = burst * 1000; + lrcf->burst = burst * 1000; return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_limit_zone_module.c b/src/http/modules/ngx_http_limit_zone_module.c --- a/src/http/modules/ngx_http_limit_zone_module.c +++ b/src/http/modules/ngx_http_limit_zone_module.c @@ -189,6 +189,10 @@ ngx_http_limit_zone_handler(ngx_http_req ngx_shmtx_unlock(&shpool->mutex); + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "limiting connections by zone \"%V\"", + &lzcf->shm_zone->name); + return NGX_HTTP_SERVICE_UNAVAILABLE; } @@ -206,6 +210,11 @@ ngx_http_limit_zone_handler(ngx_http_req node = ngx_slab_alloc_locked(shpool, n); if (node == NULL) { ngx_shmtx_unlock(&shpool->mutex); + + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "could not allocate memory in zone \"%V\"", + &lzcf->shm_zone->name); + return NGX_HTTP_SERVICE_UNAVAILABLE; } @@ -462,6 +471,10 @@ ngx_http_limit_conn(ngx_conf_t *cf, ngx_ ngx_int_t n; ngx_str_t *value; + if (lzcf->shm_zone) { + return "is duplicate"; + } + value = cf->args->elts; lzcf->shm_zone = ngx_shared_memory_add(cf, &value[1], 0, diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -375,7 +375,6 @@ ngx_http_ssi_body_filter(ngx_http_reques ngx_uint_t i, index; ngx_chain_t *cl, **ll; ngx_table_elt_t *param; - ngx_http_request_t *pr; ngx_http_ssi_ctx_t *ctx, *mctx; ngx_http_ssi_block_t *bl; ngx_http_ssi_param_t *prm; @@ -403,44 +402,37 @@ ngx_http_ssi_body_filter(ngx_http_reques } } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter \"%V?%V\"", &r->uri, &r->args); + if (ctx->wait) { - if (r->connection->data != r) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\" wait", &r->uri); + + if (r != r->connection->data) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter wait \"%V?%V\" non-active", + &ctx->wait->uri, &ctx->wait->args); + return NGX_AGAIN; } - for (pr = ctx->wait->parent; pr; pr = pr->parent) { - if (pr == r) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\" flush", &r->uri); - - rc = ngx_http_next_body_filter(r, NULL); - - if (ctx->wait->done) { - ctx->wait = NULL; - } - - if (rc == NGX_ERROR || rc == NGX_AGAIN) { - return rc; - } - - break; - } - } - - if (ctx->wait == r) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\" continue", &r->uri); + if (ctx->wait->done) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter wait \"%V?%V\" done", + &ctx->wait->uri, &ctx->wait->args); + ctx->wait = NULL; + + } else { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter wait \"%V?%V\"", + &ctx->wait->uri, &ctx->wait->args); + + return ngx_http_next_body_filter(r, NULL); } } slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\"", &r->uri); - while (ctx->in || ctx->buf) { if (ctx->buf == NULL ){ @@ -788,16 +780,12 @@ ngx_http_ssi_body_filter(ngx_http_reques } } - if (cmd->flush) { - - if (ctx->out) { - rc = ngx_http_ssi_output(r, ctx); - - } else { - rc = ngx_http_next_body_filter(r, NULL); - } - - if (rc == NGX_ERROR) { + if (cmd->flush && ctx->out) { + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "ssi flush"); + + if (ngx_http_ssi_output(r, ctx) == NGX_ERROR) { return NGX_ERROR; } } @@ -2001,6 +1989,10 @@ ngx_http_ssi_include(ngx_http_request_t } } + if (wait) { + flags |= NGX_HTTP_SUBREQUEST_WAITED; + } + if (set) { key = ngx_hash_strlow(set->data, set->data, set->len); @@ -2033,16 +2025,10 @@ ngx_http_ssi_include(ngx_http_request_t psr->data = &var->value; } - flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY; + flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY|NGX_HTTP_SUBREQUEST_WAITED; } - rc = ngx_http_subrequest(r, uri, &args, &sr, psr, flags); - - if (rc == NGX_DONE) { - return NGX_DONE; - } - - if (rc == NGX_ERROR) { + if (ngx_http_subrequest(r, uri, &args, &sr, psr, flags) != NGX_OK) { return NGX_HTTP_SSI_ERROR; } @@ -2050,17 +2036,17 @@ ngx_http_ssi_include(ngx_http_request_t return NGX_OK; } - if (rc == NGX_AGAIN) { - if (ctx->wait == NULL) { - ctx->wait = sr; - - } else { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "only one subrequest may be waited at the same time"); - } + if (ctx->wait == NULL) { + ctx->wait = sr; + + return NGX_AGAIN; + + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "only one subrequest may be waited at the same time"); } - return rc; + return NGX_OK; } diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -217,7 +217,7 @@ ngx_http_static_handler(ngx_http_request return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (r != r->main && of.size == 0) { + if (of.size == 0) { return ngx_http_send_header(r); } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.7.24'; +our $VERSION = '0.7.25'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -80,11 +80,14 @@ ngx_int_t ngx_http_parse_multi_header_li ngx_int_t ngx_http_find_server_conf(ngx_http_request_t *r); void ngx_http_update_location_config(ngx_http_request_t *r); void ngx_http_handler(ngx_http_request_t *r); +void ngx_http_run_posted_requests(ngx_connection_t *c); +ngx_int_t ngx_http_post_request(ngx_http_request_t *r); void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc); void ngx_http_empty_handler(ngx_event_t *wev); void ngx_http_request_empty_handler(ngx_http_request_t *r); + #define NGX_HTTP_LAST 1 #define NGX_HTTP_FLUSH 2 diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -117,10 +117,6 @@ ngx_http_copy_filter(ngx_http_request_t r->buffered |= NGX_HTTP_COPY_BUFFERED; } - if (r != r->main) { - r->out = ctx->in; - } - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args); } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1831,7 +1831,6 @@ ngx_http_subrequest(ngx_http_request_t * { ngx_connection_t *c; ngx_http_request_t *sr; - ngx_http_log_ctx_t *ctx; ngx_http_core_srv_conf_t *cscf; ngx_http_postponed_request_t *pr, *p; @@ -1896,6 +1895,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0; sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0; + sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0; sr->unparsed_uri = r->unparsed_uri; sr->method_name = ngx_http_core_get_method; @@ -1909,7 +1909,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->parent = r; sr->post_subrequest = ps; sr->read_event_handler = ngx_http_request_empty_handler; - sr->write_event_handler = ngx_http_request_empty_handler; + sr->write_event_handler = ngx_http_handler; if (c->data == r) { c->data = sr; @@ -1940,39 +1940,18 @@ ngx_http_subrequest(ngx_http_request_t * r->postponed = pr; } - ctx = c->log->data; - ctx->current_request = sr; - sr->internal = 1; - sr->fast_subrequest = 1; sr->discard_body = r->discard_body; sr->main_filter_need_in_memory = r->main_filter_need_in_memory; sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; - ngx_http_handler(sr); - - if (!c->destroyed) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http subrequest done \"%V?%V\"", uri, &sr->args); - - r->main->subrequests++; - - *psr = sr; - - if (sr->fast_subrequest) { - sr->fast_subrequest = 0; - - if (sr->done) { - return NGX_OK; - } - } - - return NGX_AGAIN; - } - - return NGX_DONE; + r->main->subrequests++; + + *psr = sr; + + return ngx_http_post_request(sr); } diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -9,8 +9,8 @@ #include -static ngx_int_t - ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r); +static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r, + ngx_chain_t *in); static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf); @@ -51,181 +51,119 @@ static ngx_http_output_body_filter_pt static ngx_int_t ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) { - ngx_int_t rc; - ngx_chain_t *out; - ngx_http_postponed_request_t *pr, **ppr; + ngx_connection_t *c; + ngx_http_postponed_request_t *pr; - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + c = r->connection; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in); - if (r != r->connection->data || (r->postponed && in)) { - - if (r->postponed) { - for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ } - - ppr = pr->request ? &pr->next : NULL; - - } else { - ppr = &r->postponed; -#if (NGX_SUPPRESS_WARN) - pr = NULL; -#endif - } + if (r != c->data) { - if (ppr) { - pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t)); - if (pr == NULL) { - return NGX_ERROR; - } - - *ppr = pr; - - pr->request = NULL; - pr->out = NULL; - pr->next = NULL; - } - - if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_ERROR) { - return NGX_ERROR; + if (in) { + ngx_http_postpone_filter_add(r, in); + return NGX_OK; } -#if 1 - { - ngx_chain_t *cl; - ngx_buf_t *b = NULL; - for (cl = pr->out; cl; cl = cl->next) { - if (cl->buf == b) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - "the same buf was used in postponed %p %p", - b, b->pos); - ngx_debug_point(); - return NGX_ERROR; - } - b = cl->buf; - } - } +#if 0 + /* TODO: SSI may pass NULL */ + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "http postpone filter NULL inactive request", + &r->uri, &r->args); #endif - if (r != r->connection->data || r->postponed->request) { - return NGX_AGAIN; - } - } - - if (r->postponed) { - out = r->postponed->out; - if (out) { - r->postponed = r->postponed->next; - } - - } else { - out = in; - } - - rc = NGX_OK; - - if (out - || (r->connection->buffered - & (NGX_HTTP_LOWLEVEL_BUFFERED|NGX_LOWLEVEL_BUFFERED))) - { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter out \"%V?%V\"", &r->uri, &r->args); - - if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) { - - rc = ngx_http_next_filter(r->main, out); - - if (rc == NGX_ERROR) { - /* NGX_ERROR may be returned by any filter */ - r->connection->error = 1; - } - } + return NGX_OK; } if (r->postponed == NULL) { - return rc; + + if (in || c->buffered) { + return ngx_http_next_filter(r->main, in); + } + + return NGX_OK; + } + + if (in) { + ngx_http_postpone_filter_add(r, in); } - rc = ngx_http_postpone_filter_output_postponed_request(r); + do { + pr = r->postponed; + + if (pr->request) { + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http postpone filter wake \"%V?%V\"", + &pr->request->uri, &pr->request->args); + + r->postponed = pr->next; + + c->data = pr->request; + + return ngx_http_post_request(pr->request); + } - if (rc == NGX_ERROR) { - /* NGX_ERROR may be returned by any filter */ - r->connection->error = 1; - } + if (pr->out == NULL) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "http postpone filter NULL output", + &r->uri, &r->args); + + } else { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http postpone filter output \"%V?%V\"", + &r->uri, &r->args); - return rc; + if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) { + return NGX_ERROR; + } + } + + r->postponed = pr->next; + + } while (r->postponed); + + return NGX_OK; } static ngx_int_t -ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r) +ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in) { - ngx_int_t rc; - ngx_chain_t *out; - ngx_http_log_ctx_t *ctx; - ngx_http_postponed_request_t *pr; + ngx_http_postponed_request_t *pr, **ppr; - for ( ;; ) { - pr = r->postponed; + if (r->postponed) { + for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ } - if (pr == NULL) { - break; + if (pr->request == NULL) { + goto found; } - if (pr->request) { - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter handle \"%V?%V\"", - &pr->request->uri, &pr->request->args); - - ctx = r->connection->log->data; - ctx->current_request = pr->request; - - if (!pr->request->done) { - r->connection->data = pr->request; - return NGX_AGAIN; - } - - rc = ngx_http_postpone_filter_output_postponed_request(pr->request); - - if (rc == NGX_AGAIN || rc == NGX_ERROR) { - return rc; - } + ppr = &pr->next; - r->postponed = r->postponed->next; - pr = r->postponed; - } - - if (pr == NULL) { - break; - } - - out = pr->out; + } else { + ppr = &r->postponed; + } - if (out) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter out postponed \"%V?%V\"", - &r->uri, &r->args); - - if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) { - if (ngx_http_next_filter(r->main, out) == NGX_ERROR) { - return NGX_ERROR; - } - } - } - - r->postponed = r->postponed->next; + pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t)); + if (pr == NULL) { + return NGX_ERROR; } - if (r != r->main && r->out) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter out again \"%V?%V\"", - &r->uri, &r->args); + *ppr = pr; - r->connection->data = r; - return NGX_AGAIN; + pr->request = NULL; + pr->out = NULL; + pr->next = NULL; + +found: + + if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_OK) { + return NGX_OK; } - return NGX_OK; + return NGX_ERROR; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -38,6 +38,7 @@ static ngx_int_t ngx_http_find_virtual_s static void ngx_http_request_handler(ngx_event_t *ev); static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r); static void ngx_http_writer(ngx_http_request_t *r); +static void ngx_http_request_finalizer(ngx_http_request_t *r); static void ngx_http_set_keepalive(ngx_http_request_t *r); static void ngx_http_keepalive_handler(ngx_event_t *ev); @@ -1411,9 +1412,7 @@ ngx_http_process_request_header(ngx_http } } - if (r->method & (NGX_HTTP_POST|NGX_HTTP_PUT) - && r->headers_in.content_length_n == -1) - { + if (r->method & NGX_HTTP_PUT && r->headers_in.content_length_n == -1) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent %V method without \"Content-Length\" header", &r->method_name); @@ -1524,7 +1523,7 @@ ngx_http_process_request(ngx_http_reques ngx_http_handler(r); - return; + ngx_http_run_posted_requests(c); } @@ -1677,12 +1676,73 @@ ngx_http_request_handler(ngx_event_t *ev ctx = c->log->data; ctx->current_request = r; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http run request: \"%V?%V\"", &r->uri, &r->args); + if (ev->write) { r->write_event_handler(r); } else { r->read_event_handler(r); } + + ngx_http_run_posted_requests(c); +} + + +void +ngx_http_run_posted_requests(ngx_connection_t *c) +{ + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; + ngx_http_posted_request_t *pr; + + for ( ;; ) { + + if (c->destroyed) { + return; + } + + r = c->data; + pr = r->main->posted_requests; + + if (pr == NULL) { + return; + } + + r->main->posted_requests = pr->next; + + r = pr->request; + + ctx = c->log->data; + ctx->current_request = r; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http posted request: \"%V?%V\"", &r->uri, &r->args); + + r->write_event_handler(r); + } +} + + +ngx_int_t +ngx_http_post_request(ngx_http_request_t *r) +{ + ngx_http_posted_request_t *pr, **p; + + pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t)); + if (pr == NULL) { + return NGX_ERROR; + } + + pr->request = r; + pr->next = NULL; + + for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ } + + *p = pr; + + return NGX_OK; } @@ -1691,7 +1751,6 @@ ngx_http_finalize_request(ngx_http_reque { ngx_connection_t *c; ngx_http_request_t *pr; - ngx_http_log_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; if (rc == NGX_DONE) { @@ -1701,9 +1760,9 @@ ngx_http_finalize_request(ngx_http_reque c = r->connection; - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http finalize request: %d, \"%V?%V\"", - rc, &r->uri, &r->args); + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http finalize request: %d, \"%V?%V\" %d", + rc, &r->uri, &r->args, r == c->data); if (rc == NGX_DECLINED) { r->content_handler = NULL; @@ -1759,88 +1818,93 @@ ngx_http_finalize_request(ngx_http_reque return; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (r != r->main && !r->logged) { - - if (clcf->log_subrequest) { - ngx_http_log_request(r); - } - - r->logged = 1; - } - - if (r != r->main || rc == NGX_AGAIN) { - if (ngx_http_set_write_handler(r) != NGX_OK) { + if (r != r->main) { + + if (r->buffered || r->postponed) { + + if (ngx_http_set_write_handler(r) != NGX_OK) { + ngx_http_close_request(r->main, 0); + } + return; } - } - - r->done = 1; - - if (r != c->data) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http finalize non-active request: \"%V?%V\"", - &r->uri, &r->args); - return; - } - - if (r != r->main) { + +#if (NGX_DEBUG) + if (r != c->data) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http finalize non-active request: \"%V?%V\"", + &r->uri, &r->args); + } +#endif pr = r->parent; + if (r == c->data) { + + if (!r->logged) { + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->log_subrequest) { + ngx_http_log_request(r); + } + + r->logged = 1; + + } else { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "subrequest: \"%V?%V\" logged again", + &r->uri, &r->args); + } + + r->done = 1; + + if (pr->postponed && pr->postponed->request == r) { + pr->postponed = pr->postponed->next; + } + + c->data = pr; + + } else { + + r->write_event_handler = ngx_http_request_finalizer; + + if (r->waited) { + r->done = 1; + } + } + + if (ngx_http_post_request(pr) != NGX_OK) { + ngx_http_close_request(r->main, 0); + return; + } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http parent request: \"%V?%V\"", &pr->uri, &pr->args); - - if (rc != NGX_AGAIN) { - c->data = pr; - } - - ctx = c->log->data; - ctx->current_request = pr; - - if (pr->postponed) { - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http request: \"%V?%V\" has postponed", - &pr->uri, &pr->args); - - if (rc != NGX_AGAIN && pr->postponed->request == r) { - pr->postponed = pr->postponed->next; - } - - if (r->fast_subrequest) { - - if (rc == NGX_AGAIN) { - r->fast_subrequest = 0; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http fast subrequest: \"%V?%V\" done", - &r->uri, &r->args); - return; - } - - if (rc != NGX_AGAIN) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http wake parent request: \"%V?%V\"", - &pr->uri, &pr->args); - - pr->write_event_handler(pr); - } + "http wake parent request: \"%V?%V\"", + &pr->uri, &pr->args); + + ngx_http_run_posted_requests(c); + + return; + } + + if (r->buffered || c->buffered || r->postponed) { + + if (ngx_http_set_write_handler(r) != NGX_OK) { + ngx_http_close_request(r, 0); } return; } - if (rc == NGX_AGAIN) { + if (r != c->data) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "http finalize non-active request: \"%V?%V\"", + &r->uri, &r->args); return; } - if (c->buffered) { - (void) ngx_http_set_write_handler(r); - return; - } + r->done = 1; if (!r->post_action) { r->request_complete = 1; @@ -1868,6 +1932,8 @@ ngx_http_finalize_request(ngx_http_reque return; } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (!ngx_terminate && !ngx_exiting && r->keepalive @@ -1930,6 +1996,8 @@ ngx_http_writer(ngx_http_request_t *r) ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer handler: \"%V?%V\"", &r->uri, &r->args); + clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); + if (wev->timedout) { if (!wev->delayed) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, @@ -1944,7 +2012,6 @@ ngx_http_writer(ngx_http_request_t *r) wev->delayed = 0; if (!wev->ready) { - clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); ngx_add_timer(wev, clcf->send_timeout); if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { @@ -1959,8 +2026,6 @@ ngx_http_writer(ngx_http_request_t *r) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer delayed"); - clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); - if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { ngx_http_close_request(r, 0); } @@ -1979,8 +2044,8 @@ ngx_http_writer(ngx_http_request_t *r) "http writer output filter: %d, \"%V?%V\"", rc, &r->uri, &r->args); - if (rc == NGX_AGAIN) { - clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); + if (r->buffered || r->postponed || (r == r->main && c->buffered)) { + if (!wev->ready && !wev->delayed) { ngx_add_timer(wev, clcf->send_timeout); } @@ -1989,11 +2054,7 @@ ngx_http_writer(ngx_http_request_t *r) ngx_http_close_request(r, 0); } - if (r == r->main || r->buffered) { - return; - } - - rc = NGX_OK; + return; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0, @@ -2003,6 +2064,16 @@ ngx_http_writer(ngx_http_request_t *r) } +static void +ngx_http_request_finalizer(ngx_http_request_t *r) +{ + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http finalizer done: \"%V?%V\"", &r->uri, &r->args); + + ngx_http_finalize_request(r, 0); +} + + void ngx_http_block_reading(ngx_http_request_t *r) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -58,6 +58,7 @@ #define NGX_HTTP_ZERO_IN_URI 1 #define NGX_HTTP_SUBREQUEST_IN_MEMORY 2 +#define NGX_HTTP_SUBREQUEST_WAITED 4 #define NGX_HTTP_OK 200 @@ -321,6 +322,14 @@ struct ngx_http_postponed_request_s { }; +typedef struct ngx_http_posted_request_s ngx_http_posted_request_t; + +struct ngx_http_posted_request_s { + ngx_http_request_t *request; + ngx_http_posted_request_t *next; +}; + + typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r); typedef void (*ngx_http_event_handler_pt)(ngx_http_request_t *r); @@ -373,6 +382,7 @@ struct ngx_http_request_s { ngx_http_request_t *parent; ngx_http_postponed_request_t *postponed; ngx_http_post_subrequest_t *post_subrequest; + ngx_http_posted_request_t *posted_requests; uint32_t in_addr; ngx_uint_t port; @@ -428,8 +438,8 @@ struct ngx_http_request_s { unsigned request_body_file_group_access:1; unsigned request_body_file_log_level:3; - unsigned fast_subrequest:1; unsigned subrequest_in_memory:1; + unsigned waited:1; unsigned gzip:2; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -274,13 +274,16 @@ ngx_module_t ngx_http_upstream_module = static ngx_http_variable_t ngx_http_upstream_vars[] = { { ngx_string("upstream_addr"), NULL, - ngx_http_upstream_addr_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + ngx_http_upstream_addr_variable, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("upstream_status"), NULL, - ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + ngx_http_upstream_status_variable, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("upstream_response_time"), NULL, - ngx_http_upstream_response_time_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + ngx_http_upstream_response_time_variable, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -511,6 +514,37 @@ ngx_http_upstream_resolve_handler(ngx_re static void +ngx_http_upstream_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; + ngx_http_upstream_t *u; + + c = ev->data; + r = c->data; + + u = r->upstream; + c = r->connection; + + ctx = c->log->data; + ctx->current_request = r; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream request: \"%V?%V\"", &r->uri, &r->args); + + if (ev->write) { + u->write_event_handler(ev); + + } else { + u->read_event_handler(ev); + } + + ngx_http_run_posted_requests(c); +} + + +static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r) { ngx_http_upstream_check_broken_connection(r, r->connection->read); @@ -712,8 +746,11 @@ ngx_http_upstream_connect(ngx_http_reque c->data = r; - c->write->handler = ngx_http_upstream_send_request_handler; - c->read->handler = ngx_http_upstream_process_header; + c->write->handler = ngx_http_upstream_handler; + c->read->handler = ngx_http_upstream_handler; + + u->write_event_handler = ngx_http_upstream_send_request_handler; + u->read_event_handler = ngx_http_upstream_process_header; c->sendfile &= r->connection->sendfile; u->output.sendfile = c->sendfile; @@ -838,8 +875,8 @@ ngx_http_upstream_ssl_handshake(ngx_conn u->peer.save_session(&u->peer, u->peer.data); } - c->write->handler = ngx_http_upstream_send_request_handler; - c->read->handler = ngx_http_upstream_process_header; + c->write->handler = ngx_http_upstream_handler; + c->read->handler = ngx_http_upstream_handler; ngx_http_upstream_send_request(r, u); @@ -998,7 +1035,7 @@ ngx_http_upstream_send_request(ngx_http_ } #endif - c->write->handler = ngx_http_upstream_dummy_handler; + u->write_event_handler = ngx_http_upstream_dummy_handler; if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, @@ -1037,7 +1074,7 @@ ngx_http_upstream_send_request_handler(n #endif if (u->header_sent) { - wev->handler = ngx_http_upstream_dummy_handler; + u->write_event_handler = ngx_http_upstream_dummy_handler; (void) ngx_handle_write_event(wev, 0); @@ -1350,7 +1387,7 @@ ngx_http_upstream_process_header(ngx_eve } } - rev->handler = ngx_http_upstream_process_body_in_memory; + u->read_event_handler = ngx_http_upstream_process_body_in_memory; ngx_http_upstream_process_body_in_memory(rev); } @@ -1614,8 +1651,7 @@ ngx_http_upstream_send_response(ngx_http u->input_filter_ctx = r; } - u->peer.connection->read->handler = - ngx_http_upstream_process_non_buffered_body; + u->read_event_handler = ngx_http_upstream_process_non_buffered_body; r->write_event_handler = ngx_http_upstream_process_non_buffered_downstream; @@ -1796,7 +1832,7 @@ ngx_http_upstream_send_response(ngx_http p->send_timeout = clcf->send_timeout; p->send_lowat = clcf->send_lowat; - u->peer.connection->read->handler = ngx_http_upstream_process_body; + u->read_event_handler = ngx_http_upstream_process_body; r->write_event_handler = ngx_http_upstream_process_downstream; ngx_http_upstream_process_body(u->peer.connection->read); @@ -1926,7 +1962,7 @@ ngx_http_upstream_process_non_buffered_b if (downstream->data == r) { if (ngx_handle_write_event(downstream->write, clcf->send_lowat) - == NGX_ERROR) + != NGX_OK) { ngx_http_upstream_finalize_request(r, u, 0); return; @@ -1940,7 +1976,7 @@ ngx_http_upstream_process_non_buffered_b ngx_del_timer(downstream->write); } - if (ngx_handle_read_event(upstream->read, 0) == NGX_ERROR) { + if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, 0); return; } @@ -2016,7 +2052,6 @@ ngx_http_upstream_process_body(ngx_event ngx_temp_file_t *tf; ngx_event_pipe_t *p; ngx_connection_t *c, *downstream; - ngx_http_log_ctx_t *ctx; ngx_http_request_t *r; ngx_http_upstream_t *u; @@ -2034,9 +2069,6 @@ ngx_http_upstream_process_body(ngx_event ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream process upstream"); c->log->action = "reading upstream"; - - ctx = c->log->data; - ctx->current_request = r; } p = u->pipe; @@ -2051,8 +2083,7 @@ ngx_http_upstream_process_body(ngx_event if (!ev->ready) { ngx_add_timer(ev, p->send_timeout); - if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) - { + if (ngx_handle_write_event(ev, p->send_lowat) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, 0); return; } @@ -2086,7 +2117,8 @@ ngx_http_upstream_process_body(ngx_event ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http downstream delayed"); - if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) { + if (ngx_handle_write_event(ev, p->send_lowat) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, 0); return; } @@ -2464,17 +2496,8 @@ ngx_http_upstream_finalize_request(ngx_h r->connection->log->action = "sending to client"; - if (rc == 0) { - if (r == r->main) { - if (!r->post_action) { - rc = ngx_http_send_special(r, NGX_HTTP_LAST); - } - - } else { - if (r->out) { - rc = NGX_AGAIN; - } - } + if (rc == 0 && r == r->main && !r->post_action) { + rc = ngx_http_send_special(r, NGX_HTTP_LAST); } ngx_http_finalize_request(r, rc); diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -217,6 +217,9 @@ typedef struct { struct ngx_http_upstream_s { + ngx_event_handler_pt read_event_handler; + ngx_event_handler_pt write_event_handler; + ngx_peer_connection_t peer; ngx_event_pipe_t *pipe;