diff src/http/ngx_http_core_module.c @ 632:5b73504dd4ba NGINX_1_1_0

nginx 1.1.0 *) Feature: cache loader run time decrease. *) Feature: "loader_files", "loader_sleep", and "loader_threshold" options of the "proxy/fastcgi/scgi/uwsgi_cache_path" directives. *) Feature: loading time decrease of configuration with large number of HTTPS sites. *) Feature: now nginx supports ECDHE key exchange ciphers. Thanks to Adrian Kotelba. *) Feature: the "lingering_close" directive. Thanks to Maxim Dounin. *) Bugfix: in closing connection for pipelined requests. Thanks to Maxim Dounin. *) Bugfix: nginx did not disable gzipping if client sent "gzip;q=0" in "Accept-Encoding" request header line. *) Bugfix: in timeout in unbuffered proxied mode. Thanks to Maxim Dounin. *) Bugfix: memory leaks when a "proxy_pass" directive contains variables and proxies to an HTTPS backend. Thanks to Maxim Dounin. *) Bugfix: in parameter validaiton of a "proxy_pass" directive with variables. Thanks to Lanshun Zhou. *) Bugfix: SSL did not work on QNX. Thanks to Maxim Dounin. *) Bugfix: SSL modules could not be built by gcc 4.6 without --with-debug option.
author Igor Sysoev <http://sysoev.ru>
date Mon, 01 Aug 2011 00:00:00 +0400
parents 8dc007eddbcf
children 23ef0645ea57
line wrap: on
line diff
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -70,6 +70,7 @@ static char *ngx_http_core_internal(ngx_
 static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 #if (NGX_HTTP_GZIP)
+static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);
 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 #endif
@@ -125,6 +126,14 @@ static ngx_conf_enum_t  ngx_http_core_sa
 };
 
 
+static ngx_conf_enum_t  ngx_http_core_lingering_close[] = {
+    { ngx_string("off"), NGX_HTTP_LINGERING_OFF },
+    { ngx_string("on"), NGX_HTTP_LINGERING_ON },
+    { ngx_string("always"), NGX_HTTP_LINGERING_ALWAYS },
+    { ngx_null_string, 0 }
+};
+
+
 static ngx_conf_enum_t  ngx_http_core_if_modified_since[] = {
     { ngx_string("off"), NGX_HTTP_IMS_OFF },
     { ngx_string("exact"), NGX_HTTP_IMS_EXACT },
@@ -530,6 +539,13 @@ static ngx_command_t  ngx_http_core_comm
       0,
       NULL },
 
+    { ngx_string("lingering_close"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, lingering_close),
+      &ngx_http_core_lingering_close },
+
     { ngx_string("lingering_time"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
@@ -2016,24 +2032,35 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
     time_t                     date, expires;
     ngx_uint_t                 p;
     ngx_array_t               *cc;
-    ngx_table_elt_t           *e, *d;
+    ngx_table_elt_t           *e, *d, *ae;
     ngx_http_core_loc_conf_t  *clcf;
 
     r->gzip_tested = 1;
 
-    if (r != r->main
-        || r->headers_in.accept_encoding == NULL
-        || ngx_strcasestrn(r->headers_in.accept_encoding->value.data,
-                           "gzip", 4 - 1)
-           == NULL
-
-        /*
-         * if the URL (without the "http://" prefix) is longer than 253 bytes,
-         * then MSIE 4.x can not handle the compressed stream - it waits
-         * too long, hangs up or crashes
-         */
-
-        || (r->headers_in.msie4 && r->unparsed_uri.len > 200))
+    if (r != r->main) {
+        return NGX_DECLINED;
+    }
+
+    ae = r->headers_in.accept_encoding;
+    if (ae == NULL) {
+        return NGX_DECLINED;
+    }
+
+    if (ae->value.len < sizeof("gzip") - 1) {
+        return NGX_DECLINED;
+    }
+
+    /*
+     * test first for the most common case "gzip,...":
+     *   MSIE:    "gzip, deflate"
+     *   Firefox: "gzip,deflate"
+     *   Chrome:  "gzip,deflate,sdch"
+     *   Safari:  "gzip, deflate"
+     *   Opera:   "gzip, deflate"
+     */
+
+    if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0
+        && ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)
     {
         return NGX_DECLINED;
     }
@@ -2159,6 +2186,127 @@ ok:
     return NGX_OK;
 }
 
+
+/*
+ * gzip is enabled for the following quantities:
+ *     "gzip; q=0.001" ... "gzip; q=0.999", "gzip; q=1"
+ * gzip is disabled for the following quantities:
+ *     "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases
+ */
+
+static ngx_int_t
+ngx_http_gzip_accept_encoding(ngx_str_t *ae)
+{
+    u_char      c, *p, *start, *last;
+    ngx_uint_t  n, q;
+
+    start = ae->data;
+    last = start + ae->len;
+
+    for ( ;; ) {
+        p = ngx_strcasestrn(start, "gzip", 4 - 1);
+        if (p == NULL) {
+            return NGX_DECLINED;
+        }
+
+        if (p == start || (*(p - 1) == ',' || *(p - 1) == ' ')) {
+            break;
+        }
+
+        start = p + 4;
+    }
+
+    p += 4;
+
+    while (p < last) {
+        switch(*p++) {
+        case ',':
+            return NGX_OK;
+        case ';':
+            goto quantity;
+        case ' ':
+            continue;
+        default:
+            return NGX_DECLINED;
+        }
+    }
+
+    return NGX_OK;
+
+quantity:
+
+    while (p < last) {
+        switch(*p++) {
+        case 'q':
+        case 'Q':
+            goto equal;
+        case ' ':
+            continue;
+        default:
+            return NGX_DECLINED;
+        }
+    }
+
+    return NGX_OK;
+
+equal:
+
+    if (p + 2 > last || *p++ != '=') {
+        return NGX_DECLINED;
+    }
+
+    c = *p++;
+
+    if (c == '1') {
+        if (p == last || *p == ',' || *p == ' ') {
+            return NGX_OK;
+        }
+        return NGX_DECLINED;
+    }
+
+    if (c != '0') {
+        return NGX_DECLINED;
+    }
+
+    if (p == last) {
+        return NGX_DECLINED;
+    }
+
+    if (*p++ != '.') {
+        return NGX_DECLINED;
+    }
+
+    n = 0;
+    q = 0;
+
+    while (p < last) {
+        c = *p++;
+
+        if (c == ',') {
+            break;
+        }
+
+        if (c >= '1' && c <= '9') {
+            n++;
+            q++;
+            continue;
+        }
+
+        if (c == '0') {
+            n++;
+            continue;
+        }
+
+        return NGX_DECLINED;
+    }
+
+    if (n < 4 && q != 0) {
+        return NGX_OK;
+    }
+
+    return NGX_DECLINED;
+}
+
 #endif
 
 
@@ -3117,6 +3265,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
     clcf->keepalive_header = NGX_CONF_UNSET;
     clcf->keepalive_requests = NGX_CONF_UNSET_UINT;
+    clcf->lingering_close = NGX_CONF_UNSET_UINT;
     clcf->lingering_time = NGX_CONF_UNSET_MSEC;
     clcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
     clcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
@@ -3333,6 +3482,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
                               prev->keepalive_header, 0);
     ngx_conf_merge_uint_value(conf->keepalive_requests,
                               prev->keepalive_requests, 100);
+    ngx_conf_merge_msec_value(conf->lingering_close,
+                              prev->lingering_close, NGX_HTTP_LINGERING_ON);
     ngx_conf_merge_msec_value(conf->lingering_time,
                               prev->lingering_time, 30000);
     ngx_conf_merge_msec_value(conf->lingering_timeout,