summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2011-12-12 15:04:54 +0000
committerJonathan Kolb <jon@b0g.us>2011-12-12 15:04:54 +0000
commitf3f84820db369aade03ed922872e206760e0ce0f (patch)
tree2e2010e8de0d85c2c291b7bdc3caca6f808f72c4
parent56831c260fdbd5d130c692d0d4dc8918a462f4bb (diff)
downloadnginx-f3f84820db369aade03ed922872e206760e0ce0f.tar.gz
Changes with nginx 1.1.11 12 Dec 2011v1.1.11
*) Feature: the "so_keepalive" parameter of the "listen" directive. Thanks to Vsevolod Stakhov. *) Feature: the "if_not_empty" parameter of the "fastcgi/scgi/uwsgi_param" directives. *) Feature: the $https variable. *) Feature: the "proxy_redirect" directive supports variables in the first parameter. *) Feature: the "proxy_redirect" directive supports regular expressions. *) Bugfix: the $sent_http_cache_control variable might contain a wrong value if the "expires" directive was used. Thanks to Yichun Zhang. *) Bugfix: the "read_ahead" directive might not work combined with "try_files" and "open_file_cache". *) Bugfix: a segmentation fault might occur in a worker process if small time was used in the "inactive" parameter of the "proxy_cache_path" directive. *) Bugfix: responses from cache might hang. Maxim Dounin _______________________________________________ nginx-announce mailing list nginx-announce@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-announce
-rw-r--r--CHANGES29
-rw-r--r--CHANGES.ru30
-rwxr-xr-xauto/unix14
-rw-r--r--conf/fastcgi_params1
-rw-r--r--conf/scgi_params1
-rw-r--r--conf/uwsgi_params1
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_connection.c51
-rw-r--r--src/core/ngx_connection.h6
-rw-r--r--src/core/ngx_regex.c17
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c51
-rw-r--r--src/http/modules/ngx_http_log_module.c8
-rw-r--r--src/http/modules/ngx_http_proxy_module.c218
-rw-r--r--src/http/modules/ngx_http_scgi_module.c74
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c51
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http.c7
-rw-r--r--src/http/ngx_http_core_module.c92
-rw-r--r--src/http/ngx_http_core_module.h6
-rw-r--r--src/http/ngx_http_file_cache.c79
-rw-r--r--src/http/ngx_http_header_filter_module.c31
-rw-r--r--src/http/ngx_http_upstream.c44
-rw-r--r--src/http/ngx_http_upstream.h9
-rw-r--r--src/http/ngx_http_variables.c69
-rw-r--r--src/mail/ngx_mail.c13
-rw-r--r--src/mail/ngx_mail.h12
-rw-r--r--src/mail/ngx_mail_core_module.c98
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c9
28 files changed, 778 insertions, 249 deletions
diff --git a/CHANGES b/CHANGES
index e66b5662d..9a6450a2a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,33 @@
+Changes with nginx 1.1.11 12 Dec 2011
+
+ *) Feature: the "so_keepalive" parameter of the "listen" directive.
+ Thanks to Vsevolod Stakhov.
+
+ *) Feature: the "if_not_empty" parameter of the
+ "fastcgi/scgi/uwsgi_param" directives.
+
+ *) Feature: the $https variable.
+
+ *) Feature: the "proxy_redirect" directive supports variables in the
+ first parameter.
+
+ *) Feature: the "proxy_redirect" directive supports regular expressions.
+
+ *) Bugfix: the $sent_http_cache_control variable might contain a wrong
+ value if the "expires" directive was used.
+ Thanks to Yichun Zhang.
+
+ *) Bugfix: the "read_ahead" directive might not work combined with
+ "try_files" and "open_file_cache".
+
+ *) Bugfix: a segmentation fault might occur in a worker process if small
+ time was used in the "inactive" parameter of the "proxy_cache_path"
+ directive.
+
+ *) Bugfix: responses from cache might hang.
+
+
Changes with nginx 1.1.10 30 Nov 2011
*) Bugfix: a segmentation fault occured in a worker process if AIO was
diff --git a/CHANGES.ru b/CHANGES.ru
index 9bb327769..6b559ed99 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,34 @@
+Изменения в nginx 1.1.11 12.12.2011
+
+ *) Добавление: параметр so_keepalive в директиве listen.
+ Спасибо Всеволоду Стахову.
+
+ *) Добавление: параметр if_not_empty в директивах
+ fastcgi/scgi/uwsgi_param.
+
+ *) Добавление: переменная $https.
+
+ *) Добавление: директива proxy_redirect поддерживает переменные в первом
+ параметре.
+
+ *) Добавление: директива proxy_redirect поддерживает регулярные
+ выражения.
+
+ *) Исправление: переменная $sent_http_cache_control могла содержать
+ неверное значение при использовании директивы expires.
+ Спасибо Yichun Zhang.
+
+ *) Исправление: директива read_ahead могла не работать при использовании
+ совместно с try_files и open_file_cache.
+
+ *) Исправление: если в параметре inactive директивы proxy_cache_path
+ было указано малое время, в рабочем процессе мог произойти
+ segmentation fault.
+
+ *) Исправление: ответы из кэша могли зависать.
+
+
Изменения в nginx 1.1.10 30.11.2011
*) Исправление: при использовании AIO на Linux в рабочем процессе
diff --git a/auto/unix b/auto/unix
index 7621e8fa2..67b7a9083 100755
--- a/auto/unix
+++ b/auto/unix
@@ -328,6 +328,20 @@ ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_DEFER_ACCEPT, NULL, 0)"
. auto/feature
+ngx_feature="TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT"
+ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
+ setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
+ setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
+. auto/feature
+
+
ngx_feature="accept4()"
ngx_feature_name="NGX_HAVE_ACCEPT4"
ngx_feature_run=no
diff --git a/conf/fastcgi_params b/conf/fastcgi_params
index 201c686e2..71e2c2e3b 100644
--- a/conf/fastcgi_params
+++ b/conf/fastcgi_params
@@ -9,6 +9,7 @@ fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
+fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
diff --git a/conf/scgi_params b/conf/scgi_params
index 257167eb7..47348ca38 100644
--- a/conf/scgi_params
+++ b/conf/scgi_params
@@ -8,6 +8,7 @@ scgi_param DOCUMENT_URI $document_uri;
scgi_param DOCUMENT_ROOT $document_root;
scgi_param SCGI 1;
scgi_param SERVER_PROTOCOL $server_protocol;
+scgi_param HTTPS $https if_not_empty;
scgi_param REMOTE_ADDR $remote_addr;
scgi_param REMOTE_PORT $remote_port;
diff --git a/conf/uwsgi_params b/conf/uwsgi_params
index b57e8e78e..f539451b6 100644
--- a/conf/uwsgi_params
+++ b/conf/uwsgi_params
@@ -8,6 +8,7 @@ uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
+uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 28955661b..965a7f2bf 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1001010
-#define NGINX_VERSION "1.1.10"
+#define nginx_version 1001011
+#define NGINX_VERSION "1.1.11"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 3674b9a74..9dc551090 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -462,6 +462,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
void
ngx_configure_listening_sockets(ngx_cycle_t *cycle)
{
+ int keepalive;
ngx_uint_t i;
ngx_listening_t *ls;
@@ -499,6 +500,56 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
}
}
+ if (ls[i].keepalive) {
+ keepalive = (ls[i].keepalive == 1) ? 1 : 0;
+
+ if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
+ (const void *) &keepalive, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
+ keepalive, &ls[i].addr_text);
+ }
+ }
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+
+ if (ls[i].keepidle) {
+ if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
+ (const void *) &ls[i].keepidle, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
+ ls[i].keepidle, &ls[i].addr_text);
+ }
+ }
+
+ if (ls[i].keepintvl) {
+ if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
+ (const void *) &ls[i].keepintvl, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
+ ls[i].keepintvl, &ls[i].addr_text);
+ }
+ }
+
+ if (ls[i].keepcnt) {
+ if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
+ (const void *) &ls[i].keepcnt, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
+ ls[i].keepcnt, &ls[i].addr_text);
+ }
+ }
+
+#endif
+
#if (NGX_HAVE_SETFIB)
if (ls[i].setfib != -1) {
if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index f9bf50401..9e3ca52fb 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -27,6 +27,11 @@ struct ngx_listening_s {
int backlog;
int rcvbuf;
int sndbuf;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ int keepidle;
+ int keepintvl;
+ int keepcnt;
+#endif
/* handler of accepted connection */
ngx_connection_handler_pt handler;
@@ -60,6 +65,7 @@ struct ngx_listening_s {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
unsigned ipv6only:2;
#endif
+ unsigned keepalive:2;
#if (NGX_HAVE_DEFERRED_ACCEPT)
unsigned deferred_accept:1;
diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c
index 984a28aa9..af00f8319 100644
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -137,23 +137,6 @@ failed:
ngx_int_t
-ngx_regex_capture_count(ngx_regex_t *re)
-{
- int rc, n;
-
- n = 0;
-
- rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &n);
-
- if (rc < 0) {
- return (ngx_int_t) rc;
- }
-
- return (ngx_int_t) n;
-}
-
-
-ngx_int_t
ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
{
ngx_int_t n;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 2dc56c76b..599edc77c 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -411,8 +411,8 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
&ngx_http_fastcgi_next_upstream_masks },
{ ngx_string("fastcgi_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_keyval_slot,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
+ ngx_http_upstream_param_set_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
NULL },
@@ -708,7 +708,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
u_char ch, *pos, *lowcase_key;
size_t size, len, key_len, val_len, padding,
allocated;
- ngx_uint_t i, n, next, hash, header_params;
+ ngx_uint_t i, n, next, hash, skip_empty, header_params;
ngx_buf_t *b;
ngx_chain_t *cl, *body;
ngx_list_part_t *part;
@@ -739,11 +739,18 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
lcode = *(ngx_http_script_len_code_pt *) le.ip;
key_len = lcode(&le);
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ skip_empty = lcode(&le);
+
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
}
le.ip += sizeof(uintptr_t);
+ if (skip_empty && val_len == 0) {
+ continue;
+ }
+
len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
}
}
@@ -893,11 +900,28 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
lcode = *(ngx_http_script_len_code_pt *) le.ip;
key_len = (u_char) lcode(&le);
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ skip_empty = lcode(&le);
+
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
}
le.ip += sizeof(uintptr_t);
+ if (skip_empty && val_len == 0) {
+ e.skip = 1;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
+ }
+ e.ip += sizeof(uintptr_t);
+
+ e.skip = 0;
+
+ continue;
+ }
+
*e.pos++ = (u_char) key_len;
if (val_len > 127) {
@@ -2370,9 +2394,9 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
#if (NGX_HTTP_CACHE)
ngx_array_t params_merged;
#endif
- ngx_keyval_t *src;
ngx_hash_key_t *hk;
ngx_hash_init_t hash;
+ ngx_http_upstream_param_t *src;
ngx_http_script_compile_t sc;
ngx_http_script_copy_code_t *copy;
@@ -2433,9 +2457,11 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
#if (NGX_HTTP_CACHE)
if (conf->upstream.cache) {
- ngx_keyval_t *h, *s;
+ ngx_keyval_t *h;
+ ngx_http_upstream_param_t *s;
- if (ngx_array_init(&params_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
+ if (ngx_array_init(&params_merged, cf->temp_pool, 4,
+ sizeof(ngx_http_upstream_param_t))
!= NGX_OK)
{
return NGX_ERROR;
@@ -2469,7 +2495,9 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
return NGX_ERROR;
}
- *s = *h;
+ s->key = h->key;
+ s->value = h->value;
+ s->skip_empty = 0;
next:
@@ -2511,6 +2539,15 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
+ copy = ngx_array_push_n(conf->params_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
+ copy->len = src[i].skip_empty;
+
size = (sizeof(ngx_http_script_copy_code_t)
+ src[i].key.len + sizeof(uintptr_t) - 1)
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index da6fbb619..cb9c77f6f 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -971,7 +971,7 @@ buffer:
if (buf == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[3]);
+ "invalid buffer value \"%V\"", &name);
return NGX_CONF_ERROR;
}
@@ -1004,6 +1004,12 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_uint_t i;
ngx_http_log_fmt_t *fmt;
+ if (cf->cmd_type != NGX_HTTP_MAIN_CONF) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "the \"log_format\" directive may be used "
+ "only on \"http\" level");
+ }
+
value = cf->args->elts;
fmt = lmcf->formats.elts;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 5476f396e..5ce875f62 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -16,18 +16,15 @@ typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
struct ngx_http_proxy_redirect_s {
ngx_http_proxy_redirect_pt handler;
- ngx_str_t redirect;
union {
- ngx_str_t text;
-
- struct {
- void *lengths;
- void *values;
- } vars;
+ ngx_http_complex_value_t complex;
+#if (NGX_PCRE)
+ ngx_http_regex_t *regex;
+#endif
+ } redirect;
- void *regex;
- } replacement;
+ ngx_http_complex_value_t replacement;
};
@@ -2289,20 +2286,29 @@ ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t
-ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h,
- size_t prefix, ngx_http_proxy_redirect_t *pr)
+ngx_http_proxy_rewrite_redirect_complex(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr)
{
- size_t len;
- u_char *data, *p;
+ size_t len;
+ u_char *data, *p;
+ ngx_str_t redirect, replacement;
+
+ if (ngx_http_complex_value(r, &pr->redirect.complex, &redirect) != NGX_OK) {
+ return NGX_ERROR;
+ }
- if (pr->redirect.len > h->value.len - prefix
- || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
- pr->redirect.len) != 0)
+ if (redirect.len > h->value.len - prefix
+ || ngx_rstrncmp(h->value.data + prefix, redirect.data,
+ redirect.len) != 0)
{
return NGX_DECLINED;
}
- len = pr->replacement.text.len + h->value.len - pr->redirect.len;
+ if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ len = replacement.len + h->value.len - redirect.len;
data = ngx_pnalloc(r->pool, len);
if (data == NULL) {
@@ -2311,12 +2317,12 @@ ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h,
p = ngx_copy(data, h->value.data, prefix);
- if (pr->replacement.text.len) {
- p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len);
+ if (replacement.len) {
+ p = ngx_copy(p, replacement.data, replacement.len);
}
- ngx_memcpy(p, h->value.data + prefix + pr->redirect.len,
- h->value.len - pr->redirect.len - prefix);
+ ngx_memcpy(p, h->value.data + prefix + redirect.len,
+ h->value.len - redirect.len - prefix);
h->value.len = len;
h->value.data = data;
@@ -2325,59 +2331,32 @@ ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h,
}
+#if (NGX_PCRE)
+
static ngx_int_t
-ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h,
+ngx_http_proxy_rewrite_redirect_regex(ngx_http_request_t *r, ngx_table_elt_t *h,
size_t prefix, ngx_http_proxy_redirect_t *pr)
{
- size_t len;
- u_char *data, *p;
- ngx_http_script_code_pt code;
- ngx_http_script_engine_t e;
- ngx_http_script_len_code_pt lcode;
-
- if (pr->redirect.len > h->value.len - prefix
- || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
- pr->redirect.len) != 0)
- {
- return NGX_DECLINED;
- }
+ ngx_str_t redirect, replacement;
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
+ redirect.len = h->value.len - prefix;
+ redirect.data = h->value.data + prefix;
- e.ip = pr->replacement.vars.lengths;
- e.request = r;
-
- len = h->value.len - pr->redirect.len;
-
- while (*(uintptr_t *) e.ip) {
- lcode = *(ngx_http_script_len_code_pt *) e.ip;
- len += lcode(&e);
+ if (ngx_http_regex_exec(r, pr->redirect.regex, &redirect) != NGX_OK) {
+ return NGX_DECLINED;
}
- data = ngx_pnalloc(r->pool, len);
- if (data == NULL) {
+ if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
return NGX_ERROR;
}
- p = ngx_copy(data, h->value.data, prefix);
-
- e.ip = pr->replacement.vars.values;
- e.pos = p;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code(&e);
- }
-
- ngx_memcpy(e.pos, h->value.data + prefix + pr->redirect.len,
- h->value.len - pr->redirect.len - prefix);
-
- h->value.len = len;
- h->value.data = data;
+ h->value = replacement;
return NGX_OK;
}
+#endif
+
static ngx_int_t
ngx_http_proxy_add_variables(ngx_conf_t *cf)
@@ -2749,26 +2728,32 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
- pr->handler = ngx_http_proxy_rewrite_redirect_text;
+ ngx_memzero(&pr->redirect.complex,
+ sizeof(ngx_http_complex_value_t));
+
+ ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
+
+ pr->handler = ngx_http_proxy_rewrite_redirect_complex;
if (conf->vars.uri.len) {
- pr->redirect = conf->url;
- pr->replacement.text = conf->location;
+ pr->redirect.complex.value = conf->url;
+ pr->replacement.value = conf->location;
} else {
- pr->redirect.len = conf->url.len + sizeof("/") - 1;
+ pr->redirect.complex.value.len = conf->url.len
+ + sizeof("/") - 1;
- p = ngx_pnalloc(cf->pool, pr->redirect.len);
+ p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len);
if (p == NULL) {
return NGX_CONF_ERROR;
}
- pr->redirect.data = p;
+ pr->redirect.complex.value.data = p;
p = ngx_cpymem(p, conf->url.data, conf->url.len);
*p = '/';
- ngx_str_set(&pr->replacement.text, "/");
+ ngx_str_set(&pr->replacement.value, "/");
}
}
}
@@ -3256,11 +3241,10 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_proxy_loc_conf_t *plcf = conf;
- u_char *p;
- ngx_str_t *value;
- ngx_array_t *vars_lengths, *vars_values;
- ngx_http_script_compile_t sc;
- ngx_http_proxy_redirect_t *pr;
+ u_char *p;
+ ngx_str_t *value;
+ ngx_http_proxy_redirect_t *pr;
+ ngx_http_compile_complex_value_t ccv;
if (plcf->redirect == 0) {
return NGX_CONF_OK;
@@ -3318,59 +3302,95 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- pr->handler = ngx_http_proxy_rewrite_redirect_text;
+ pr->handler = ngx_http_proxy_rewrite_redirect_complex;
+
+ ngx_memzero(&pr->redirect.complex, sizeof(ngx_http_complex_value_t));
+
+ ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
if (plcf->vars.uri.len) {
- pr->redirect = plcf->url;
- pr->replacement.text = plcf->location;
+ pr->redirect.complex.value = plcf->url;
+ pr->replacement.value = plcf->location;
} else {
- pr->redirect.len = plcf->url.len + sizeof("/") - 1;
+ pr->redirect.complex.value.len = plcf->url.len + sizeof("/") - 1;
- p = ngx_pnalloc(cf->pool, pr->redirect.len);
+ p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len);
if (p == NULL) {
return NGX_CONF_ERROR;
}
- pr->redirect.data = p;
+ pr->redirect.complex.value.data = p;
p = ngx_cpymem(p, plcf->url.data, plcf->url.len);
*p = '/';
- ngx_str_set(&pr->replacement.text, "/");
+ ngx_str_set(&pr->replacement.value, "/");
}
return NGX_CONF_OK;
}
- if (ngx_http_script_variables_count(&value[2]) == 0) {
- pr->handler = ngx_http_proxy_rewrite_redirect_text;
- pr->redirect = value[1];
- pr->replacement.text = value[2];
- return NGX_CONF_OK;
- }
+ if (value[1].data[0] == '~') {
+#if (NGX_PCRE)
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
+ ngx_regex_compile_t rc;
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+ value[1].len--;
+ value[1].data++;
- vars_lengths = NULL;
- vars_values = NULL;
+ ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
- sc.cf = cf;
- sc.source = &value[2];
- sc.lengths = &vars_lengths;
- sc.values = &vars_values;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
+ if (value[1].data[0] == '*') {
+ value[1].len--;
+ value[1].data++;
+ rc.options = NGX_REGEX_CASELESS;
+ }
+
+ rc.pattern = value[1];
+ rc.err.len = NGX_MAX_CONF_ERRSTR;
+ rc.err.data = errstr;
+
+ pr->redirect.regex = ngx_http_regex_compile(cf, &rc);
+ if (pr->redirect.regex == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ pr->handler = ngx_http_proxy_rewrite_redirect_regex;
+
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "using regex \"%V\" requires PCRE library",
+ &value[1]);
- if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_CONF_ERROR;
+#endif
+ } else {
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[1];
+ ccv.complex_value = &pr->redirect.complex;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ pr->handler = ngx_http_proxy_rewrite_redirect_complex;
}
- pr->handler = ngx_http_proxy_rewrite_redirect_vars;
- pr->redirect = value[1];
- pr->replacement.vars.lengths = vars_lengths->elts;
- pr->replacement.vars.values = vars_values->elts;
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[2];
+ ccv.complex_value = &pr->replacement;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 168f497ce..41cf23bc6 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -278,8 +278,8 @@ static ngx_command_t ngx_http_scgi_commands[] = {
&ngx_http_scgi_next_upstream_masks },
{ ngx_string("scgi_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_keyval_slot,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
+ ngx_http_upstream_param_set_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_scgi_loc_conf_t, params_source),
NULL },
@@ -519,10 +519,10 @@ static ngx_int_t
ngx_http_scgi_create_request(ngx_http_request_t *r)
{
u_char ch, *key, *val, *lowcase_key;
- size_t len, allocated;
+ size_t len, key_len, val_len, allocated;
ngx_buf_t *b;
ngx_str_t *content_length;
- ngx_uint_t i, n, hash, header_params;
+ ngx_uint_t i, n, hash, skip_empty, header_params;
ngx_chain_t *cl, *body;
ngx_list_part_t *part;
ngx_table_elt_t *header, **ignored;
@@ -554,15 +554,21 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
while (*(uintptr_t *) le.ip) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
- len += lcode(&le);
+ key_len = lcode(&le);
+
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ skip_empty = lcode(&le);
- while (*(uintptr_t *) le.ip) {
+ for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
- len += lcode(&le);
}
- len++;
-
le.ip += sizeof(uintptr_t);
+
+ if (skip_empty && val_len == 0) {
+ continue;
+ }
+
+ len += key_len + val_len + 1;
}
}
@@ -665,7 +671,34 @@ ngx_http_scgi_create_request(ngx_http_request_t *r)
e.request = r;
e.flushed = 1;
- while (*(uintptr_t *) e.ip) {
+ le.ip = scf->params_len->elts;
+
+ while (*(uintptr_t *) le.ip) {
+
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ lcode(&le); /* key length */
+
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ skip_empty = lcode(&le);
+
+ for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ }
+ le.ip += sizeof(uintptr_t);
+
+ if (skip_empty && val_len == 0) {
+ e.skip = 1;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
+ }
+ e.ip += sizeof(uintptr_t);
+
+ e.skip = 0;
+
+ continue;
+ }
#if (NGX_DEBUG)
key = e.pos;
@@ -1323,9 +1356,9 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
#if (NGX_HTTP_CACHE)
ngx_array_t params_merged;
#endif
- ngx_keyval_t *src;
ngx_hash_key_t *hk;
ngx_hash_init_t hash;
+ ngx_http_upstream_param_t *src;
ngx_http_script_compile_t sc;
ngx_http_script_copy_code_t *copy;
@@ -1386,9 +1419,11 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
#if (NGX_HTTP_CACHE)
if (conf->upstream.cache) {
- ngx_keyval_t *h, *s;
+ ngx_keyval_t *h;
+ ngx_http_upstream_param_t *s;
- if (ngx_array_init(&params_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
+ if (ngx_array_init(&params_merged, cf->temp_pool, 4,
+ sizeof(ngx_http_upstream_param_t))
!= NGX_OK)
{
return NGX_ERROR;
@@ -1422,7 +1457,9 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
return NGX_ERROR;
}
- *s = *h;
+ s->key = h->key;
+ s->value = h->value;
+ s->skip_empty = 0;
next:
@@ -1464,6 +1501,15 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->len = src[i].key.len + 1;
+ copy = ngx_array_push_n(conf->params_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
+ copy->len = src[i].skip_empty;
+
size = (sizeof(ngx_http_script_copy_code_t)
+ src[i].key.len + 1 + sizeof(uintptr_t) - 1)
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index d60812932..2916a5916 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -305,8 +305,8 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
&ngx_http_uwsgi_next_upstream_masks },
{ ngx_string("uwsgi_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_keyval_slot,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
+ ngx_http_upstream_param_set_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_uwsgi_loc_conf_t, params_source),
NULL },
@@ -553,7 +553,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
{
u_char ch, *lowcase_key;
size_t key_len, val_len, len, allocated;
- ngx_uint_t i, n, hash, header_params;
+ ngx_uint_t i, n, hash, skip_empty, header_params;
ngx_buf_t *b;
ngx_chain_t *cl, *body;
ngx_list_part_t *part;
@@ -583,11 +583,18 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
lcode = *(ngx_http_script_len_code_pt *) le.ip;
key_len = lcode(&le);
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ skip_empty = lcode(&le);
+
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
}
le.ip += sizeof(uintptr_t);
+ if (skip_empty && val_len == 0) {
+ continue;
+ }
+
len += 2 + key_len + 2 + val_len;
}
}
@@ -706,11 +713,28 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r)
lcode = *(ngx_http_script_len_code_pt *) le.ip;
key_len = (u_char) lcode (&le);
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ skip_empty = lcode(&le);
+
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
}
le.ip += sizeof(uintptr_t);
+ if (skip_empty && val_len == 0) {
+ e.skip = 1;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
+ }
+ e.ip += sizeof(uintptr_t);
+
+ e.skip = 0;
+
+ continue;
+ }
+
*e.pos++ = (u_char) (key_len & 0xff);
*e.pos++ = (u_char) ((key_len >> 8) & 0xff);
@@ -1379,9 +1403,9 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
#if (NGX_HTTP_CACHE)
ngx_array_t params_merged;
#endif
- ngx_keyval_t *src;
ngx_hash_key_t *hk;
ngx_hash_init_t hash;
+ ngx_http_upstream_param_t *src;
ngx_http_script_compile_t sc;
ngx_http_script_copy_code_t *copy;
@@ -1442,9 +1466,11 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
#if (NGX_HTTP_CACHE)
if (conf->upstream.cache) {
- ngx_keyval_t *h, *s;
+ ngx_keyval_t *h;
+ ngx_http_upstream_param_t *s;
- if (ngx_array_init(&params_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
+ if (ngx_array_init(&params_merged, cf->temp_pool, 4,
+ sizeof(ngx_http_upstream_param_t))
!= NGX_OK)
{
return NGX_ERROR;
@@ -1478,7 +1504,9 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
return NGX_ERROR;
}
- *s = *h;
+ s->key = h->key;
+ s->value = h->value;
+ s->skip_empty = 0;
next:
@@ -1520,6 +1548,15 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
+ copy = ngx_array_push_n(conf->params_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
+ copy->len = src[i].skip_empty;
+
size = (sizeof(ngx_http_script_copy_code_t)
+ src[i].key.len + sizeof(uintptr_t) - 1)
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index c25925ab9..ec49d7bad 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.1.10';
+our $VERSION = '1.1.11';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 1eb22f81e..e10dbc88d 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1762,6 +1762,13 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
ls->rcvbuf = addr->opt.rcvbuf;
ls->sndbuf = addr->opt.sndbuf;
+ ls->keepalive = addr->opt.so_keepalive;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ ls->keepidle = addr->opt.tcp_keepidle;
+ ls->keepintvl = addr->opt.tcp_keepintvl;
+ ls->keepcnt = addr->opt.tcp_keepcnt;
+#endif
+
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
ls->accept_filter = addr->opt.accept_filter;
#endif
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 96be42369..3c5711748 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1289,6 +1289,7 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r,
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+ of.read_ahead = clcf->read_ahead;
of.directio = clcf->directio;
of.valid = clcf->open_file_cache_valid;
of.min_uses = clcf->open_file_cache_min_uses;
@@ -3815,6 +3816,97 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
+ if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) {
+
+ if (ngx_strcmp(&value[n].data[13], "on") == 0) {
+ lsopt.so_keepalive = 1;
+
+ } else if (ngx_strcmp(&value[n].data[13], "off") == 0) {
+ lsopt.so_keepalive = 2;
+
+ } else {
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ u_char *p, *end;
+ ngx_str_t s;
+
+ end = value[n].data + value[n].len;
+ s.data = value[n].data + 13;
+
+ p = ngx_strlchr(s.data, end, ':');
+ if (p == NULL) {
+ p = end;
+ }
+
+ if (p > s.data) {
+ s.len = p - s.data;
+
+ lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
+ if (lsopt.tcp_keepidle == NGX_ERROR) {
+ goto invalid_so_keepalive;
+ }
+ }
+
+ s.data = (p < end) ? (p + 1) : end;
+
+ p = ngx_strlchr(s.data, end, ':');
+ if (p == NULL) {
+ p = end;
+ }
+
+ if (p > s.data) {
+ s.len = p - s.data;
+
+ lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
+ if (lsopt.tcp_keepintvl == NGX_ERROR) {
+ goto invalid_so_keepalive;
+ }
+ }
+
+ s.data = (p < end) ? (p + 1) : end;
+
+ if (s.data < end) {
+ s.len = end - s.data;
+
+ lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len);
+ if (lsopt.tcp_keepcnt == NGX_ERROR) {
+ goto invalid_so_keepalive;
+ }
+ }
+
+ if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0
+ && lsopt.tcp_keepcnt == 0)
+ {
+ goto invalid_so_keepalive;
+ }
+
+ lsopt.so_keepalive = 1;
+
+#else
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the \"so_keepalive\" parameter accepts "
+ "only \"on\" or \"off\" on this platform");
+ return NGX_CONF_ERROR;
+
+#endif
+ }
+
+ lsopt.set = 1;
+ lsopt.bind = 1;
+
+ continue;
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ invalid_so_keepalive:
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid so_keepalive value: \"%s\"",
+ &value[n].data[13]);
+ return NGX_CONF_ERROR;
+#endif
+ }
+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[n]);
return NGX_CONF_ERROR;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index d2764fe0d..73e39e3b9 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -77,6 +77,7 @@ typedef struct {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
unsigned ipv6only:2;
#endif
+ unsigned so_keepalive:2;
int backlog;
int rcvbuf;
@@ -84,6 +85,11 @@ typedef struct {
#if (NGX_HAVE_SETFIB)
int setfib;
#endif
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ int tcp_keepidle;
+ int tcp_keepintvl;
+ int tcp_keepcnt;
+#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
char *accept_filter;
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index f212d6c6c..050f356f1 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -386,6 +386,13 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c)
return NGX_DECLINED;
}
+ if (h->body_start > c->body_start) {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
+ "cache file \"%s\" has too long header",
+ c->file.name.data);
+ return NGX_DECLINED;
+ }
+
c->buf->last += n;
c->valid_sec = h->valid_sec;
@@ -1106,12 +1113,12 @@ ngx_http_file_cache_expire(ngx_http_file_cache_t *cache)
/*
* abnormally exited workers may leave locked cache entries,
* and although it may be safe to remove them completely,
- * we prefer to remove them from inactive queue and rbtree
- * only, and to allow other leaks
+ * we prefer to just move them to the top of the inactive queue
*/
ngx_queue_remove(q);
- ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
+ fcn->expire = ngx_time() + cache->inactive;
+ ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
"ignore long locked inactive cache entry %*s, count:%d",
@@ -1752,69 +1759,3 @@ ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
return NGX_CONF_OK;
}
-
-
-ngx_int_t
-ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache)
-{
- ngx_str_t val;
- ngx_uint_t i;
- ngx_http_complex_value_t *cv;
-
- cv = no_cache->elts;
-
- for (i = 0; i < no_cache->nelts; i++) {
- if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (val.len && val.data[0] != '0') {
- return NGX_DECLINED;
- }
- }
-
- return NGX_OK;
-}
-
-
-char *
-ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- char *p = conf;
-
- ngx_str_t *value;
- ngx_uint_t i;
- ngx_array_t **a;
- ngx_http_complex_value_t *cv;
- ngx_http_compile_complex_value_t ccv;
-
- a = (ngx_array_t **) (p + cmd->offset);
-
- if (*a == NGX_CONF_UNSET_PTR) {
- *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
- if (*a == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- value = cf->args->elts;
-
- for (i = 1; i < cf->args->nelts; i++) {
- cv = ngx_array_push(*a);
- if (cv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[i];
- ccv.complex_value = cv;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- return NGX_CONF_OK;
-}
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index bccf63624..2f8a38dad 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -61,8 +61,8 @@ static ngx_str_t ngx_http_status_lines[] = {
/* ngx_null_string, */ /* "207 Multi-Status" */
-#define NGX_HTTP_LAST_LEVEL_200 207
-#define NGX_HTTP_LEVEL_200 (NGX_HTTP_LAST_LEVEL_200 - 200)
+#define NGX_HTTP_LAST_2XX 207
+#define NGX_HTTP_OFF_3XX (NGX_HTTP_LAST_2XX - 200)
/* ngx_null_string, */ /* "300 Multiple Choices" */
@@ -75,8 +75,8 @@ static ngx_str_t ngx_http_status_lines[] = {
/* ngx_null_string, */ /* "306 unused" */
/* ngx_null_string, */ /* "307 Temporary Redirect" */
-#define NGX_HTTP_LAST_LEVEL_300 305
-#define NGX_HTTP_LEVEL_300 (NGX_HTTP_LAST_LEVEL_300 - 301)
+#define NGX_HTTP_LAST_3XX 305
+#define NGX_HTTP_OFF_4XX (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX)
ngx_string("400 Bad Request"),
ngx_string("401 Unauthorized"),
@@ -108,8 +108,8 @@ static ngx_str_t ngx_http_status_lines[] = {
/* ngx_null_string, */ /* "423 Locked" */
/* ngx_null_string, */ /* "424 Failed Dependency" */
-#define NGX_HTTP_LAST_LEVEL_400 417
-#define NGX_HTTP_LEVEL_400 (NGX_HTTP_LAST_LEVEL_400 - 400)
+#define NGX_HTTP_LAST_4XX 417
+#define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX)
ngx_string("500 Internal Server Error"),
ngx_string("501 Method Not Implemented"),
@@ -124,7 +124,7 @@ static ngx_str_t ngx_http_status_lines[] = {
/* ngx_null_string, */ /* "509 unused" */
/* ngx_null_string, */ /* "510 Not Extended" */
-#define NGX_HTTP_LAST_LEVEL_500 508
+#define NGX_HTTP_LAST_5XX 508
};
@@ -216,7 +216,7 @@ ngx_http_header_filter(ngx_http_request_t *r)
status = r->headers_out.status;
if (status >= NGX_HTTP_OK
- && status < NGX_HTTP_LAST_LEVEL_200)
+ && status < NGX_HTTP_LAST_2XX)
{
/* 2XX */
@@ -234,7 +234,7 @@ ngx_http_header_filter(ngx_http_request_t *r)
len += ngx_http_status_lines[status].len;
} else if (status >= NGX_HTTP_MOVED_PERMANENTLY
- && status < NGX_HTTP_LAST_LEVEL_300)
+ && status < NGX_HTTP_LAST_3XX)
{
/* 3XX */
@@ -242,29 +242,26 @@ ngx_http_header_filter(ngx_http_request_t *r)
r->header_only = 1;
}
- status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200;
+ status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX;
status_line = &ngx_http_status_lines[status];
len += ngx_http_status_lines[status].len;
} else if (status >= NGX_HTTP_BAD_REQUEST
- && status < NGX_HTTP_LAST_LEVEL_400)
+ && status < NGX_HTTP_LAST_4XX)
{
/* 4XX */
status = status - NGX_HTTP_BAD_REQUEST
- + NGX_HTTP_LEVEL_200
- + NGX_HTTP_LEVEL_300;
+ + NGX_HTTP_OFF_4XX;
status_line = &ngx_http_status_lines[status];
len += ngx_http_status_lines[status].len;
} else if (status >= NGX_HTTP_INTERNAL_SERVER_ERROR
- && status < NGX_HTTP_LAST_LEVEL_500)
+ && status < NGX_HTTP_LAST_5XX)
{
/* 5XX */
status = status - NGX_HTTP_INTERNAL_SERVER_ERROR
- + NGX_HTTP_LEVEL_200
- + NGX_HTTP_LEVEL_300
- + NGX_HTTP_LEVEL_400;
+ + NGX_HTTP_OFF_5XX;
status_line = &ngx_http_status_lines[status];
len += ngx_http_status_lines[status].len;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 25b6de2e8..9f0ff3a54 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -4444,6 +4444,50 @@ ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
}
+char *
+ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf)
+{
+ char *p = conf;
+
+ ngx_str_t *value;
+ ngx_array_t **a;
+ ngx_http_upstream_param_t *param;
+
+ a = (ngx_array_t **) (p + cmd->offset);
+
+ if (*a == NULL) {
+ *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
+ if (*a == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ param = ngx_array_push(*a);
+ if (param == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ value = cf->args->elts;
+
+ param->key = value[1];
+ param->value = value[2];
+ param->skip_empty = 0;
+
+ if (cf->args->nelts == 4) {
+ if (ngx_strcmp(value[3].data, "if_not_empty") != 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter \"%V\"", &value[3]);
+ return NGX_CONF_ERROR;
+ }
+
+ param->skip_empty = 1;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
ngx_int_t
ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index aea9466a2..fa93be69f 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -328,6 +328,13 @@ typedef struct {
} ngx_http_upstream_next_t;
+typedef struct {
+ ngx_str_t key;
+ ngx_str_t value;
+ ngx_uint_t skip_empty;
+} ngx_http_upstream_param_t;
+
+
ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@@ -337,6 +344,8 @@ ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
ngx_url_t *u, ngx_uint_t flags);
char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+char *ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
ngx_str_t *default_hide_headers, ngx_hash_init_t *hash);
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 4afd88405..840519ef9 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -48,6 +48,8 @@ static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
@@ -157,6 +159,8 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 },
+ { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 },
+
{ ngx_string("request_uri"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
@@ -640,8 +644,8 @@ static ngx_int_t
ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
{
- ssize_t len;
- u_char *p;
+ size_t len;
+ u_char *p, *end;
ngx_uint_t i, n;
ngx_array_t *a;
ngx_table_elt_t **h;
@@ -649,18 +653,30 @@ ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
a = (ngx_array_t *) ((char *) r + data);
n = a->nelts;
+ h = a->elts;
- if (n == 0) {
+ len = 0;
+
+ for (i = 0; i < n; i++) {
+
+ if (h[i]->hash == 0) {
+ continue;
+ }
+
+ len += h[i]->value.len + sizeof("; ") - 1;
+ }
+
+ if (len == 0) {
v->not_found = 1;
return NGX_OK;
}
+ len -= sizeof("; ") - 1;
+
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
- h = a->elts;
-
if (n == 1) {
v->len = (*h)->value.len;
v->data = (*h)->value.data;
@@ -668,12 +684,6 @@ ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
return NGX_OK;
}
- len = - (ssize_t) (sizeof("; ") - 1);
-
- for (i = 0; i < n; i++) {
- len += h[i]->value.len + sizeof("; ") - 1;
- }
-
p = ngx_pnalloc(r->pool, len);
if (p == NULL) {
return NGX_ERROR;
@@ -682,10 +692,17 @@ ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
v->len = len;
v->data = p;
+ end = p + len;
+
for (i = 0; /* void */ ; i++) {
+
+ if (h[i]->hash == 0) {
+ continue;
+ }
+
p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
- if (i == n - 1) {
+ if (p == end) {
break;
}
@@ -738,6 +755,10 @@ ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
i = 0;
}
+ if (header[i].hash == 0) {
+ continue;
+ }
+
for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) {
ch = header[i].key.data[n];
@@ -1091,6 +1112,30 @@ ngx_http_variable_scheme(ngx_http_request_t *r,
static ngx_int_t
+ngx_http_variable_https(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+#if (NGX_HTTP_SSL)
+
+ if (r->connection->ssl) {
+ v->len = sizeof("on") - 1;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) "on";
+
+ return NGX_OK;
+ }
+
+#endif
+
+ *v = ngx_http_variable_null_value;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_variable_is_args(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c
index 3eeb97fe0..0234d18ef 100644
--- a/src/mail/ngx_mail.c
+++ b/src/mail/ngx_mail.c
@@ -308,6 +308,12 @@ found:
addr->ctx = listen->ctx;
addr->bind = listen->bind;
addr->wildcard = listen->wildcard;
+ addr->so_keepalive = listen->so_keepalive;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ addr->tcp_keepidle = listen->tcp_keepidle;
+ addr->tcp_keepintvl = listen->tcp_keepintvl;
+ addr->tcp_keepcnt = listen->tcp_keepcnt;
+#endif
#if (NGX_MAIL_SSL)
addr->ssl = listen->ssl;
#endif
@@ -373,6 +379,13 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
ls->log.data = &ls->addr_text;
ls->log.handler = ngx_accept_log_error;
+ ls->keepalive = addr[i].so_keepalive;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ ls->keepidle = addr[i].tcp_keepidle;
+ ls->keepintvl = addr[i].tcp_keepintvl;
+ ls->keepcnt = addr[i].tcp_keepcnt;
+#endif
+
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
ls->ipv6only = addr[i].ipv6only;
#endif
diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h
index fd6d318a5..ca78d0553 100644
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -40,6 +40,12 @@ typedef struct {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
unsigned ipv6only:2;
#endif
+ unsigned so_keepalive:2;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ int tcp_keepidle;
+ int tcp_keepintvl;
+ int tcp_keepcnt;
+#endif
} ngx_mail_listen_t;
@@ -95,6 +101,12 @@ typedef struct {
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
unsigned ipv6only:2;
#endif
+ unsigned so_keepalive:2;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ int tcp_keepidle;
+ int tcp_keepintvl;
+ int tcp_keepcnt;
+#endif
} ngx_mail_conf_addr_t;
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index 0088fbf26..530bc5d49 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -24,6 +24,12 @@ static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static ngx_conf_deprecated_t ngx_conf_deprecated_so_keepalive = {
+ ngx_conf_deprecated, "so_keepalive",
+ "so_keepalive\" parameter of the \"listen"
+};
+
+
static ngx_command_t ngx_mail_core_commands[] = {
{ ngx_string("server"),
@@ -52,7 +58,7 @@ static ngx_command_t ngx_mail_core_commands[] = {
ngx_conf_set_flag_slot,
NGX_MAIL_SRV_CONF_OFFSET,
offsetof(ngx_mail_core_srv_conf_t, so_keepalive),
- NULL },
+ &ngx_conf_deprecated_so_keepalive },
{ ngx_string("timeout"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
@@ -446,6 +452,96 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
+ if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
+
+ if (ngx_strcmp(&value[i].data[13], "on") == 0) {
+ ls->so_keepalive = 1;
+
+ } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
+ ls->so_keepalive = 2;
+
+ } else {
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ u_char *p, *end;
+ ngx_str_t s;
+
+ end = value[i].data + value[i].len;
+ s.data = value[i].data + 13;
+
+ p = ngx_strlchr(s.data, end, ':');
+ if (p == NULL) {
+ p = end;
+ }
+
+ if (p > s.data) {
+ s.len = p - s.data;
+
+ ls->tcp_keepidle = ngx_parse_time(&s, 1);
+ if (ls->tcp_keepidle == NGX_ERROR) {
+ goto invalid_so_keepalive;
+ }
+ }
+
+ s.data = (p < end) ? (p + 1) : end;
+
+ p = ngx_strlchr(s.data, end, ':');
+ if (p == NULL) {
+ p = end;
+ }
+
+ if (p > s.data) {
+ s.len = p - s.data;
+
+ ls->tcp_keepintvl = ngx_parse_time(&s, 1);
+ if (ls->tcp_keepintvl == NGX_ERROR) {
+ goto invalid_so_keepalive;
+ }
+ }
+
+ s.data = (p < end) ? (p + 1) : end;
+
+ if (s.data < end) {
+ s.len = end - s.data;
+
+ ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
+ if (ls->tcp_keepcnt == NGX_ERROR) {
+ goto invalid_so_keepalive;
+ }
+ }
+
+ if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
+ && ls->tcp_keepcnt == 0)
+ {
+ goto invalid_so_keepalive;
+ }
+
+ ls->so_keepalive = 1;
+
+#else
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the \"so_keepalive\" parameter accepts "
+ "only \"on\" or \"off\" on this platform");
+ return NGX_CONF_ERROR;
+
+#endif
+ }
+
+ ls->bind = 1;
+
+ continue;
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+ invalid_so_keepalive:
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid so_keepalive value: \"%s\"",
+ &value[i].data[13]);
+ return NGX_CONF_ERROR;
+#endif
+ }
+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the invalid \"%V\" parameter", &value[i]);
return NGX_CONF_ERROR;
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 039243e96..8c98f8e38 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -246,9 +246,14 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
}
}
- hdtr.headers = (struct iovec *) header.elts;
+ /*
+ * sendfile() does unneeded work if sf_hdtr's count is 0,
+ * but corresponding pointer is not NULL
+ */
+
+ hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL;
hdtr.hdr_cnt = header.nelts;
- hdtr.trailers = (struct iovec *) trailer.elts;
+ hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL;
hdtr.trl_cnt = trailer.nelts;
/*