summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES12
-rw-r--r--CHANGES.ru13
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_radix_tree.c10
-rw-r--r--src/http/modules/ngx_http_addition_filter_module.c16
-rw-r--r--src/http/modules/ngx_http_autoindex_module.c5
-rw-r--r--src/http/modules/ngx_http_geo_module.c3
-rw-r--r--src/http/modules/ngx_http_limit_req_module.c115
-rw-r--r--src/http/modules/ngx_http_limit_zone_module.c13
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c88
-rw-r--r--src/http/modules/ngx_http_static_module.c2
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http.h3
-rw-r--r--src/http/ngx_http_copy_filter_module.c4
-rw-r--r--src/http/ngx_http_core_module.c31
-rw-r--r--src/http/ngx_http_postpone_filter_module.c208
-rw-r--r--src/http/ngx_http_request.c207
-rw-r--r--src/http/ngx_http_request.h12
-rw-r--r--src/http/ngx_http_upstream.c89
-rw-r--r--src/http/ngx_http_upstream.h3
20 files changed, 448 insertions, 390 deletions
diff --git a/CHANGES b/CHANGES
index ed7cae635..471f8d4f3 100644
--- 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
index a7eaff7f7..04068b1a3 100644
--- 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
index b65e539f7..0c4dece2f 100644
--- 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
index 050dac061..f339e6fab 100644
--- 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, ngx_int_t preallocate)
}
/*
- * 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
index 55b1ca8e0..eb6a4b168 100644
--- 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_request_t *r, ngx_chain_t *in)
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_request_t *r, ngx_chain_t *in)
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
index 86b7c0b30..c8137ad68 100644
--- 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_request_t *r)
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
index bba399f6c..4c2b679e2 100644
--- 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_http_geo_conf_ctx_t *ctx,
{
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
index 10f0dd68c..dac62ed15 100644
--- 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_request_t *r)
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_request_t *r)
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_request_t *r)
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_request_t *r)
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_request_t *r)
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(ngx_rbtree_node_t *temp,
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(ngx_rbtree_node_t *temp,
} 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(ngx_rbtree_node_t *temp,
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_req_conf_t *lzcf, ngx_uint_t hash,
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_req_conf_t *lzcf, ngx_uint_t hash,
/* 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_req_conf_t *lzcf, ngx_uint_t hash,
break;
}
- *lzp = NULL;
+ *lrp = NULL;
return NGX_DECLINED;
}
@@ -397,7 +402,7 @@ ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)
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_req_ctx_t *ctx, ngx_uint_t n)
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_req_ctx_t *ctx, ngx_uint_t n)
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_t *cf)
* 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, ngx_command_t *cmd, void *conf)
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_command_t *cmd, void *conf)
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_command_t *cmd, void *conf)
}
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_command_t *cmd, void *conf)
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
index c7a3753d9..3fc4efada 100644
--- 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_request_t *r)
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_request_t *r)
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_command_t *cmd, void *conf)
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
index 04ab04200..61c95929d 100644
--- 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_request_t *r, ngx_chain_t *in)
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_request_t *r, ngx_chain_t *in)
}
}
+ 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);
- 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);
+ 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);
- rc = ngx_http_next_body_filter(r, NULL);
+ return NGX_AGAIN;
+ }
- if (ctx->wait->done) {
- ctx->wait = NULL;
- }
+ 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);
- if (rc == NGX_ERROR || rc == NGX_AGAIN) {
- return rc;
- }
+ ctx->wait = NULL;
- break;
- }
- }
+ } else {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http ssi filter wait \"%V?%V\"",
+ &ctx->wait->uri, &ctx->wait->args);
- if (ctx->wait == r) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter \"%V\" continue", &r->uri);
- ctx->wait = NULL;
+ 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_request_t *r, ngx_chain_t *in)
}
}
- if (cmd->flush) {
+ if (cmd->flush && ctx->out) {
- if (ctx->out) {
- rc = ngx_http_ssi_output(r, ctx);
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ssi flush");
- } else {
- rc = ngx_http_next_body_filter(r, NULL);
- }
-
- if (rc == NGX_ERROR) {
+ if (ngx_http_ssi_output(r, ctx) == NGX_ERROR) {
return NGX_ERROR;
}
}
@@ -2001,6 +1989,10 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
}
+ 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 *r, ngx_http_ssi_ctx_t *ctx,
psr->data = &var->value;
}
- flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;
- }
-
- rc = ngx_http_subrequest(r, uri, &args, &sr, psr, flags);
-
- if (rc == NGX_DONE) {
- return NGX_DONE;
+ flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY|NGX_HTTP_SUBREQUEST_WAITED;
}
- 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 *r, ngx_http_ssi_ctx_t *ctx,
return NGX_OK;
}
- if (rc == NGX_AGAIN) {
- if (ctx->wait == NULL) {
- ctx->wait = sr;
+ 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");
- }
+ 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
index 9ff1f817f..e90d83c57 100644
--- 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_t *r)
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
index 77f527c72..2f65af218 100644
--- 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
index 77d80a895..8c07a909c 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -80,11 +80,14 @@ ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers,
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
index 3b1a3a730..c7f6be29d 100644
--- 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, ngx_chain_t *in)
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
index b4bd40a93..01dd513e3 100644
--- 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 *r,
{
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 *r,
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 *r,
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,
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;
- }
- }
+ r->main->subrequests++;
- return NGX_AGAIN;
- }
+ *psr = sr;
- return NGX_DONE;
+ 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
index 1088704c9..3b1d780f2 100644
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -9,8 +9,8 @@
#include <ngx_http.h>
-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 ngx_http_next_filter;
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_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
+ ngx_connection_t *c;
+ ngx_http_postponed_request_t *pr;
- if (r != r->connection->data || (r->postponed && in)) {
+ c = r->connection;
- if (r->postponed) {
- for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
- ppr = pr->request ? &pr->next : NULL;
+ if (r != c->data) {
- } else {
- ppr = &r->postponed;
-#if (NGX_SUPPRESS_WARN)
- pr = NULL;
-#endif
+ if (in) {
+ ngx_http_postpone_filter_add(r, in);
+ return NGX_OK;
}
- if (ppr) {
- pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
- if (pr == NULL) {
- return NGX_ERROR;
- }
+#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
- *ppr = pr;
+ return NGX_OK;
+ }
- pr->request = NULL;
- pr->out = NULL;
- pr->next = NULL;
- }
+ if (r->postponed == NULL) {
- if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_ERROR) {
- return NGX_ERROR;
+ if (in || c->buffered) {
+ return ngx_http_next_filter(r->main, in);
}
-#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;
- }
- }
-#endif
+ return NGX_OK;
+ }
- if (r != r->connection->data || r->postponed->request) {
- return NGX_AGAIN;
- }
+ if (in) {
+ ngx_http_postpone_filter_add(r, in);
}
- if (r->postponed) {
- out = r->postponed->out;
- if (out) {
- r->postponed = r->postponed->next;
- }
+ do {
+ pr = r->postponed;
- } else {
- out = in;
- }
+ 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);
- rc = NGX_OK;
+ r->postponed = pr->next;
- 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);
+ c->data = pr->request;
- if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) {
+ return ngx_http_post_request(pr->request);
+ }
+
+ if (pr->out == NULL) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "http postpone filter NULL output",
+ &r->uri, &r->args);
- rc = ngx_http_next_filter(r->main, out);
+ } else {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http postpone filter output \"%V?%V\"",
+ &r->uri, &r->args);
- if (rc == NGX_ERROR) {
- /* NGX_ERROR may be returned by any filter */
- r->connection->error = 1;
+ if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) {
+ return NGX_ERROR;
}
}
- }
-
- if (r->postponed == NULL) {
- return rc;
- }
- rc = ngx_http_postpone_filter_output_postponed_request(r);
+ r->postponed = pr->next;
- if (rc == NGX_ERROR) {
- /* NGX_ERROR may be returned by any filter */
- r->connection->error = 1;
- }
+ } while (r->postponed);
- return rc;
+ 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;
-
- for ( ;; ) {
- pr = r->postponed;
-
- if (pr == NULL) {
- break;
- }
-
- 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);
+ ngx_http_postponed_request_t *pr, **ppr;
- if (rc == NGX_AGAIN || rc == NGX_ERROR) {
- return rc;
- }
+ if (r->postponed) {
+ for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
- r->postponed = r->postponed->next;
- pr = r->postponed;
+ if (pr->request == NULL) {
+ goto found;
}
- if (pr == NULL) {
- break;
- }
+ ppr = &pr->next;
- 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);
+ pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
+ if (pr == NULL) {
+ return NGX_ERROR;
+ }
- if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) {
- if (ngx_http_next_filter(r->main, out) == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
- }
+ *ppr = pr;
- r->postponed = r->postponed->next;
- }
+ pr->request = NULL;
+ pr->out = NULL;
+ pr->next = NULL;
- 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);
+found:
- r->connection->data = r;
- return NGX_AGAIN;
+ 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
index ab4c0e08f..2faa79195 100644
--- 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_server(ngx_http_request_t *r,
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_request_t *r)
}
}
- 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_request_t *r)
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_request_t *r, ngx_int_t rc)
{
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_request_t *r, ngx_int_t rc)
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,89 +1818,94 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
return;
}
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (r != r->main && !r->logged) {
+ if (r != r->main) {
- if (clcf->log_subrequest) {
- ngx_http_log_request(r);
- }
+ if (r->buffered || r->postponed) {
- r->logged = 1;
- }
+ if (ngx_http_set_write_handler(r) != NGX_OK) {
+ ngx_http_close_request(r->main, 0);
+ }
- if (r != r->main || rc == NGX_AGAIN) {
- if (ngx_http_set_write_handler(r) != NGX_OK) {
return;
}
- }
- r->done = 1;
+#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
- 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;
- }
+ pr = r->parent;
- if (r != r->main) {
+ if (r == c->data) {
- pr = r->parent;
+ if (!r->logged) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- if (rc != NGX_AGAIN) {
- c->data = pr;
- }
+ if (clcf->log_subrequest) {
+ ngx_http_log_request(r);
+ }
- ctx = c->log->data;
- ctx->current_request = pr;
+ r->logged = 1;
- if (pr->postponed) {
+ } else {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "subrequest: \"%V?%V\" logged again",
+ &r->uri, &r->args);
+ }
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http request: \"%V?%V\" has postponed",
- &pr->uri, &pr->args);
+ r->done = 1;
- if (rc != NGX_AGAIN && pr->postponed->request == r) {
+ if (pr->postponed && pr->postponed->request == r) {
pr->postponed = pr->postponed->next;
}
- if (r->fast_subrequest) {
-
- if (rc == NGX_AGAIN) {
- r->fast_subrequest = 0;
- }
+ c->data = pr;
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http fast subrequest: \"%V?%V\" done",
- &r->uri, &r->args);
- return;
- }
+ } else {
- if (rc != NGX_AGAIN) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http wake parent request: \"%V?%V\"",
- &pr->uri, &pr->args);
+ r->write_event_handler = ngx_http_request_finalizer;
- pr->write_event_handler(pr);
+ 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 wake parent request: \"%V?%V\"",
+ &pr->uri, &pr->args);
+
+ ngx_http_run_posted_requests(c);
+
return;
}
- if (rc == NGX_AGAIN) {
+ if (r->buffered || c->buffered || r->postponed) {
+
+ if (ngx_http_set_write_handler(r) != NGX_OK) {
+ ngx_http_close_request(r, 0);
+ }
+
return;
}
- if (c->buffered) {
- (void) ngx_http_set_write_handler(r);
+ 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;
}
+ r->done = 1;
+
if (!r->post_action) {
r->request_complete = 1;
}
@@ -1868,6 +1932,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
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
index f0e0eade1..1add80da6 100644
--- 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
index d5b6ae7ec..bbf5ae84d 100644
--- 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_resolver_ctx_t *ctx)
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_request_t *r, ngx_http_upstream_t *u)
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_connection_t *c)
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_request_t *r, ngx_http_upstream_t *u)
}
#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(ngx_event_t *wev)
#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_event_t *rev)
}
}
- 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_request_t *r, ngx_http_upstream_t *u)
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_request_t *r, ngx_http_upstream_t *u)
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_body(ngx_event_t *ev)
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_body(ngx_event_t *ev)
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_t *ev)
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_t *ev)
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_t *ev)
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_t *ev)
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_http_request_t *r,
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
index c87bcdc57..8d65a35b5 100644
--- 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;