changeset 644:6f21ae02fb01 NGINX_1_1_6

nginx 1.1.6 *) Change in internal API: now module context data are cleared while internal redirect to named location. Requested by Yichun Zhang. *) Change: if a server in an upstream failed, only one request will be sent to it after fail_timeout; the server will be considered alive if it will successfully respond to the request. *) Change: now the 0x7F-0x1F characters are escaped as \xXX in an access_log. *) Feature: "proxy/fastcgi/scgi/uwsgi_ignore_headers" directives support the following additional values: X-Accel-Limit-Rate, X-Accel-Buffering, X-Accel-Charset. *) Feature: decrease of memory consumption if SSL is used. *) Bugfix: some UTF-8 characters were processed incorrectly. Thanks to Alexey Kuts. *) Bugfix: the ngx_http_rewrite_module directives specified at "server" level were executed twice if no matching locations were defined. *) Bugfix: a socket leak might occurred if "aio sendfile" was used. *) Bugfix: connections with fast clients might be closed after send_timeout if file AIO was used. *) Bugfix: in the ngx_http_autoindex_module. *) Bugfix: the module ngx_http_mp4_module did not support seeking on 32-bit platforms.
author Igor Sysoev <http://sysoev.ru>
date Mon, 17 Oct 2011 00:00:00 +0400
parents a4bb0b481f6c
children e461dead01e9
files CHANGES CHANGES.ru auto/install html/ngx_core_module.html src/core/nginx.h src/core/ngx_parse.c src/core/ngx_parse.h src/core/ngx_string.c src/core/ngx_string.h src/event/ngx_event_openssl.c src/http/modules/ngx_http_autoindex_module.c src/http/modules/ngx_http_log_module.c src/http/modules/ngx_http_mp4_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_rewrite_module.c src/http/modules/ngx_http_static_module.c src/http/modules/ngx_http_upstream_ip_hash_module.c src/http/modules/perl/nginx.pm src/http/modules/perl/nginx.xs src/http/ngx_http_copy_filter_module.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_request.c src/http/ngx_http_script.c src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/http/ngx_http_upstream_round_robin.c src/http/ngx_http_upstream_round_robin.h
diffstat 29 files changed, 332 insertions(+), 267 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,40 @@
 
+Changes with nginx 1.1.6                                         17 Oct 2011
+
+    *) Change in internal API: now module context data are cleared while
+       internal redirect to named location.
+       Requested by Yichun Zhang.
+
+    *) Change: if a server in an upstream failed, only one request will be
+       sent to it after fail_timeout; the server will be considered alive if
+       it will successfully respond to the request.
+
+    *) Change: now the 0x7F-0x1F characters are escaped as \xXX in an
+       access_log.
+
+    *) Feature: "proxy/fastcgi/scgi/uwsgi_ignore_headers" directives support
+       the following additional values: X-Accel-Limit-Rate,
+       X-Accel-Buffering, X-Accel-Charset.
+
+    *) Feature: decrease of memory consumption if SSL is used.
+
+    *) Bugfix: some UTF-8 characters were processed incorrectly.
+       Thanks to Alexey Kuts.
+
+    *) Bugfix: the ngx_http_rewrite_module directives specified at "server"
+       level were executed twice if no matching locations were defined.
+
+    *) Bugfix: a socket leak might occurred if "aio sendfile" was used.
+
+    *) Bugfix: connections with fast clients might be closed after
+       send_timeout if file AIO was used.
+
+    *) Bugfix: in the ngx_http_autoindex_module.
+
+    *) Bugfix: the module ngx_http_mp4_module did not support seeking on
+       32-bit platforms.
+
+
 Changes with nginx 1.1.5                                         05 Oct 2011
 
     *) Feature: the "uwsgi_buffering" and "scgi_buffering" directives.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,43 @@
 
+Изменения в nginx 1.1.6                                           17.10.2011
+
+    *) Изменение во внутреннем API: теперь при внутреннем редиректе в
+       именованный location контексты модулей очищаются.
+       По запросу Yichun Zhang.
+
+    *) Изменение: теперь если сервер, описанный в блоке upstream, был
+       признан неработающим, то после истечения fail_timeout на него будет
+       отправлен только один запрос; сервер будет считаться работающим, если
+       успешно ответит на этот запрос.
+
+    *) Изменение: теперь символы 0x7F-0xFF в access_log записываются в виде
+       \xXX.
+
+    *) Добавление: директивы "proxy/fastcgi/scgi/uwsgi_ignore_headers"
+       теперь поддерживают значения X-Accel-Limit-Rate, X-Accel-Buffering и
+       X-Accel-Charset.
+
+    *) Добавление: уменьшение потребления памяти при использовании SSL.
+
+    *) Исправление: некоторые UTF-8 символы обрабатывались неправильно.
+       Спасибо Алексею Куцу.
+
+    *) Исправление: директивы модуля ngx_http_rewrite_module, заданные на
+       уровне server, применялись повторно, если для запроса не находилось
+       ни одного location'а.
+
+    *) Исправление: при использовании "aio sendfile" могла происходить
+       утечка сокетов.
+
+    *) Исправление: при использовании файлового AIO соединения с быстрыми
+       клиентами могли быть закрыты по истечению send_timeout.
+
+    *) Исправление: в модуле ngx_http_autoindex_module.
+
+    *) Исправление: модуль ngx_http_mp4_module не поддерживал перемотку на
+       32-битных платформах.
+
+
 Изменения в nginx 1.1.5                                           05.10.2011
 
     *) Добавление: директивы uwsgi_buffering и scgi_buffering.
--- a/auto/install
+++ b/auto/install
@@ -53,7 +53,7 @@ esac
 
 
 case ".$NGX_ERROR_LOG_PATH" in
-    ./*)
+    ./* | .)
     ;;
 
     *)
@@ -80,7 +80,7 @@ manpage:	$NGX_OBJS/nginx.8
 	sed -e "s|%%PREFIX%%|$NGX_PREFIX|" \\
 		-e "s|%%PID_PATH%%|$NGX_PID_PATH|" \\
 		-e "s|%%CONF_PATH%%|$NGX_CONF_PATH|" \\
-		-e "s|%%ERROR_LOG_PATH%%|$NGX_ERROR_LOG_PATH|" \\
+		-e "s|%%ERROR_LOG_PATH%%|${NGX_ERROR_LOG_PATH:-stderr}|" \\
 		< man/nginx.8 > $NGX_OBJS/nginx.8
 
 install:	$NGX_OBJS${ngx_dirsep}nginx${ngx_binext} \
@@ -139,7 +139,7 @@ install:	$NGX_OBJS${ngx_dirsep}nginx${ng
 END
 
 
-if test -n "\$(DESTDIR)$NGX_ERROR_LOG_PATH"; then
+if test -n "$NGX_ERROR_LOG_PATH"; then
     cat << END                                                >> $NGX_MAKEFILE
 
 	test -d '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' || \
deleted file mode 100644
--- a/html/ngx_core_module.html
+++ /dev/null
@@ -1,148 +0,0 @@
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Core Module</title></head><body><center><h3>Core Module</h3></center><a name="example"></a><center><h4>Example Configuration</h4></center><p><blockquote><pre>
-user www www;
-worker_processes 2;
-
-error_log /var/log/nginx-error.log info;
-
-events {
-    use kqueue;
-    worker_connections 2048;
-}
-
-...
-</pre></blockquote></p><a name="directives"></a><center><h4>Directives</h4></center><hr><a name="daemon"></a><strong>syntax</strong>:
-         <code>daemon <code>on</code> | <code>off</code></code><br><strong>default</strong>:
-      <code>daemon on</code><br><strong>context</strong>:
-      <code>main</code><br><p>
-Determines whether nginx should become a daemon.
-Mainly used during development.
-</p><hr><a name="env"></a><strong>syntax</strong>:
-         <code>env <code><i>VAR</i></code>[=<code><i>VALUE</i></code>]</code><br><strong>default</strong>:
-      <code>env TZ</code><br><strong>context</strong>:
-      <code>main</code><br><p>
-Allows to limit a set of environment variables, change their values,
-or create new environment variables, for the following cases:
-<ul><li>
-variable inheritance during a
-<a href="control.html#upgrade">live upgrade</a>
-of an executable file;
-</li><li>
-use of variables by the module
-<a href="http/ngx_http_perl_module.html">ngx_http_perl_module</a>;
-</li><li>
-use of variables by worker processes.
-Please bear in mind that controlling system libraries in this way
-is not always possible as it is not uncommon for libraries to check
-variables only during initialization, well before they can be set
-using this directive.
-An exception from this is an above mentioned
-<a href="control.html#upgrade">live upgrade</a>
-of an executable file.
-</li></ul></p><p>
-The TZ variable is always inherited and made available to the module
-<a href="http/ngx_http_perl_module.html">ngx_http_perl_module</a>,
-unless configured explicitly.
-</p><p>
-Usage example:
-<blockquote><pre>
-env MALLOC_OPTIONS;
-env PERL5LIB=/data/site/modules;
-env OPENSSL_ALLOW_PROXY_CERTS=1;
-</pre></blockquote></p><hr><a name="include"></a><strong>syntax</strong>:
-         <code>include <code><i>file</i></code> | <code><i>mask</i></code></code><br><strong>default</strong>:
-      <strong>none</strong><br><strong>context</strong>:
-      <strong>any</strong><br><p>
-Includes another <code><i>file</i></code>, or files matching the
-specified <code><i>mask</i></code>, into configuration.
-Included files should consist of
-syntactically correct directives and blocks.
-</p><p>
-Usage example:
-<blockquote><pre>
-include mime.types;
-include vhosts/*.conf;
-</pre></blockquote></p><hr><a name="master_process"></a><strong>syntax</strong>:
-         <code>master_process <code>on</code> | <code>off</code></code><br><strong>default</strong>:
-      <code>master_process on</code><br><strong>context</strong>:
-      <code>main</code><br><p>
-Determines whether worker processes are started.
-This directive is intended for nginx developers.
-</p><hr><a name="pid"></a><strong>syntax</strong>:
-         <code>pid <code><i>file</i></code></code><br><strong>default</strong>:
-      <code>pid nginx.pid</code><br><strong>context</strong>:
-      <code>main</code><br><p>
-Defines a <code><i>file</i></code> which will store the process ID of the main process.
-</p><hr><a name="ssl_engine"></a><strong>syntax</strong>:
-         <code>ssl_engine <code><i>device</i></code></code><br><strong>default</strong>:
-      <strong>none</strong><br><strong>context</strong>:
-      <code>main</code><br><p>
-Defines the name of the hardware SSL accelerator.
-</p><hr><a name="user"></a><strong>syntax</strong>:
-         <code>user <code><i>user</i></code> [<code><i>group</i></code>]</code><br><strong>default</strong>:
-      <code>user nobody nobody</code><br><strong>context</strong>:
-      <code>main</code><br><p>
-Defines <code><i>user</i></code> and <code><i>group</i></code>
-credentials used by worker processes.
-If <code><i>group</i></code> is omitted, a group whose name equals
-that of <code><i>user</i></code> is used.
-</p><hr><a name="timer_resolution"></a><strong>syntax</strong>:
-         <code>timer_resolution <code><i>interval</i></code></code><br><strong>default</strong>:
-      <strong>none</strong><br><strong>context</strong>:
-      <code>main</code><br><p>
-Reduces timer resolution in worker processes, thus reducing the
-number of <code>gettimeofday()</code> system calls made.
-By default, <code>gettimeofday()</code> is called each time
-on receiving a kernel event.
-With reduced resolution, <code>gettimeofday()</code> is only
-called once per specified <code><i>interval</i></code>.
-</p><p>
-Example:
-<blockquote><pre>
-timer_resolution 100ms;
-</pre></blockquote></p><p>
-An internal implementation of interval depends on the method used:
-<ul><li>
-an <code>EVFILT_TIMER</code> filter if <code>kqueue</code> is used;
-</li><li><code>timer_create()</code> if <code>eventport</code> is used;
-</li><li><code>setitimer()</code> otherwise.
-</li></ul></p><hr><a name="worker_rlimit_core"></a><strong>syntax</strong>:
-         <code>worker_rlimit_core <code><i>size</i></code></code><br><strong>default</strong>:
-      <strong>none</strong><br><strong>context</strong>:
-      <code>main</code><br><p>
-Changes the limit on the largest size of a core file
-(<code>RLIMIT_CORE</code>) for worker processes.
-Used to increase the limit without restarting the main process.
-</p><hr><a name="worker_rlimit_nofile"></a><strong>syntax</strong>:
-         <code>worker_rlimit_nofile <code><i>number</i></code></code><br><strong>default</strong>:
-      <strong>none</strong><br><strong>context</strong>:
-      <code>main</code><br><p>
-Changes the limit on the maximum number of open files
-(<code>RLIMIT_NOFILE</code>) for worker processes.
-Used to increase the limit without restarting the main process.
-</p><hr><a name="worker_priority"></a><strong>syntax</strong>:
-         <code>worker_priority <code><i>number</i></code></code><br><strong>default</strong>:
-      <code>worker_priority 0</code><br><strong>context</strong>:
-      <code>main</code><br><p>
-Defines a scheduling priority for worker processes like is
-done by the <code>nice</code>: a negative
-<code><i>number</i></code>
-means higher priority.
-Allowed range normally varies from -20 to 20.
-</p><p>
-Example:
-<blockquote><pre>
-worker_priority -10;
-</pre></blockquote></p><hr><a name="worker_processes"></a><strong>syntax</strong>:
-         <code>worker_processes <code><i>number</i></code></code><br><strong>default</strong>:
-      <code>worker_processes 1</code><br><strong>context</strong>:
-      <code>main</code><br><p>
-Defines the number of worker processes.
-</p><hr><a name="working_directory"></a><strong>syntax</strong>:
-         <code>working_directory <code><i>directory</i></code></code><br><strong>default</strong>:
-      <strong>none</strong><br><strong>context</strong>:
-      <code>main</code><br><p>
-Defines a current working directory for a worker process.
-It is primarily used when writing a core-file, in which case
-a working process should have write permission for the
-specified directory.
-</p></body></html>
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version      1001005
-#define NGINX_VERSION      "1.1.5"
+#define nginx_version      1001006
+#define NGINX_VERSION      "1.1.6"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_parse.c
+++ b/src/core/ngx_parse.c
@@ -93,7 +93,7 @@ ngx_parse_offset(ngx_str_t *line)
 
 
 ngx_int_t
-ngx_parse_time(ngx_str_t *line, ngx_uint_t sec)
+ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec)
 {
     u_char      *p, *last;
     ngx_int_t    value, total, scale;
@@ -114,8 +114,8 @@ ngx_parse_time(ngx_str_t *line, ngx_uint
     valid = 0;
     value = 0;
     total = 0;
-    step = sec ? st_start : st_month;
-    scale = sec ? 1 : 1000;
+    step = is_sec ? st_start : st_month;
+    scale = is_sec ? 1 : 1000;
 
     p = line->data;
     last = p + line->len;
@@ -135,81 +135,81 @@ ngx_parse_time(ngx_str_t *line, ngx_uint
                 return NGX_ERROR;
             }
             step = st_year;
-            max = 68;
+            max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 365);
             scale = 60 * 60 * 24 * 365;
             break;
 
         case 'M':
-            if (step > st_year) {
+            if (step >= st_month) {
                 return NGX_ERROR;
             }
             step = st_month;
-            max = 828;
+            max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 30);
             scale = 60 * 60 * 24 * 30;
             break;
 
         case 'w':
-            if (step > st_month) {
+            if (step >= st_week) {
                 return NGX_ERROR;
             }
             step = st_week;
-            max = 3550;
+            max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 7);
             scale = 60 * 60 * 24 * 7;
             break;
 
         case 'd':
-            if (step > st_week) {
+            if (step >= st_day) {
                 return NGX_ERROR;
             }
             step = st_day;
-            max = 24855;
+            max = NGX_MAX_INT32_VALUE / (60 * 60 * 24);
             scale = 60 * 60 * 24;
             break;
 
         case 'h':
-            if (step > st_day) {
+            if (step >= st_hour) {
                 return NGX_ERROR;
             }
             step = st_hour;
-            max = 596523;
+            max = NGX_MAX_INT32_VALUE / (60 * 60);
             scale = 60 * 60;
             break;
 
         case 'm':
             if (*p == 's') {
-                if (sec || step > st_sec) {
+                if (is_sec || step >= st_msec) {
                     return NGX_ERROR;
                 }
                 p++;
                 step = st_msec;
-                max = 2147483647;
+                max = NGX_MAX_INT32_VALUE;
                 scale = 1;
                 break;
             }
 
-            if (step > st_hour) {
+            if (step >= st_min) {
                 return NGX_ERROR;
             }
             step = st_min;
-            max = 35791394;
+            max = NGX_MAX_INT32_VALUE / 60;
             scale = 60;
             break;
 
         case 's':
-            if (step > st_min) {
+            if (step >= st_sec) {
                 return NGX_ERROR;
             }
             step = st_sec;
-            max = 2147483647;
+            max = NGX_MAX_INT32_VALUE;
             scale = 1;
             break;
 
         case ' ':
-            if (step > st_min) {
+            if (step >= st_sec) {
                 return NGX_ERROR;
             }
             step = st_last;
-            max = 2147483647;
+            max = NGX_MAX_INT32_VALUE;
             scale = 1;
             break;
 
@@ -217,7 +217,7 @@ ngx_parse_time(ngx_str_t *line, ngx_uint
             return NGX_ERROR;
         }
 
-        if (step != st_msec && !sec) {
+        if (step != st_msec && !is_sec) {
             scale *= 1000;
             max /= 1000;
         }
@@ -228,12 +228,12 @@ ngx_parse_time(ngx_str_t *line, ngx_uint
 
         total += value * scale;
 
-        if ((ngx_uint_t) total > 2147483647) {
+        if ((ngx_uint_t) total > NGX_MAX_INT32_VALUE) {
             return NGX_ERROR;
         }
 
         value = 0;
-        scale = sec ? 1 : 1000;
+        scale = is_sec ? 1 : 1000;
 
         while (p < last && *p == ' ') {
             p++;
--- a/src/core/ngx_parse.h
+++ b/src/core/ngx_parse.h
@@ -17,7 +17,7 @@
 
 ssize_t ngx_parse_size(ngx_str_t *line);
 off_t ngx_parse_offset(ngx_str_t *line);
-ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_uint_t sec);
+ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec);
 
 
 #endif /* _NGX_PARSE_H_INCLUDED_ */
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1211,19 +1211,19 @@ ngx_utf8_decode(u_char **p, size_t n)
 
     u = **p;
 
-    if (u > 0xf0) {
+    if (u >= 0xf0) {
 
         u &= 0x07;
         valid = 0xffff;
         len = 3;
 
-    } else if (u > 0xe0) {
+    } else if (u >= 0xe0) {
 
         u &= 0x0f;
         valid = 0x7ff;
         len = 2;
 
-    } else if (u > 0xc0) {
+    } else if (u >= 0xc2) {
 
         u &= 0x1f;
         valid = 0x7f;
@@ -1380,6 +1380,26 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
     };
 
+                    /* not ALPHA, DIGIT, "-", ".", "_", "~" */
+
+    static uint32_t   uri_component[] = {
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+
+                    /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
+        0xfc009fff, /* 1111 1100 0000 0000  1001 1111 1111 1111 */
+
+                    /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
+        0x78000001, /* 0111 1000 0000 0000  0000 0000 0000 0001 */
+
+                    /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
+        0xb8000001, /* 1011 1000 0000 0000  0000 0000 0000 0001 */
+
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+    };
+
                     /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */
 
     static uint32_t   html[] = {
@@ -1443,7 +1463,7 @@ ngx_escape_uri(u_char *dst, u_char *src,
                     /* mail_auth is the same as memcached */
 
     static uint32_t  *map[] =
-        { uri, args, html, refresh, memcached, memcached };
+        { uri, args, uri_component, html, refresh, memcached, memcached };
 
 
     escape = map[type];
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -189,12 +189,13 @@ size_t ngx_utf8_length(u_char *p, size_t
 u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);
 
 
-#define NGX_ESCAPE_URI         0
-#define NGX_ESCAPE_ARGS        1
-#define NGX_ESCAPE_HTML        2
-#define NGX_ESCAPE_REFRESH     3
-#define NGX_ESCAPE_MEMCACHED   4
-#define NGX_ESCAPE_MAIL_AUTH   5
+#define NGX_ESCAPE_URI            0
+#define NGX_ESCAPE_ARGS           1
+#define NGX_ESCAPE_URI_COMPONENT  2
+#define NGX_ESCAPE_HTML           3
+#define NGX_ESCAPE_REFRESH        4
+#define NGX_ESCAPE_MEMCACHED      5
+#define NGX_ESCAPE_MAIL_AUTH      6
 
 #define NGX_UNESCAPE_URI       1
 #define NGX_UNESCAPE_REDIRECT  2
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -175,6 +175,14 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_
         SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
     }
 
+#ifdef SSL_OP_NO_COMPRESSION
+    SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
+#endif
+
+#ifdef SSL_MODE_RELEASE_BUFFERS
+    SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
+#endif
+
     SSL_CTX_set_read_ahead(ssl->ctx, 1);
 
     SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -26,9 +26,9 @@ typedef struct {
     ngx_str_t      name;
     size_t         utf_len;
     size_t         escape;
+    size_t         escape_html;
 
     unsigned       dir:1;
-    unsigned       colon:1;
 
     time_t         mtime;
     off_t          size;
@@ -138,7 +138,7 @@ ngx_http_autoindex_handler(ngx_http_requ
 {
     u_char                         *last, *filename, scale;
     off_t                           length;
-    size_t                          len, utf_len, allocated, root;
+    size_t                          len, char_len, escape_html, allocated, root;
     ngx_tm_t                        tm;
     ngx_err_t                       err;
     ngx_buf_t                      *b;
@@ -338,7 +338,10 @@ ngx_http_autoindex_handler(ngx_http_requ
         ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
 
         entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,
-                                           NGX_ESCAPE_HTML);
+                                           NGX_ESCAPE_URI_COMPONENT);
+
+        entry->escape_html = ngx_escape_html(NULL, entry->name.data,
+                                             entry->name.len);
 
         if (utf8) {
             entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);
@@ -346,8 +349,6 @@ ngx_http_autoindex_handler(ngx_http_requ
             entry->utf_len = len;
         }
 
-        entry->colon = (ngx_strchr(entry->name.data, ':') != NULL);
-
         entry->dir = ngx_de_is_dir(&dir);
         entry->mtime = ngx_de_mtime(&dir);
         entry->size = ngx_de_size(&dir);
@@ -358,10 +359,12 @@ ngx_http_autoindex_handler(ngx_http_requ
                       ngx_close_dir_n " \"%s\" failed", &path);
     }
 
+    escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len);
+
     len = sizeof(title) - 1
-          + r->uri.len
+          + r->uri.len + escape_html
           + sizeof(header) - 1
-          + r->uri.len
+          + r->uri.len + escape_html
           + sizeof("</h1>") - 1
           + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1
           + sizeof("</pre><hr>") - 1
@@ -373,7 +376,8 @@ ngx_http_autoindex_handler(ngx_http_requ
             + entry[i].name.len + entry[i].escape
             + 1                                          /* 1 is for "/" */
             + sizeof("\">") - 1
-            + entry[i].name.len - entry[i].utf_len + entry[i].colon * 2
+            + entry[i].name.len - entry[i].utf_len
+            + entry[i].escape_html
             + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
             + sizeof("</a>") - 1
             + sizeof(" 28-Sep-1970 12:00 ") - 1
@@ -393,9 +397,18 @@ ngx_http_autoindex_handler(ngx_http_requ
     }
 
     b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);
-    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-    b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
-    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+
+    if (escape_html) {
+        b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
+        b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
+        b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
+
+    } else {
+        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+        b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
+        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+    }
+
     b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);
 
     b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF,
@@ -406,14 +419,9 @@ ngx_http_autoindex_handler(ngx_http_requ
     for (i = 0; i < entries.nelts; i++) {
         b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
 
-        if (entry[i].colon) {
-            *b->last++ = '.';
-            *b->last++ = '/';
-        }
-
         if (entry[i].escape) {
             ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
-                           NGX_ESCAPE_HTML);
+                           NGX_ESCAPE_URI_COMPONENT);
 
             b->last += entry[i].name.len + entry[i].escape;
 
@@ -433,20 +441,41 @@ ngx_http_autoindex_handler(ngx_http_requ
 
         if (entry[i].name.len != len) {
             if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
-                utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
+                char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
 
             } else {
-                utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
+                char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
             }
 
+            last = b->last;
             b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
-                                       utf_len, entry[i].name.len + 1);
+                                       char_len, entry[i].name.len + 1);
+
+            if (entry[i].escape_html) {
+                b->last = (u_char *) ngx_escape_html(last, entry[i].name.data,
+                                                     b->last - last);
+            }
+
             last = b->last;
 
         } else {
-            b->last = ngx_cpystrn(b->last, entry[i].name.data,
-                                  NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
-            last = b->last - 3;
+            if (entry[i].escape_html) {
+                if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
+                    char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3;
+
+                } else {
+                    char_len = len;
+                }
+
+                b->last = (u_char *) ngx_escape_html(b->last,
+                                                  entry[i].name.data, char_len);
+                last = b->last;
+
+            } else {
+                b->last = ngx_cpystrn(b->last, entry[i].name.data,
+                                      NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
+                last = b->last - 3;
+            }
         }
 
         if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -690,12 +690,12 @@ ngx_http_log_escape(u_char *dst, u_char 
         0x10000000, /* 0001 0000 0000 0000  0000 0000 0000 0000 */
 
                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
-        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
+        0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
 
-        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
-        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
-        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
-        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
     };
 
 
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -1882,7 +1882,7 @@ ngx_http_mp4_update_stts_atom(ngx_http_m
     }
 
     entries = trak->time_to_sample_entries;
-    start_time = mp4->start * trak->timescale / 1000;
+    start_time = (uint64_t) mp4->start * trak->timescale / 1000;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
                    "time-to-sample start_time:%uL", start_time);
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1560,7 +1560,7 @@ ngx_http_proxy_copy_filter(ngx_event_pip
         p->upstream_done = 1;
 
         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
-                      "upstream sent too many data");
+                      "upstream sent too much data");
     }
 
     return NGX_OK;
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -135,10 +135,22 @@ ngx_module_t  ngx_http_rewrite_module = 
 static ngx_int_t
 ngx_http_rewrite_handler(ngx_http_request_t *r)
 {
+    ngx_int_t                     index;
     ngx_http_script_code_pt       code;
     ngx_http_script_engine_t     *e;
+    ngx_http_core_srv_conf_t     *cscf;
+    ngx_http_core_main_conf_t    *cmcf;
     ngx_http_rewrite_loc_conf_t  *rlcf;
 
+    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+    index = cmcf->phase_engine.location_rewrite_index;
+
+    if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) {
+        /* skipping location rewrite phase for server null location */
+        return NGX_DECLINED;
+    }
+
     rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
 
     if (rlcf->codes == NULL) {
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -139,6 +139,8 @@ ngx_http_static_handler(ngx_http_request
 
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
 
+        ngx_http_clear_location(r);
+
         r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
         if (r->headers_out.location == NULL) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
--- a/src/http/modules/ngx_http_upstream_ip_hash_module.c
+++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c
@@ -185,8 +185,8 @@ ngx_http_upstream_get_ip_hash_peer(ngx_p
                     break;
                 }
 
-                if (now - peer->accessed > peer->fail_timeout) {
-                    peer->fails = 0;
+                if (now - peer->checked > peer->fail_timeout) {
+                    peer->checked = now;
                     break;
                 }
             }
--- 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.5';
+our $VERSION = '1.1.6';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -474,6 +474,13 @@ header_out(r, key, value)
         r->headers_out.content_length = header;
     }
 
+    if (header->key.len == sizeof("Content-Encoding") - 1
+        && ngx_strncasecmp(header->key.data, "Content-Encoding",
+                           sizeof("Content-Encoding") - 1) == 0)
+    {
+        r->headers_out.content_encoding = header;
+    }
+
 
 void
 filename(r)
@@ -836,7 +843,7 @@ variable(r, name, value = NULL)
     var.len = len;
     var.data = lowcase;
 
-    #if (NGX_LOG_DEBUG)
+    #if (NGX_DEBUG)
 
     if (value) {
         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -158,6 +158,11 @@ ngx_http_copy_filter(ngx_http_request_t 
             ngx_file_t            *file;
             ngx_http_ephemeral_t  *e;
 
+            if (r->aio) {
+                c->busy_sendfile = NULL;
+                return rc;
+            }
+
             file = c->busy_sendfile->file;
             offset = c->busy_sendfile->file_pos;
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -983,6 +983,8 @@ ngx_http_core_find_config_phase(ngx_http
     }
 
     if (rc == NGX_DONE) {
+        ngx_http_clear_location(r);
+
         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
         if (r->headers_out.location == NULL) {
             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -1796,6 +1798,8 @@ ngx_http_send_response(ngx_http_request_
 
     if (status >= NGX_HTTP_MOVED_PERMANENTLY && status <= NGX_HTTP_SEE_OTHER) {
 
+        ngx_http_clear_location(r);
+
         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
         if (r->headers_out.location == NULL) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -2542,6 +2546,9 @@ ngx_http_named_location(ngx_http_request
             r->content_handler = NULL;
             r->loc_conf = (*clcfp)->loc_conf;
 
+            /* clear the modules contexts */
+            ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
+
             ngx_http_update_location_config(r);
 
             cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
@@ -2994,6 +3001,12 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c
     value = cf->args->elts;
 
     if (ngx_strcmp(value[0].data, "include") == 0) {
+        if (cf->args->nelts != 2) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid number of arguments"
+                               " in \"include\" directive");
+            return NGX_CONF_ERROR;
+        }
         file = value[1];
 
         if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
@@ -3027,7 +3040,7 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c
                                    "content type: \"%V\", "
                                    "previous content type: \"%V\"",
                                    &value[i], content_type, old);
-                continue;
+                goto next;
             }
         }
 
@@ -3040,6 +3053,9 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c
         type->key = value[i];
         type->key_hash = hash;
         type->value = content_type;
+
+    next:
+        continue;
     }
 
     return NGX_CONF_OK;
@@ -3373,7 +3389,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
                                              ngx_cacheline_size);
 
     /*
-     * the special handling the "types" directive in the "http" section
+     * the special handling of the "types" directive in the "http" section
      * to inherit the http's conf->types_hash to all servers
      */
 
@@ -3400,7 +3416,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
     }
 
     if (conf->types == NULL) {
-        conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
+        conf->types = ngx_array_create(cf->pool, 3, sizeof(ngx_hash_key_t));
         if (conf->types == NULL) {
             return NGX_CONF_ERROR;
         }
@@ -3425,7 +3441,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
         types_hash.key = ngx_hash_key_lc;
         types_hash.max_size = conf->types_hash_max_size;
         types_hash.bucket_size = conf->types_hash_bucket_size;
-        types_hash.name = "mime_types_hash";
+        types_hash.name = "types_hash";
         types_hash.pool = cf->pool;
         types_hash.temp_pool = NULL;
 
@@ -3467,9 +3483,10 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
                               NGX_HTTP_IMS_EXACT);
     ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges,
-                              0x7fffffff);
+                              NGX_MAX_INT32_VALUE);
     ngx_conf_merge_uint_value(conf->client_body_in_file_only,
-                              prev->client_body_in_file_only, 0);
+                              prev->client_body_in_file_only,
+                              NGX_HTTP_REQUEST_BODY_FILE_OFF);
     ngx_conf_merge_value(conf->client_body_in_single_buffer,
                               prev->client_body_in_single_buffer, 0);
     ngx_conf_merge_value(conf->internal, prev->internal, 0);
@@ -3477,11 +3494,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
                               prev->sendfile_max_chunk, 0);
 #if (NGX_HAVE_FILE_AIO)
-    ngx_conf_merge_value(conf->aio, prev->aio, 0);
+    ngx_conf_merge_value(conf->aio, prev->aio, NGX_HTTP_AIO_OFF);
 #endif
     ngx_conf_merge_size_value(conf->read_ahead, prev->read_ahead, 0);
     ngx_conf_merge_off_value(conf->directio, prev->directio,
-                              NGX_MAX_OFF_T_VALUE);
+                              NGX_OPEN_FILE_DIRECTIO_OFF);
     ngx_conf_merge_off_value(conf->directio_alignment, prev->directio_alignment,
                               512);
     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
@@ -3839,13 +3856,6 @@ ngx_http_core_server_name(ngx_conf_t *cf
                                &value[i]);
         }
 
-        if (value[i].len == 1 && ch == '*') {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "\"server_name *\" is unsupported, use "
-                               "\"server_name_in_redirect off\" instead");
-            return NGX_CONF_ERROR;
-        }
-
         sn = ngx_array_push(&cscf->server_names);
         if (sn == NULL) {
             return NGX_CONF_ERROR;
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -529,5 +529,12 @@ extern ngx_str_t  ngx_http_core_get_meth
         r->headers_out.last_modified = NULL;                                  \
     }
 
+#define ngx_http_clear_location(r)                                            \
+                                                                              \
+    if (r->headers_out.location) {                                            \
+        r->headers_out.location->hash = 0;                                    \
+        r->headers_out.location = NULL;                                       \
+    }
+
 
 #endif /* _NGX_HTTP_CORE_H_INCLUDED_ */
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2248,17 +2248,17 @@ ngx_http_writer(ngx_http_request_t *r)
             return;
         }
 
-    } else {
-        if (wev->delayed || r->aio) {
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
-                           "http writer delayed");
-
-            if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
-                ngx_http_close_request(r, 0);
-            }
-
-            return;
+    }
+
+    if (wev->delayed || r->aio) {
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
+                       "http writer delayed");
+
+        if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
+            ngx_http_close_request(r, 0);
         }
+
+        return;
     }
 
     rc = ngx_http_output_filter(r, NULL);
@@ -2274,7 +2274,7 @@ ngx_http_writer(ngx_http_request_t *r)
 
     if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
 
-        if (!wev->ready && !wev->delayed) {
+        if (!wev->delayed) {
             ngx_add_timer(wev, clcf->send_timeout);
         }
 
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1106,6 +1106,8 @@ ngx_http_script_regex_end_code(ngx_http_
                           "rewritten redirect: \"%V\"", &e->buf);
         }
 
+        ngx_http_clear_location(r);
+
         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
         if (r->headers_out.location == NULL) {
             e->ip = ngx_http_script_exit;
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -375,7 +375,7 @@ ngx_http_special_response_handler(ngx_ht
         }
     }
 
-    if (r->lingering_close == 1) {
+    if (r->lingering_close) {
         switch (error) {
             case NGX_HTTP_BAD_REQUEST:
             case NGX_HTTP_TO_HTTPS:
@@ -582,6 +582,8 @@ ngx_http_send_error_page(ngx_http_reques
     ngx_str_set(&location->key, "Location");
     location->value = uri;
 
+    ngx_http_clear_location(r);
+
     r->headers_out.location = location;
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -369,6 +369,9 @@ ngx_conf_bitmask_t  ngx_http_upstream_ca
 ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[] = {
     { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
     { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
+    { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE },
+    { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING },
+    { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET },
     { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
     { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
     { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
@@ -999,7 +1002,7 @@ ngx_http_upstream_check_broken_connectio
 
         if (!u->cacheable && u->peer.connection) {
             ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
-                          "kevent() reported that client closed prematurely "
+                          "kevent() reported that client prematurely closed "
                           "connection, so upstream connection is closed too");
             ngx_http_upstream_finalize_request(r, u,
                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
@@ -1007,8 +1010,8 @@ ngx_http_upstream_check_broken_connectio
         }
 
         ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
-                      "kevent() reported that client closed "
-                      "prematurely connection");
+                      "kevent() reported that client prematurely closed "
+                      "connection");
 
         if (u->peer.connection == NULL) {
             ngx_http_upstream_finalize_request(r, u,
@@ -1062,7 +1065,7 @@ ngx_http_upstream_check_broken_connectio
 
     if (!u->cacheable && u->peer.connection) {
         ngx_log_error(NGX_LOG_INFO, ev->log, err,
-                      "client closed prematurely connection, "
+                      "client prematurely closed connection, "
                       "so upstream connection is closed too");
         ngx_http_upstream_finalize_request(r, u,
                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
@@ -1070,7 +1073,7 @@ ngx_http_upstream_check_broken_connectio
     }
 
     ngx_log_error(NGX_LOG_INFO, ev->log, err,
-                  "client closed prematurely connection");
+                  "client prematurely closed connection");
 
     if (u->peer.connection == NULL) {
         ngx_http_upstream_finalize_request(r, u,
@@ -3328,9 +3331,15 @@ static ngx_int_t
 ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
 {
-    ngx_int_t  n;
-
-    r->upstream->headers_in.x_accel_limit_rate = h;
+    ngx_int_t             n;
+    ngx_http_upstream_t  *u;
+
+    u = r->upstream;
+    u->headers_in.x_accel_limit_rate = h;
+
+    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE) {
+        return NGX_OK;
+    }
 
     n = ngx_atoi(h->value.data, h->value.len);
 
@@ -3346,16 +3355,23 @@ static ngx_int_t
 ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
 {
-    u_char  c0, c1, c2;
-
-    if (r->upstream->conf->change_buffering) {
+    u_char                c0, c1, c2;
+    ngx_http_upstream_t  *u;
+
+    u = r->upstream;
+
+    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING) {
+        return NGX_OK;
+    }
+
+    if (u->conf->change_buffering) {
 
         if (h->value.len == 2) {
             c0 = ngx_tolower(h->value.data[0]);
             c1 = ngx_tolower(h->value.data[1]);
 
             if (c0 == 'n' && c1 == 'o') {
-                r->upstream->buffering = 0;
+                u->buffering = 0;
             }
 
         } else if (h->value.len == 3) {
@@ -3364,7 +3380,7 @@ ngx_http_upstream_process_buffering(ngx_
             c2 = ngx_tolower(h->value.data[2]);
 
             if (c0 == 'y' && c1 == 'e' && c2 == 's') {
-                r->upstream->buffering = 1;
+                u->buffering = 1;
             }
         }
     }
@@ -3377,6 +3393,10 @@ static ngx_int_t
 ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
 {
+    if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) {
+        return NGX_OK;
+    }
+
     r->headers_out.override_charset = &h->value;
 
     return NGX_OK;
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -44,6 +44,9 @@
 #define NGX_HTTP_UPSTREAM_IGN_EXPIRES        0x00000008
 #define NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL  0x00000010
 #define NGX_HTTP_UPSTREAM_IGN_SET_COOKIE     0x00000020
+#define NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE  0x00000040
+#define NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING   0x00000080
+#define NGX_HTTP_UPSTREAM_IGN_XA_CHARSET     0x00000100
 
 
 typedef struct {
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -443,8 +443,8 @@ ngx_http_upstream_get_round_robin_peer(n
                             break;
                         }
 
-                        if (now - peer->accessed > peer->fail_timeout) {
-                            peer->fails = 0;
+                        if (now - peer->checked > peer->fail_timeout) {
+                            peer->checked = now;
                             break;
                         }
 
@@ -491,8 +491,8 @@ ngx_http_upstream_get_round_robin_peer(n
                             break;
                         }
 
-                        if (now - peer->accessed > peer->fail_timeout) {
-                            peer->fails = 0;
+                        if (now - peer->checked > peer->fail_timeout) {
+                            peer->checked = now;
                             break;
                         }
 
@@ -663,15 +663,16 @@ ngx_http_upstream_free_round_robin_peer(
         return;
     }
 
+    peer = &rrp->peers->peer[rrp->current];
+
     if (state & NGX_PEER_FAILED) {
         now = ngx_time();
 
-        peer = &rrp->peers->peer[rrp->current];
-
         /* ngx_lock_mutex(rrp->peers->mutex); */
 
         peer->fails++;
         peer->accessed = now;
+        peer->checked = now;
 
         if (peer->max_fails) {
             peer->current_weight -= peer->weight / peer->max_fails;
@@ -686,6 +687,14 @@ ngx_http_upstream_free_round_robin_peer(
         }
 
         /* ngx_unlock_mutex(rrp->peers->mutex); */
+
+    } else {
+
+        /* mark peer live if check passed */
+
+        if (peer->accessed < peer->checked) {
+            peer->fails = 0;
+        }
     }
 
     rrp->current++;
--- a/src/http/ngx_http_upstream_round_robin.h
+++ b/src/http/ngx_http_upstream_round_robin.h
@@ -23,6 +23,7 @@ typedef struct {
 
     ngx_uint_t                      fails;
     time_t                          accessed;
+    time_t                          checked;
 
     ngx_uint_t                      max_fails;
     time_t                          fail_timeout;