changeset 592:09d5f308901f NGINX_0_8_48

nginx 0.8.48 *) Change: now the "server_name" directive default value is an empty name "". Thanks to Gena Makhomed. *) Change: now the "server_name_in_redirect" directive default value is "off". *) Feature: the $geoip_dma_code, $geoip_area_code, and $geoip_region_name variables. Thanks to Christine McGonagle. *) Bugfix: the "proxy_pass", "fastcgi_pass", "uwsgi_pass", and "scgi_pass" directives were not inherited inside "limit_except" blocks. *) Bugfix: the "proxy_cache_min_uses", "fastcgi_cache_min_uses" "uwsgi_cache_min_uses", and "scgi_cache_min_uses" directives did not work; the bug had appeared in 0.8.46. *) Bugfix: the "fastcgi_split_path_info" directive used incorrectly captures, if only parts of an URI were captured. Thanks to Yuriy Taraday and Frank Enderle. *) Bugfix: the "rewrite" directive did not escape a ";" character during copying from URI to query string. Thanks to Daisuke Murase. *) Bugfix: the ngx_http_image_filter_module closed a connection, if an image was larger than "image_filter_buffer" size.
author Igor Sysoev <http://sysoev.ru>
date Tue, 03 Aug 2010 00:00:00 +0400
parents 8b891ad58d6a
children ad310549c5d4
files CHANGES CHANGES.ru src/core/nginx.h src/core/ngx_string.c src/event/ngx_event_openssl.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_geoip_module.c src/http/modules/ngx_http_image_filter_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_scgi_module.c src/http/modules/ngx_http_uwsgi_module.c src/http/modules/perl/nginx.pm src/http/ngx_http.c src/http/ngx_http_config.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_file_cache.c
diffstat 17 files changed, 363 insertions(+), 168 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,9 +1,42 @@
 
+Changes with nginx 0.8.48                                        03 Aug 2010
+
+    *) Change: now the "server_name" directive default value is an empty 
+       name "".
+       Thanks to Gena Makhomed.
+
+    *) Change: now the "server_name_in_redirect" directive default value is 
+       "off".
+
+    *) Feature: the $geoip_dma_code, $geoip_area_code, and 
+       $geoip_region_name variables.
+       Thanks to Christine McGonagle.
+
+    *) Bugfix: the "proxy_pass", "fastcgi_pass", "uwsgi_pass", and 
+       "scgi_pass" directives were not inherited inside "limit_except" 
+       blocks.
+
+    *) Bugfix: the "proxy_cache_min_uses", "fastcgi_cache_min_uses" 
+       "uwsgi_cache_min_uses", and "scgi_cache_min_uses" directives did not 
+       work; the bug had appeared in 0.8.46.
+
+    *) Bugfix: the "fastcgi_split_path_info" directive used incorrectly 
+       captures, if only parts of an URI were captured.
+       Thanks to Yuriy Taraday and Frank Enderle.
+
+    *) Bugfix: the "rewrite" directive did not escape a ";" character 
+       during copying from URI to query string.
+       Thanks to Daisuke Murase.
+
+    *) Bugfix: the ngx_http_image_filter_module closed a connection, if an 
+       image was larger than "image_filter_buffer" size.
+
+
 Changes with nginx 0.8.47                                        28 Jul 2010
 
     *) Bugfix: $request_time variable had invalid values for subrequests.
 
-    *) Bugfix: errors intercepted by error_page could be cached.
+    *) Bugfix: errors intercepted by error_page could not be cached.
 
     *) Bugfix: a cache manager process my got caught in an endless loop, if 
        max_size parameter was used; the bug had appeared in 0.8.46.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,36 @@
 
+Изменения в nginx 0.8.48                                          03.08.2010
+
+    *) Изменение: теперь по умолчанию директива server_name имеет значение 
+       пустое имя "".
+       Спасибо Геннадию Махомеду.
+
+    *) Изменение: теперь по умолчанию директива server_name_in_redirect 
+       имеет значение off.
+
+    *) Добавление: переменные $geoip_dma_code, $geoip_area_code и 
+       $geoip_region_name.
+       Спасибо Christine McGonagle.
+
+    *) Исправление: директивы proxy_pass, fastcgi_pass, uwsgi_pass и 
+       scgi_pass не наследовались в блоки limit_except.
+
+    *) Исправление: директивы proxy_cache_min_uses, fastcgi_cache_min_uses 
+       uwsgi_cache_min_uses и scgi_cache_min_uses не работали; ошибка 
+       появилась в 0.8.46.
+
+    *) Исправление: директива fastcgi_split_path_info неверно использовала 
+       выделения, если в выделения попадала только часть URI.
+       Спасибо Юрию Тарадаю и Frank Enderle.
+
+    *) Исправление: директива rewrite не экранировала символ ";" при 
+       копировании из URI в аргументы. 
+       Спасибо Daisuke Murase.
+
+    *) Исправление: модуль ngx_http_image_filter_module закрывал 
+       соединение, если изображение было больше размера image_filter_buffer.
+
+
 Изменения в nginx 0.8.47                                          28.07.2010
 
     *) Исправление: переменная $request_time имела неверные значения для 
@@ -7,7 +39,7 @@
     *) Исправление: ошибки, перехваченные error_page, не кэшировались.
 
     *) Исправление: если использовался параметр max_size, то cache manager 
-       мог зациклиться. ошибка появилась в 0.8.46.
+       мог зациклиться; ошибка появилась в 0.8.46.
 
 
 Изменения в nginx 0.8.46                                          19.07.2010
@@ -1922,7 +1954,7 @@
 
     *) Исправление: nginx неверно определял длину строки кэша на 
        Pentium 4.
-       Спасибо Gena Makhomed.
+       Спасибо Геннадию Махомеду.
 
     *) Исправление: в проксированных подзапросах и подзапросах к 
        FastCGI-серверу вместо метода GET использовался оригинальный метод 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8047
-#define NGINX_VERSION      "0.8.47"
+#define nginx_version         8048
+#define NGINX_VERSION      "0.8.48"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1329,7 +1329,7 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
 
                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
-        0x80000869, /* 1000 0000 0000 0000  0000 1000 0110 1001 */
+        0x88000869, /* 1000 1000 0000 0000  0000 1000 0110 1001 */
 
                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1312,7 +1312,8 @@ ngx_ssl_connection_error(ngx_connection_
         n = ERR_GET_REASON(ERR_peek_error());
 
             /* handshake failures */
-        if (n == SSL_R_DIGEST_CHECK_FAILED                           /*  149 */
+        if (n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                     /*  129 */
+            || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
             || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
             || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -310,14 +310,14 @@ static ngx_command_t  ngx_http_fastcgi_c
 #if (NGX_HTTP_CACHE)
 
     { ngx_string("fastcgi_cache"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_fastcgi_cache,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
       NULL },
 
     { ngx_string("fastcgi_cache_key"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_fastcgi_cache_key,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -410,14 +410,14 @@ static ngx_command_t  ngx_http_fastcgi_c
       NULL },
 
     { ngx_string("fastcgi_pass_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers),
       NULL },
 
     { ngx_string("fastcgi_hide_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
@@ -2025,6 +2025,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
     ngx_keyval_t                 *src;
     ngx_hash_key_t               *hk;
     ngx_hash_init_t               hash;
+    ngx_http_core_loc_conf_t     *clcf;
     ngx_http_script_compile_t     sc;
     ngx_http_script_copy_code_t  *copy;
 
@@ -2270,6 +2271,13 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
         conf->fastcgi_values = prev->fastcgi_values;
     }
 
+    if (conf->upstream.upstream || conf->fastcgi_lengths) {
+        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+        if (clcf->handler == NULL && clcf->lmt_excpt) {
+            clcf->handler = ngx_http_fastcgi_handler;
+        }
+    }
+
 #if (NGX_PCRE)
     if (conf->split_regex == NULL) {
         conf->split_regex = prev->split_regex;
@@ -2558,10 +2566,10 @@ ngx_http_fastcgi_split(ngx_http_request_
 
     if (n >= 0) { /* match */
         f->script_name.len = captures[3] - captures[2];
-        f->script_name.data = r->uri.data;
+        f->script_name.data = r->uri.data + captures[2];
 
         f->path_info.len = captures[5] - captures[4];
-        f->path_info.data = r->uri.data + f->script_name.len;
+        f->path_info.data = r->uri.data + captures[4];
 
         return f;
     }
--- a/src/http/modules/ngx_http_geoip_module.c
+++ b/src/http/modules/ngx_http_geoip_module.c
@@ -30,8 +30,12 @@ static ngx_int_t ngx_http_geoip_country_
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
 
 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
@@ -128,6 +132,10 @@ static ngx_http_variable_t  ngx_http_geo
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, region), 0, 0 },
 
+    { ngx_string("geoip_region_name"), NULL,
+      ngx_http_geoip_region_name_variable,
+      0, 0, 0 },
+
     { ngx_string("geoip_city"), NULL,
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, city), 0, 0 },
@@ -144,6 +152,14 @@ static ngx_http_variable_t  ngx_http_geo
       ngx_http_geoip_city_float_variable,
       offsetof(GeoIPRecord, longitude), 0, 0 },
 
+    { ngx_string("geoip_dma_code"), NULL,
+      ngx_http_geoip_city_int_variable,
+      offsetof(GeoIPRecord, dma_code), 0, 0 },
+
+    { ngx_string("geoip_area_code"), NULL,
+      ngx_http_geoip_city_int_variable,
+      offsetof(GeoIPRecord, area_code), 0, 0 },
+
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -245,6 +261,48 @@ not_found:
 
 
 static ngx_int_t
+ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    size_t        len;
+    const char   *val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        goto not_found;
+    }
+
+    val = GeoIP_region_name_by_code(gr->country_code, gr->region);
+
+    len = ngx_strlen(val);
+    v->data = ngx_pnalloc(r->pool, len);
+
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    ngx_memcpy(v->data, val, len);
+
+    v->len = len;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+
+    GeoIPRecord_delete(gr);
+
+    return NGX_OK;
+
+not_found:
+
+    v->not_found = 1;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
@@ -273,6 +331,35 @@ ngx_http_geoip_city_float_variable(ngx_h
 }
 
 
+static ngx_int_t
+ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    int           val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN);
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    val = *(int *) ((char *) gr + data);
+
+    v->len = ngx_sprintf(v->data, "%d", val) - v->data;
+
+    GeoIPRecord_delete(gr);
+
+    return NGX_OK;
+}
+
+
 static GeoIPRecord *
 ngx_http_geoip_get_city_record(ngx_http_request_t *r)
 {
--- a/src/http/modules/ngx_http_image_filter_module.c
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -228,7 +228,7 @@ ngx_http_image_header_filter(ngx_http_re
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "image filter: too big response: %O", len);
 
-        return NGX_ERROR;
+        return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
     }
 
     if (len == -1) {
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -319,14 +319,14 @@ static ngx_command_t  ngx_http_proxy_com
 #if (NGX_HTTP_CACHE)
 
     { ngx_string("proxy_cache"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_proxy_cache,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
       NULL },
 
     { ngx_string("proxy_cache_key"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_proxy_cache_key,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -412,14 +412,14 @@ static ngx_command_t  ngx_http_proxy_com
       &ngx_http_proxy_next_upstream_masks },
 
     { ngx_string("proxy_pass_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers),
       NULL },
 
     { ngx_string("proxy_hide_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
@@ -572,7 +572,7 @@ ngx_http_proxy_handler(ngx_http_request_
 
     u = r->upstream;
 
-    if (plcf->proxy_lengths == 0) {
+    if (plcf->proxy_lengths == NULL) {
         ctx->vars = plcf->vars;
         u->schema = plcf->vars.schema;
 #if (NGX_HTTP_SSL)
@@ -1720,6 +1720,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
     size_t                      size;
     ngx_keyval_t               *s;
     ngx_hash_init_t             hash;
+    ngx_http_core_loc_conf_t   *clcf;
     ngx_http_proxy_redirect_t  *pr;
     ngx_http_script_compile_t   sc;
 
@@ -1985,12 +1986,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
         }
     }
 
-    /* STUB */
-    if (prev->proxy_lengths) {
-        conf->proxy_lengths = prev->proxy_lengths;
-        conf->proxy_values = prev->proxy_values;
-    }
-
 #if (NGX_HTTP_SSL)
     if (conf->upstream.ssl == NULL) {
         conf->upstream.ssl = prev->upstream.ssl;
@@ -2022,6 +2017,18 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
         conf->vars = prev->vars;
     }
 
+    if (conf->proxy_lengths == NULL) {
+        conf->proxy_lengths = prev->proxy_lengths;
+        conf->proxy_values = prev->proxy_values;
+    }
+
+    if (conf->upstream.upstream || conf->proxy_lengths) {
+        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+        if (clcf->handler == NULL && clcf->lmt_excpt) {
+            clcf->handler = ngx_http_proxy_handler;
+            conf->location = prev->location;
+        }
+    }
 
     if (conf->body_source.data == NULL) {
         conf->body_source = prev->body_source;
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -176,14 +176,14 @@ static ngx_command_t ngx_http_scgi_comma
 #if (NGX_HTTP_CACHE)
 
     { ngx_string("scgi_cache"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_scgi_cache,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
       NULL },
 
     { ngx_string("scgi_cache_key"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_scgi_cache_key,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -276,14 +276,14 @@ static ngx_command_t ngx_http_scgi_comma
       NULL },
 
     { ngx_string("scgi_pass_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_scgi_loc_conf_t, upstream.pass_headers),
       NULL },
 
     { ngx_string("scgi_hide_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_scgi_loc_conf_t, upstream.hide_headers),
@@ -1053,6 +1053,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t 
     ngx_keyval_t                 *src;
     ngx_hash_key_t               *hk;
     ngx_hash_init_t               hash;
+    ngx_http_core_loc_conf_t     *clcf;
     ngx_http_script_compile_t     sc;
     ngx_http_script_copy_code_t  *copy;
 
@@ -1285,6 +1286,13 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t 
         conf->scgi_values = prev->scgi_values;
     }
 
+    if (conf->upstream.upstream || conf->scgi_lengths) {
+        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+        if (clcf->handler == NULL && clcf->lmt_excpt) {
+            clcf->handler = ngx_http_scgi_handler;
+        }
+    }
+
     if (conf->params_source == NULL) {
         conf->flushes = prev->flushes;
         conf->params_len = prev->params_len;
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -203,14 +203,14 @@ static ngx_command_t ngx_http_uwsgi_comm
 #if (NGX_HTTP_CACHE)
 
     { ngx_string("uwsgi_cache"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_uwsgi_cache,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
       NULL },
 
     { ngx_string("uwsgi_cache_key"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_uwsgi_cache_key,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -310,14 +310,14 @@ static ngx_command_t ngx_http_uwsgi_comm
       NULL },
 
     { ngx_string("uwsgi_pass_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_headers),
       NULL },
 
     { ngx_string("uwsgi_hide_header"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.hide_headers),
@@ -1106,6 +1106,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t
     ngx_keyval_t                 *src;
     ngx_hash_key_t               *hk;
     ngx_hash_init_t               hash;
+    ngx_http_core_loc_conf_t     *clcf;
     ngx_http_script_compile_t     sc;
     ngx_http_script_copy_code_t  *copy;
 
@@ -1340,6 +1341,13 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t
         conf->uwsgi_values = prev->uwsgi_values;
     }
 
+    if (conf->upstream.upstream || conf->uwsgi_lengths) {
+        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+        if (clcf->handler == NULL && clcf->lmt_excpt) {
+            clcf->handler = ngx_http_uwsgi_handler;
+        }
+    }
+
     ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0);
     ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0);
 
--- 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 = '0.8.47';
+our $VERSION = '0.8.48';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -26,6 +26,9 @@ static ngx_int_t ngx_http_add_address(ng
 static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
 
+static char *ngx_http_merge_servers(ngx_conf_t *cf,
+    ngx_http_core_main_conf_t *cmcf, ngx_http_module_t *module,
+    ngx_uint_t ctx_index);
 static char *ngx_http_merge_locations(ngx_conf_t *cf,
     ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
     ngx_uint_t ctx_index);
@@ -263,39 +266,9 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
             }
         }
 
-        for (s = 0; s < cmcf->servers.nelts; s++) {
-
-            /* merge the server{}s' srv_conf's */
-
-            if (module->merge_srv_conf) {
-                rv = module->merge_srv_conf(cf, ctx->srv_conf[mi],
-                                            cscfp[s]->ctx->srv_conf[mi]);
-                if (rv != NGX_CONF_OK) {
-                    goto failed;
-                }
-            }
-
-            if (module->merge_loc_conf) {
-
-                /* merge the server{}'s loc_conf */
-
-                rv = module->merge_loc_conf(cf, ctx->loc_conf[mi],
-                                            cscfp[s]->ctx->loc_conf[mi]);
-                if (rv != NGX_CONF_OK) {
-                    goto failed;
-                }
-
-                /* merge the locations{}' loc_conf's */
-
-                clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
-
-                rv = ngx_http_merge_locations(cf, clcf->locations,
-                                              cscfp[s]->ctx->loc_conf,
-                                              module, mi);
-                if (rv != NGX_CONF_OK) {
-                    goto failed;
-                }
-            }
+        rv = ngx_http_merge_servers(cf, cmcf, module, mi);
+        if (rv != NGX_CONF_OK) {
+            goto failed;
         }
     }
 
@@ -586,11 +559,74 @@ ngx_http_init_phase_handlers(ngx_conf_t 
 
 
 static char *
+ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
+    ngx_http_module_t *module, ngx_uint_t ctx_index)
+{
+    char                        *rv;
+    ngx_uint_t                   s;
+    ngx_http_conf_ctx_t         *ctx, saved;
+    ngx_http_core_loc_conf_t    *clcf;
+    ngx_http_core_srv_conf_t   **cscfp;
+
+    cscfp = cmcf->servers.elts;
+    ctx = (ngx_http_conf_ctx_t *) cf->ctx;
+    saved = *ctx;
+    rv = NGX_CONF_OK;
+
+    for (s = 0; s < cmcf->servers.nelts; s++) {
+
+        /* merge the server{}s' srv_conf's */
+
+        ctx->srv_conf = cscfp[s]->ctx->srv_conf;
+
+        if (module->merge_srv_conf) {
+            rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
+                                        cscfp[s]->ctx->srv_conf[ctx_index]);
+            if (rv != NGX_CONF_OK) {
+                goto failed;
+            }
+        }
+
+        if (module->merge_loc_conf) {
+
+            /* merge the server{}'s loc_conf */
+
+            ctx->loc_conf = cscfp[s]->ctx->loc_conf;
+
+            rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
+                                        cscfp[s]->ctx->loc_conf[ctx_index]);
+            if (rv != NGX_CONF_OK) {
+                goto failed;
+            }
+
+            /* merge the locations{}' loc_conf's */
+
+            clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
+
+            rv = ngx_http_merge_locations(cf, clcf->locations,
+                                          cscfp[s]->ctx->loc_conf,
+                                          module, ctx_index);
+            if (rv != NGX_CONF_OK) {
+                goto failed;
+            }
+        }
+    }
+
+failed:
+
+    *ctx = saved;
+
+    return rv;
+}
+
+
+static char *
 ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
     void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
 {
     char                       *rv;
     ngx_queue_t                *q;
+    ngx_http_conf_ctx_t        *ctx, saved;
     ngx_http_core_loc_conf_t   *clcf;
     ngx_http_location_queue_t  *lq;
 
@@ -598,6 +634,9 @@ ngx_http_merge_locations(ngx_conf_t *cf,
         return NGX_CONF_OK;
     }
 
+    ctx = (ngx_http_conf_ctx_t *) cf->ctx;
+    saved = *ctx;
+
     for (q = ngx_queue_head(locations);
          q != ngx_queue_sentinel(locations);
          q = ngx_queue_next(q))
@@ -605,6 +644,7 @@ ngx_http_merge_locations(ngx_conf_t *cf,
         lq = (ngx_http_location_queue_t *) q;
 
         clcf = lq->exact ? lq->exact : lq->inclusive;
+        ctx->loc_conf = clcf->loc_conf;
 
         rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
                                     clcf->loc_conf[ctx_index]);
@@ -619,6 +659,8 @@ ngx_http_merge_locations(ngx_conf_t *cf,
         }
     }
 
+    *ctx = saved;
+
     return NGX_CONF_OK;
 }
 
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -56,10 +56,6 @@ typedef struct {
 #define ngx_http_get_module_srv_conf(r, module)  (r)->srv_conf[module.ctx_index]
 #define ngx_http_get_module_loc_conf(r, module)  (r)->loc_conf[module.ctx_index]
 
-/*
- * ngx_http_conf_get_module_srv_conf() and ngx_http_conf_get_module_loc_conf()
- * must not be used at the merge phase because cf->ctx points to http{}'s ctx
- */
 
 #define ngx_http_conf_get_module_main_conf(cf, module)                        \
     ((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -3011,7 +3011,7 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 
     }
 
     if (conf->server_name.data == NULL) {
-        conf->server_name = cf->cycle->hostname;
+        ngx_str_set(&conf->server_name, "");
 
         sn = ngx_array_push(&conf->server_names);
         if (sn == NULL) {
@@ -3022,8 +3022,7 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 
         sn->regex = NULL;
 #endif
         sn->server = conf;
-        sn->name.len = conf->server_name.len;
-        sn->name.data = conf->server_name.data;
+        ngx_str_set(&sn->name, "");
     }
 
     return NGX_CONF_OK;
@@ -3331,7 +3330,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
     ngx_conf_merge_value(conf->reset_timedout_connection,
                               prev->reset_timedout_connection, 0);
     ngx_conf_merge_value(conf->server_name_in_redirect,
-                              prev->server_name_in_redirect, 1);
+                              prev->server_name_in_redirect, 0);
     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
@@ -3609,23 +3608,16 @@ ngx_http_core_server_name(ngx_conf_t *cf
     ch = value[1].data[0];
 
     if (cscf->server_name.data == NULL) {
-        if (value[1].len) {
-            name = value[1];
-
-            if (ch == '.') {
-                name.len--;
-                name.data++;
-            }
-
-            cscf->server_name.len = name.len;
-            cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
-            if (cscf->server_name.data == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-        } else {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "the first server name must not be empty");
+        name = value[1];
+
+        if (ch == '.') {
+            name.len--;
+            name.data++;
+        }
+
+        cscf->server_name.len = name.len;
+        cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
+        if (cscf->server_name.data == NULL) {
             return NGX_CONF_ERROR;
         }
     }
@@ -3916,6 +3908,7 @@ ngx_http_core_limit_except(ngx_conf_t *c
     clcf->loc_conf = ctx->loc_conf;
     clcf->name = pclcf->name;
     clcf->noname = 1;
+    clcf->lmt_excpt = 1;
 
     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
         return NGX_CONF_ERROR;
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -286,6 +286,7 @@ struct ngx_http_core_loc_conf_s {
 #endif
 
     unsigned      noname:1;   /* "if () {}" block or limit_except */
+    unsigned      lmt_excpt:1;
     unsigned      named:1;
 
     unsigned      exact_match:1;
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -368,8 +368,6 @@ ngx_http_file_cache_read(ngx_http_reques
     ngx_http_file_cache_t         *cache;
     ngx_http_file_cache_header_t  *h;
 
-    c = r->cache;
-
     n = ngx_http_file_cache_aio_read(r, c);
 
     if (n < 0) {
@@ -519,6 +517,9 @@ ngx_http_file_cache_exists(ngx_http_file
     if (fcn) {
         ngx_queue_remove(&fcn->queue);
 
+        fcn->uses++;
+        fcn->count++;
+
         if (fcn->error) {
 
             if (fcn->valid_sec < ngx_time()) {
@@ -530,9 +531,6 @@ ngx_http_file_cache_exists(ngx_http_file
             goto done;
         }
 
-        fcn->uses++;
-        fcn->count++;
-
         if (fcn->exists) {
 
             c->exists = fcn->exists;
@@ -581,12 +579,13 @@ ngx_http_file_cache_exists(ngx_http_file
 
     ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
 
+    fcn->uses = 1;
+    fcn->count = 1;
+
 renew:
 
     rc = NGX_DECLINED;
 
-    fcn->uses = 1;
-    fcn->count = 1;
     fcn->valid_msec = 0;
     fcn->error = 0;
     fcn->exists = 0;
@@ -932,7 +931,7 @@ ngx_http_file_cache_free(ngx_http_cache_
         fcn->valid_msec = c->valid_msec;
         fcn->error = c->error;
 
-    } else if (!fcn->exists && fcn->count == 0) {
+    } else if (!fcn->exists && fcn->count == 0 && c->min_uses == 1) {
         ngx_queue_remove(&fcn->queue);
         ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
         ngx_slab_free_locked(cache->shpool, fcn);
@@ -1006,7 +1005,7 @@ ngx_http_file_cache_forced_expire(ngx_ht
     ngx_memcpy(name, path->name.data, path->name.len);
 
     wait = 10;
-    tries = 0;
+    tries = 20;
 
     ngx_shmtx_lock(&cache->shpool->mutex);
 
@@ -1021,28 +1020,17 @@ ngx_http_file_cache_forced_expire(ngx_ht
                   fcn->count, fcn->exists,
                   fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);
 
-        if (fcn->count) {
+        if (fcn->count == 0) {
+            ngx_http_file_cache_delete(cache, q, name);
 
-            if (tries++ < 20) {
+        } else {
+            if (--tries) {
                 continue;
             }
 
             wait = 1;
-
-            break;
         }
 
-        if (!fcn->exists) {
-
-            ngx_queue_remove(q);
-            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
-            ngx_slab_free_locked(cache->shpool, fcn);
-
-            break;
-        }
-
-        ngx_http_file_cache_delete(cache, q, name);
-
         break;
     }
 
@@ -1105,41 +1093,29 @@ ngx_http_file_cache_expire(ngx_http_file
                        fcn->count, fcn->exists,
                        fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);
 
-        if (fcn->count) {
-
-            p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
-                             sizeof(ngx_rbtree_key_t));
-
-            len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
-            (void) ngx_hex_dump(p, fcn->key, len);
-
-            /*
-             * 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
-             */
-
-            ngx_queue_remove(q);
-            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
-
-            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
-                       "ignore long locked inactive cache entry %*s, count:%d",
-                       2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
-
+        if (fcn->count == 0) {
+            ngx_http_file_cache_delete(cache, q, name);
             continue;
         }
 
-        if (!fcn->exists) {
+        p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
+                         sizeof(ngx_rbtree_key_t));
+        len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
+        (void) ngx_hex_dump(p, fcn->key, len);
 
-            ngx_queue_remove(q);
-            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
-            ngx_slab_free_locked(cache->shpool, fcn);
+        /*
+         * 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
+         */
 
-            continue;
-        }
+        ngx_queue_remove(q);
+        ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
 
-        ngx_http_file_cache_delete(cache, q, name);
+        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+                      "ignore long locked inactive cache entry %*s, count:%d",
+                      2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
     }
 
     ngx_shmtx_unlock(&cache->shpool->mutex);
@@ -1161,37 +1137,40 @@ ngx_http_file_cache_delete(ngx_http_file
 
     fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
 
-    cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
-
-    path = cache->path;
-
-    p = name + path->name.len + 1 + path->len;
+    if (fcn->exists) {
+        cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
 
-    p = ngx_hex_dump(p, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t));
+        path = cache->path;
+        p = name + path->name.len + 1 + path->len;
+        p = ngx_hex_dump(p, (u_char *) &fcn->node.key,
+                         sizeof(ngx_rbtree_key_t));
+        len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
+        p = ngx_hex_dump(p, fcn->key, len);
+        *p = '\0';
 
-    len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
-    p = ngx_hex_dump(p, fcn->key, len);
-    *p = '\0';
+        fcn->count++;
+        ngx_shmtx_unlock(&cache->shpool->mutex);
 
-    ngx_queue_remove(q);
-    ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
-    ngx_slab_free_locked(cache->shpool, fcn);
+        len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;
+        ngx_create_hashed_filename(path, name, len);
 
-    ngx_shmtx_unlock(&cache->shpool->mutex);
-
-    len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
+                       "http file cache expire: \"%s\"", name);
 
-    ngx_create_hashed_filename(path, name, len);
+        if (ngx_delete_file(name) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
+                          ngx_delete_file_n " \"%s\" failed", name);
+        }
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
-                   "http file cache expire: \"%s\"", name);
-
-    if (ngx_delete_file(name) == NGX_FILE_ERROR) {
-        ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
-                      ngx_delete_file_n " \"%s\" failed", name);
+        ngx_shmtx_lock(&cache->shpool->mutex);
+        fcn->count--;
     }
 
-    ngx_shmtx_lock(&cache->shpool->mutex);
+    if (fcn->count == 0) {
+        ngx_queue_remove(q);
+        ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
+        ngx_slab_free_locked(cache->shpool, fcn);
+    }
 }