summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2006-04-05 12:53:42 +0000
committerJonathan Kolb <jon@b0g.us>2006-04-05 12:53:42 +0000
commit49072507cf1eb437c0f1355d0281d9434e74b9fc (patch)
tree659a1d1959f9d31e5fe5dc5de6c18f95e7b5e4ff
parent35ff24bd91545a9fb68d11a332096e3a0f952927 (diff)
downloadnginx-49072507cf1eb437c0f1355d0281d9434e74b9fc.tar.gz
Changes with nginx 0.3.36 05 Apr 2006v0.3.36
*) Feature: the ngx_http_addition_filter_module. *) Feature: the "proxy_pass" and "fastcgi_pass" directives may be used inside the "if" block. *) Feature: the "proxy_ignore_client_abort" and "fastcgi_ignore_client_abort" directives. *) Feature: the "$request_completion" variable. *) Feature: the ngx_http_perl_module supports the $r->request_method and $r->remote_addr. *) Feature: the ngx_http_ssi_module supports the "elif" command. *) Bugfix: the "/" string in the expression of the "if" command of the ngx_http_ssi_module was treated incorrectly. *) Bugfix: in the regular expressions in the "if" command of the ngx_http_ssi_module. *) Bugfix: if the relative path was specified in the "client_body_temp_path", "proxy_temp_path", "fastcgi_temp_path", and "perl_modules" directives, then the directory was used relatively to a current path but not to a server prefix.
-rw-r--r--CHANGES29
-rw-r--r--CHANGES.ru31
-rw-r--r--auto/modules6
-rw-r--r--auto/options2
-rw-r--r--auto/os/linux4
-rw-r--r--auto/sources4
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_conf_file.c19
-rw-r--r--src/core/ngx_file.c7
-rw-r--r--src/core/ngx_palloc.c40
-rw-r--r--src/http/modules/ngx_http_addition_filter_module.c228
-rw-r--r--src/http/modules/ngx_http_chunked_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c14
-rw-r--r--src/http/modules/ngx_http_memcached_module.c2
-rw-r--r--src/http/modules/ngx_http_proxy_module.c22
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c63
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.h10
-rw-r--r--src/http/modules/perl/nginx.xs29
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c49
-rw-r--r--src/http/ngx_http_request.c5
-rw-r--r--src/http/ngx_http_request.h2
-rw-r--r--src/http/ngx_http_upstream.c17
-rw-r--r--src/http/ngx_http_upstream.h1
-rw-r--r--src/http/ngx_http_variables.c29
24 files changed, 537 insertions, 80 deletions
diff --git a/CHANGES b/CHANGES
index 4cef85b66..a023a459f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,33 @@
+Changes with nginx 0.3.36 05 Apr 2006
+
+ *) Feature: the ngx_http_addition_filter_module.
+
+ *) Feature: the "proxy_pass" and "fastcgi_pass" directives may be used
+ inside the "if" block.
+
+ *) Feature: the "proxy_ignore_client_abort" and
+ "fastcgi_ignore_client_abort" directives.
+
+ *) Feature: the "$request_completion" variable.
+
+ *) Feature: the ngx_http_perl_module supports the $r->request_method
+ and $r->remote_addr.
+
+ *) Feature: the ngx_http_ssi_module supports the "elif" command.
+
+ *) Bugfix: the "\/" string in the expression of the "if" command of the
+ ngx_http_ssi_module was treated incorrectly.
+
+ *) Bugfix: in the regular expressions in the "if" command of the
+ ngx_http_ssi_module.
+
+ *) Bugfix: if the relative path was specified in the
+ "client_body_temp_path", "proxy_temp_path", "fastcgi_temp_path", and
+ "perl_modules" directives, then the directory was used relatively to
+ a current path but not to a server prefix.
+
+
Changes with nginx 0.3.35 22 Mar 2006
*) Bugfix: the accept-filter and the TCP_DEFER_ACCEPT option were set
diff --git a/CHANGES.ru b/CHANGES.ru
index 9939a29fc..a89bfc8a6 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,33 @@
+Изменения в nginx 0.3.36 05.04.2006
+
+ *) Добавление: модуль ngx_http_addition_filter_module.
+
+ *) Добавление: директивы proxy_pass и fastcgi_pass можно использовать
+ внутри блока if.
+
+ *) Добавление: директивы proxy_ignore_client_abort и
+ fastcgi_ignore_client_abort.
+
+ *) Добавление: переменная $request_completion.
+
+ *) Добавление: модуль ngx_http_perl_module поддерживает методы
+ $r->request_method и $r->remote_addr.
+
+ *) Добавление: модуль ngx_http_ssi_module поддерживает команду elif.
+
+ *) Исправление: строка "\/" в начале выражения команды if модуля
+ ngx_http_ssi_module воспринималась неверно.
+
+ *) Исправление: в использовании регулярных выражениях в команде if
+ модуля ngx_http_ssi_module.
+
+ *) Исправление: при задании относительного пути в директивах
+ client_body_temp_path, proxy_temp_path, fastcgi_temp_path и
+ perl_modules использовался каталог относительно текущего каталога, а
+ не относительно префикса сервера.
+
+
Изменения в nginx 0.3.35 22.03.2006
*) Исправление: accept-фильтр и TCP_DEFER_ACCEPT устанавливались только
@@ -19,7 +48,7 @@
fastcgi_next_upstream.
*) Исправление: ngx_http_perl_module не работал со встроенным в
- конфигурацинный файл кодом, если он не начинался сразу же с "sub".
+ конфигурационный файл кодом, если он не начинался сразу же с "sub".
*) Исправление: в директиве post_action.
diff --git a/auto/modules b/auto/modules
index ef3a35d94..56dad56de 100644
--- a/auto/modules
+++ b/auto/modules
@@ -78,6 +78,7 @@ fi
# ngx_http_postpone_filter
# ngx_http_charset_filter
# ngx_http_ssi_filter
+# ngx_http_addition_filter
# ngx_http_userid_filter
# ngx_http_headers_filter
# ngx_http_copy_filter
@@ -114,6 +115,11 @@ if [ $HTTP_SSI = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS"
fi
+if [ $HTTP_ADDITION = YES ]; then
+ HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_ADDITION_FILTER_MODULE"
+ HTTP_SRCS="$HTTP_SRCS $HTTP_ADDITION_SRCS"
+fi
+
if [ $HTTP_USERID = YES ]; then
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_USERID_FILTER_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS"
diff --git a/auto/options b/auto/options
index 4ff11000c..f80b5fc14 100644
--- a/auto/options
+++ b/auto/options
@@ -52,6 +52,7 @@ HTTP_SSL=NO
HTTP_SSI=YES
HTTP_POSTPONE=NO
HTTP_REALIP=NO
+HTTP_ADDITION=NO
HTTP_ACCESS=YES
HTTP_AUTH_BASIC=YES
HTTP_USERID=YES
@@ -139,6 +140,7 @@ do
--with-http_ssl_module) HTTP_SSL=YES ;;
--with-http_realip_module) HTTP_REALIP=YES ;;
+ --with-http_addition_module) HTTP_ADDITION=YES ;;
--without-http_charset_module) HTTP_CHARSET=NO ;;
--without-http_gzip_module) HTTP_GZIP=NO ;;
--without-http_ssi_module) HTTP_SSI=NO ;;
diff --git a/auto/os/linux b/auto/os/linux
index a7a8d713d..413648633 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -59,7 +59,7 @@ fi
# sendfile()
-CC_AUX_FLAGS="-D_GNU_SOURCE"
+CC_AUX_FLAGS="$CC_AUX_FLAGS -D_GNU_SOURCE"
ngx_feature="sendfile()"
ngx_feature_name="NGX_HAVE_SENDFILE"
ngx_feature_run=yes
@@ -79,7 +79,7 @@ fi
# sendfile64()
-CC_AUX_FLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
+CC_AUX_FLAGS="$CC_AUX_FLAGS -D_FILE_OFFSET_BITS=64"
ngx_feature="sendfile64()"
ngx_feature_name="NGX_HAVE_SENDFILE64"
ngx_feature_run=yes
diff --git a/auto/sources b/auto/sources
index 20866f699..4731f4878 100644
--- a/auto/sources
+++ b/auto/sources
@@ -319,6 +319,10 @@ HTTP_REALIP_MODULE=ngx_http_realip_module
HTTP_REALIP_SRCS=src/http/modules/ngx_http_realip_module.c
+HTTP_ADDITION_FILTER_MODULE=ngx_http_addition_filter_module
+HTTP_ADDITION_SRCS=src/http/modules/ngx_http_addition_filter_module.c
+
+
HTTP_ACCESS_MODULE=ngx_http_access_module
HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_module.c
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 46d0a3dd4..3f910cb26 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.35"
+#define NGINX_VER "nginx/0.3.36"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index ab097c049..7c22948a3 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -63,6 +63,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
char *rv;
ngx_fd_t fd;
ngx_int_t rc;
+ ngx_buf_t *b;
ngx_uint_t block;
ngx_conf_file_t *prev;
@@ -95,11 +96,23 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
ngx_fd_info_n " \"%s\" failed", filename->data);
}
- cf->conf_file->buffer = ngx_create_temp_buf(cf->pool, ngx_pagesize);
- if (cf->conf_file->buffer == NULL) {
+ b = ngx_calloc_buf(cf->pool);
+ if (b == NULL) {
return NGX_CONF_ERROR;
}
+ cf->conf_file->buffer = b;
+
+ b->start = ngx_alloc(ngx_pagesize, cf->log);
+ if (b->start == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ b->pos = b->start;
+ b->last = b->start;
+ b->end = b->last + ngx_pagesize;
+ b->temporary = 1;
+
cf->conf_file->file.fd = fd;
cf->conf_file->file.name.len = filename->len;
cf->conf_file->file.name.data = filename->data;
@@ -183,7 +196,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
if (filename) {
- ngx_pfree(cf->pool, cf->conf_file->buffer->start);
+ ngx_free(cf->conf_file->buffer->start);
cf->conf_file = prev;
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 0c6576087..e3e719022 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -211,8 +211,8 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
char *p = conf;
ssize_t level;
- ngx_uint_t i, n;
ngx_str_t *value;
+ ngx_uint_t i, n;
ngx_path_t *path, **slot;
slot = (ngx_path_t **) (p + cmd->offset);
@@ -229,6 +229,11 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
path->name = value[1];
+
+ if (ngx_conf_full_name(cf->cycle, &path->name) == NGX_ERROR) {
+ return NULL;
+ }
+
path->len = 0;
path->cleaner = (ngx_gc_handler_pt) cmd->post;
path->conf_file = cf->conf_file->file.name.data;
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index eb0e86d0a..1797e96d0 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -86,7 +86,7 @@ ngx_palloc(ngx_pool_t *pool, size_t size)
{
u_char *m;
ngx_pool_t *p, *n;
- ngx_pool_large_t *large, *last;
+ ngx_pool_large_t *large;
if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL
&& size <= (size_t) (pool->end - (u_char *) pool)
@@ -134,34 +134,6 @@ ngx_palloc(ngx_pool_t *pool, size_t size)
return m;
}
- /* allocate a large block */
-
- large = NULL;
- last = NULL;
-
- if (pool->large) {
- for (last = pool->large; /* void */ ; last = last->next) {
- if (last->alloc == NULL) {
- large = last;
- last = NULL;
- break;
- }
-
- if (last->next == NULL) {
- break;
- }
- }
- }
-
- if (large == NULL) {
- large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
- if (large == NULL) {
- return NULL;
- }
-
- large->next = NULL;
- }
-
#if 0
p = ngx_memalign(ngx_pagesize, size, pool->log);
if (p == NULL) {
@@ -174,14 +146,14 @@ ngx_palloc(ngx_pool_t *pool, size_t size)
}
#endif
- if (pool->large == NULL) {
- pool->large = large;
-
- } else if (last) {
- last->next = large;
+ large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
+ if (large == NULL) {
+ return NULL;
}
large->alloc = p;
+ large->next = pool->large;
+ pool->large = large;
return p;
}
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
new file mode 100644
index 000000000..efd622e5a
--- /dev/null
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -0,0 +1,228 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+ ngx_str_t before_body;
+ ngx_str_t after_body;
+} ngx_http_addition_conf_t;
+
+
+typedef struct {
+ unsigned before_body_sent:1;
+ unsigned after_body_sent:1;
+} ngx_http_addition_ctx_t;
+
+
+static ngx_int_t ngx_http_addition_filter_init(ngx_cycle_t *cycle);
+static void *ngx_http_addition_create_conf(ngx_conf_t *cf);
+static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent,
+ void *child);
+
+
+static ngx_command_t ngx_http_addition_commands[] = {
+
+ { ngx_string("add_before_body"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_addition_conf_t, before_body),
+ NULL },
+
+ { ngx_string("add_after_body"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_addition_conf_t, after_body),
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_http_module_t ngx_http_addition_filter_module_ctx = {
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_http_addition_create_conf, /* create location configuration */
+ ngx_http_addition_merge_conf /* merge location configuration */
+};
+
+
+ngx_module_t ngx_http_addition_filter_module = {
+ NGX_MODULE_V1,
+ &ngx_http_addition_filter_module_ctx, /* module context */
+ ngx_http_addition_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init master */
+ ngx_http_addition_filter_init, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
+
+
+static ngx_int_t
+ngx_http_addition_header_filter(ngx_http_request_t *r)
+{
+ ngx_http_addition_ctx_t *ctx;
+ ngx_http_addition_conf_t *conf;
+
+ if (r->headers_out.status != NGX_HTTP_OK || r != r->main) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ if (ngx_strncasecmp(r->headers_out.content_type.data, "text/html",
+ sizeof("text/html") - 1)
+ != 0)
+ {
+ return ngx_http_next_header_filter(r);
+ }
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
+
+ if (conf->before_body.len == 0 && conf->after_body.len == 0) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module);
+
+ ngx_http_clear_content_length(r);
+ ngx_http_clear_accept_ranges(r);
+
+ return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ ngx_int_t rc;
+ ngx_uint_t last;
+ ngx_chain_t *cl;
+ ngx_http_addition_ctx_t *ctx;
+ ngx_http_addition_conf_t *conf;
+
+ if (in == NULL || r->header_only) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module);
+
+ if (ctx == NULL) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
+
+ if (!ctx->before_body_sent) {
+ ctx->before_body_sent = 1;
+
+ if (conf->before_body.len) {
+ if (ngx_http_subrequest(r, &conf->before_body, NULL, 0) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+ }
+
+ last = 0;
+
+ for (cl = in; cl; cl = cl->next) {
+ if (cl->buf->last_buf) {
+ cl->buf->last_buf = 0;
+ last = 1;
+ }
+ }
+
+ rc = ngx_http_next_body_filter(r, in);
+
+ if (rc == NGX_ERROR
+ || !last
+ || ctx->after_body_sent
+ || conf->after_body.len == 0)
+ {
+ return rc;
+ }
+
+ if (ngx_http_subrequest(r, &conf->after_body, NULL, 0) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ ctx->after_body_sent = 1;
+
+ return ngx_http_send_special(r, NGX_HTTP_LAST);
+}
+
+
+static ngx_int_t
+ngx_http_addition_filter_init(ngx_cycle_t *cycle)
+{
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
+ ngx_http_top_header_filter = ngx_http_addition_header_filter;
+
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_addition_body_filter;
+
+ return NGX_OK;
+}
+
+
+static void *
+ngx_http_addition_create_conf(ngx_conf_t *cf)
+{
+ ngx_http_addition_conf_t *conf;
+
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t));
+ if (conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ /*
+ * set by ngx_pcalloc():
+ *
+ * conf->before_body.len = 0;
+ * conf->before_body.date = NULL;
+ * conf->after_body.len = 0;
+ * conf->after_body.date = NULL;
+ */
+
+ return conf;
+}
+
+
+static char *
+ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_http_addition_conf_t *prev = parent;
+ ngx_http_addition_conf_t *conf = child;
+
+ ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
+ ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
+
+ return NGX_CONF_OK;
+}
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index d8d12088c..45110c59e 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -23,7 +23,7 @@ static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
NULL, /* merge server configuration */
NULL, /* create location configuration */
- NULL, /* merge location configuration */
+ NULL /* merge location configuration */
};
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 66e221f2b..ee603d17d 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -170,7 +170,7 @@ static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = {
static ngx_command_t ngx_http_fastcgi_commands[] = {
{ ngx_string("fastcgi_pass"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
ngx_http_fastcgi_pass,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -183,6 +183,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, index),
NULL },
+ { ngx_string("fastcgi_ignore_client_abort"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
+ NULL },
+
{ ngx_string("fastcgi_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -1470,6 +1477,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
*/
conf->upstream.buffering = NGX_CONF_UNSET;
+ conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
@@ -1520,6 +1528,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->upstream.buffering,
prev->upstream.buffering, 1);
+ ngx_conf_merge_value(conf->upstream.ignore_client_abort,
+ prev->upstream.ignore_client_abort, 0);
+
ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
prev->upstream.connect_timeout, 60000);
@@ -1670,6 +1681,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->peers == NULL) {
conf->peers = prev->peers;
+ conf->upstream.schema = prev->upstream.schema;
}
if (conf->params_source == NULL) {
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index 89a568d2e..73c018ed9 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -517,6 +517,8 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cyclic_temp_file = 0;
/* the hardcoded values */
+ conf->upstream.buffering = 0;
+ conf->upstream.ignore_client_abort = 0;
conf->upstream.send_lowat = 0;
conf->upstream.bufs.num = 0;
conf->upstream.busy_buffers_size = 0;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index f8dfdc4e1..e96ba042e 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -130,7 +130,7 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
static ngx_command_t ngx_http_proxy_commands[] = {
{ ngx_string("proxy_pass"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
ngx_http_proxy_pass,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -150,6 +150,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
NULL },
+ { ngx_string("proxy_ignore_client_abort"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
+ NULL },
+
{ ngx_string("proxy_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -1415,6 +1422,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
*/
conf->upstream.buffering = NGX_CONF_UNSET;
+ conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
@@ -1468,6 +1476,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->upstream.buffering,
prev->upstream.buffering, 1);
+ ngx_conf_merge_value(conf->upstream.ignore_client_abort,
+ prev->upstream.ignore_client_abort, 0);
+
ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
prev->upstream.connect_timeout, 60000);
@@ -1654,6 +1665,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->peers == NULL) {
conf->peers = prev->peers;
+
+ conf->host_header = prev->host_header;
+ conf->port_text = prev->port_text;
+ conf->upstream.schema = prev->upstream.schema;
}
@@ -2057,11 +2072,12 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_PCRE)
- if (clcf->regex) {
+ if (clcf->regex || clcf->noname) {
if (plcf->upstream.uri.len) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"proxy_pass\" may not have URI part in "
- "location given by regular expression");
+ "location given by regular expression or "
+ "inside the \"if\" statement");
return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 1b528f7fb..f116634e8 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -13,6 +13,7 @@
#define NGX_HTTP_SSI_DATE_LEN 2048
#define NGX_HTTP_SSI_ADD_PREFIX 1
+#define NGX_HTTP_SSI_ADD_ZERO 2
typedef struct {
@@ -247,8 +248,12 @@ static ngx_http_ssi_command_t ngx_http_ssi_commands[] = {
{ ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 },
{ ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
- { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, 1, 0 },
- { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params, 1, 0 },
+ { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
+ NGX_HTTP_SSI_COND_IF, 0 },
+ { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
+ NGX_HTTP_SSI_COND_IF, 0 },
+ { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
+ NGX_HTTP_SSI_COND_ELSE, 0 },
{ ngx_null_string, NULL, NULL, 0, 0 }
};
@@ -523,7 +528,17 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
continue;
}
- if (!ctx->output && !cmd->conditional) {
+ if (cmd->conditional
+ && (ctx->conditional == 0
+ || ctx->conditional > cmd->conditional))
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid context of SSI command: \"%V\"",
+ &ctx->command);
+ goto ssi_error;
+ }
+
+ if (!ctx->output && cmd->conditional == 0) {
continue;
}
@@ -926,6 +941,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
ctx->key = ngx_hash(ctx->key, ch);
ctx->params.nelts = 0;
+
state = ssi_command_state;
break;
}
@@ -1565,7 +1581,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
}
- p = ngx_palloc(r->pool, len);
+ p = ngx_palloc(r->pool, len + ((flags & NGX_HTTP_SSI_ADD_ZERO) ? 1 : 0));
if (p == NULL) {
return NGX_ERROR;
}
@@ -1809,13 +1825,26 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
u_char *p, *last;
ngx_str_t *expr, left, right;
ngx_int_t rc;
- ngx_uint_t negative, noregex;
+ ngx_uint_t negative, noregex, flags;
#if (NGX_PCRE)
ngx_str_t err;
ngx_regex_t *regex;
u_char errstr[NGX_MAX_CONF_ERRSTR];
#endif
+ if (ctx->command.len == 2) {
+ if (ctx->conditional) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "the \"if\" command inside the \"if\" command");
+ return NGX_HTTP_SSI_ERROR;
+ }
+ }
+
+ if (ctx->output_chosen) {
+ ctx->output = 0;
+ return NGX_OK;
+ }
+
expr = params[NGX_HTTP_SSI_IF_EXPR];
left.data = expr->data;
@@ -1857,11 +1886,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
if (p == last) {
if (left.len) {
ctx->output = 1;
+ ctx->output_chosen = 1;
} else {
ctx->output = 0;
}
+ ctx->conditional = NGX_HTTP_SSI_COND_IF;
+
return NGX_OK;
}
@@ -1887,11 +1919,17 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
noregex = 0;
+ flags = NGX_HTTP_SSI_ADD_ZERO;
last--;
p++;
} else {
noregex = 1;
+ flags = 0;
+
+ if (p < last - 1 && p[0] == '\\' && p[1] == '/') {
+ p++;
+ }
}
right.len = last - p;
@@ -1900,7 +1938,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"right: \"%V\"", &right);
- if (ngx_http_ssi_evaluate_string(r, ctx, &right, 0) != NGX_OK) {
+ if (ngx_http_ssi_evaluate_string(r, ctx, &right, flags) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
@@ -1948,11 +1986,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
if ((rc == 0 && !negative) || (rc != 0 && negative)) {
ctx->output = 1;
+ ctx->output_chosen = 1;
} else {
ctx->output = 0;
}
+ ctx->conditional = NGX_HTTP_SSI_COND_IF;
+
return NGX_OK;
invalid_expression:
@@ -1968,7 +2009,13 @@ static ngx_int_t
ngx_http_ssi_else(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
- ctx->output = !ctx->output;
+ if (ctx->output_chosen) {
+ ctx->output = 0;
+ } else {
+ ctx->output = 1;
+ }
+
+ ctx->conditional = NGX_HTTP_SSI_COND_ELSE;
return NGX_OK;
}
@@ -1979,6 +2026,8 @@ ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
ctx->output = 1;
+ ctx->output_chosen = 0;
+ ctx->conditional = 0;
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h
index 5337e942a..eff236050 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -20,6 +20,10 @@
#define NGX_HTTP_SSI_PARAMS_N 4
+#define NGX_HTTP_SSI_COND_IF 1
+#define NGX_HTTP_SSI_COND_ELSE 2
+
+
typedef struct {
ngx_hash_t hash;
ngx_hash_keys_arrays_t commands;
@@ -54,7 +58,9 @@ typedef struct {
ngx_array_t variables;
- ngx_uint_t output; /* unsigned output:1; */
+ unsigned conditional:2;
+ unsigned output:1;
+ unsigned output_chosen:1;
void *value_buf;
ngx_str_t timefmt;
@@ -80,7 +86,7 @@ typedef struct {
ngx_http_ssi_command_pt handler;
ngx_http_ssi_param_t *params;
- unsigned conditional:1;
+ unsigned conditional:2;
unsigned flush:1;
} ngx_http_ssi_command_t;
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index 4d57bb63e..d0453ea8d 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -178,6 +178,35 @@ args(r, ...)
char *
+request_method(r)
+ nginx r
+
+ CODE:
+
+ RETVAL = ngx_palloc(r->pool, r->method_name.len + 1);
+ if (RETVAL == NULL) {
+ XSRETURN_UNDEF;
+ }
+
+ ngx_cpystrn((u_char *) RETVAL, r->method_name.data, r->method_name.len + 1);
+
+ OUTPUT:
+ RETVAL
+
+
+char *
+remote_addr(r)
+ nginx r
+
+ CODE:
+
+ RETVAL = (char *) r->connection->addr_text.data;
+
+ OUTPUT:
+ RETVAL
+
+
+char *
header_in(r, key)
nginx r
SV *key
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 0bcad5ccb..e453dc38b 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -39,6 +39,7 @@ static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
#endif
+static void ngx_http_perl_handle_request(ngx_http_request_t *r);
static ngx_int_t
ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf,
PerlInterpreter **perl, ngx_log_t *log);
@@ -174,23 +175,39 @@ ngx_http_perl_xs_init(pTHX)
static ngx_int_t
ngx_http_perl_handler(ngx_http_request_t *r)
{
- ngx_int_t rc;
- ngx_str_t uri, args;
- ngx_http_perl_ctx_t *ctx;
- ngx_http_perl_loc_conf_t *plcf;
- ngx_http_perl_main_conf_t *pmcf;
+ ngx_int_t rc;
/* TODO: Win32 */
if (r->zero_in_uri) {
return NGX_HTTP_NOT_FOUND;
}
+ rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
+
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+ return rc;
+ }
+
+ return NGX_DONE;
+}
+
+
+static void
+ngx_http_perl_handle_request(ngx_http_request_t *r)
+{
+ ngx_int_t rc;
+ ngx_str_t uri, args;
+ ngx_http_perl_ctx_t *ctx;
+ ngx_http_perl_loc_conf_t *plcf;
+ ngx_http_perl_main_conf_t *pmcf;
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler");
/* mod_perl's content handler assumes that content type was already set */
if (ngx_http_set_content_type(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
}
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
@@ -198,7 +215,8 @@ ngx_http_perl_handler(ngx_http_request_t *r)
if (ctx == NULL) {
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
if (ctx == NULL) {
- return NGX_ERROR;
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
}
ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
@@ -209,7 +227,8 @@ ngx_http_perl_handler(ngx_http_request_t *r)
rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
if (rc != NGX_OK) {
- return rc;
+ ngx_http_finalize_request(r, rc);
+ return;
}
{
@@ -235,20 +254,24 @@ ngx_http_perl_handler(ngx_http_request_t *r)
if (ctx->redirect_uri.len) {
uri = ctx->redirect_uri;
args = ctx->redirect_args;
+
+ } else {
+ uri.len = 0;
}
ctx->filename = NULL;
ctx->redirect_uri.len = 0;
if (uri.len) {
- return ngx_http_internal_redirect(r, &uri, &args);
+ ngx_http_internal_redirect(r, &uri, &args);
+ return;
}
if (rc == NGX_OK || rc == NGX_HTTP_OK) {
- return ngx_http_send_special(r, NGX_HTTP_LAST);
+ ngx_http_send_special(r, NGX_HTTP_LAST);
}
- return rc;
+ ngx_http_finalize_request(r, rc);
}
@@ -448,6 +471,10 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
}
#endif
+ if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
PERL_SYS_INIT(&ngx_argc, &ngx_argv);
pmcf->perl = ngx_http_perl_create_interpreter(pmcf, cf->log);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 870dd8bcc..514658ca2 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1503,6 +1503,10 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
return;
}
+ if (!r->post_action) {
+ r->request_complete = 1;
+ }
+
if (ngx_http_post_action(r) == NGX_OK) {
return;
}
@@ -2254,6 +2258,7 @@ ngx_http_post_action(ngx_http_request_t *r)
r->http_version = NGX_HTTP_VERSION_9;
r->header_only = 1;
+ r->post_action = 1;
ngx_http_internal_redirect(r, &clcf->post_action, NULL);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 8450b0434..7e1a43b5d 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -405,6 +405,8 @@ struct ngx_http_request_s {
unsigned lingering_close:1;
unsigned discard_body:1;
unsigned internal:1;
+ unsigned post_action:1;
+ unsigned request_complete:1;
unsigned done:1;
unsigned utf8:1;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 9fd1a1ebd..bfaed70a5 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -277,9 +277,9 @@ ngx_http_upstream_init(ngx_http_request_t *r)
ngx_del_timer(c->read);
}
- if (!(r->http_version == NGX_HTTP_VERSION_9 && r->header_only)) {
- /* not a post_action */
+ u = r->upstream;
+ if (!r->post_action && !u->conf->ignore_client_abort) {
r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
}
@@ -296,8 +296,6 @@ ngx_http_upstream_init(ngx_http_request_t *r)
}
}
- u = r->upstream;
-
if (r->request_body) {
u->request_bufs = r->request_body->bufs;
}
@@ -1208,10 +1206,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
rc = ngx_http_send_header(r);
- if (rc == NGX_ERROR
- || rc > NGX_OK
- /* post_action */
- || (r->http_version == NGX_HTTP_VERSION_9 && r->header_only)) {
+ if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
ngx_http_upstream_finalize_request(r, u, rc);
return;
}
@@ -1947,11 +1942,7 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
r->connection->log->action = "sending to client";
- if (rc == 0
- && r == r->main
- /* not a post_action */
- && !(r->http_version == NGX_HTTP_VERSION_9 && r->header_only))
- {
+ if (rc == 0 && r == r->main && !r->post_action) {
rc = ngx_http_send_special(r, NGX_HTTP_LAST);
}
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 117def185..4d07c3e7e 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -73,6 +73,7 @@ typedef struct {
ngx_flag_t pass_request_headers;
ngx_flag_t pass_request_body;
+ ngx_flag_t ignore_client_abort;
ngx_flag_t redirect_errors;
ngx_flag_t cyclic_temp_file;
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 1370162c1..261592978 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -44,6 +44,8 @@ static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
/*
@@ -135,6 +137,9 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("body_bytes_sent"), ngx_http_variable_body_bytes_sent,
0, 0, 0 },
+ { ngx_string("request_completion"), ngx_http_variable_request_completion,
+ 0, 0, 0 },
+
{ ngx_null_string, NULL, 0, 0, 0 }
};
@@ -798,6 +803,30 @@ ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
}
+static ngx_int_t
+ngx_http_variable_request_completion(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ if (r->request_complete) {
+ v->len = 2;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) "OK";
+
+ return NGX_OK;
+ }
+
+ v->len = 0;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) "";
+
+ return NGX_OK;
+}
+
+
ngx_int_t
ngx_http_variables_add_core_vars(ngx_conf_t *cf)
{