Merge branch 'nginx' (nginx-1.17.0).

Change-Id: I6b716497d5213cf48a9323590f3cb6b70c044339
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags
index 910104d..5dd625b 100644
--- a/.hgtags
+++ b/.hgtags
@@ -438,3 +438,4 @@
 75f5c7f628411c79c7044102049f7ab4f7a246e7 release-1.15.10
 5155d0296a5ef9841f035920527ffdb771076b44 release-1.15.11
 0130ca3d58437b3c7c707cdddd813d530c68da9a release-1.15.12
+054c1c46395caff79bb4caf16f40b331f71bb6dd release-1.17.0
diff --git a/BUILD b/BUILD
index aec97eb..076b3b4 100644
--- a/BUILD
+++ b/BUILD
@@ -399,6 +399,7 @@
         "src/http/ngx_http_file_cache.c",
         "src/http/ngx_http_header_filter_module.c",
         "src/http/ngx_http_parse.c",
+        "src/http/ngx_http_postpone_filter_module.c",
         "src/http/ngx_http_request.c",
         "src/http/ngx_http_request.h",
         "src/http/ngx_http_request_body.c",
@@ -473,7 +474,6 @@
     deps = [
         ":core",
         ":http",
-        ":http_postpone",
     ],
 )
 
@@ -780,21 +780,6 @@
 )
 
 cc_library(
-    name = "http_postpone",
-    srcs = [
-        "src/http/ngx_http_postpone_filter_module.c",
-    ],
-    copts = nginx_copts,
-    defines = [
-        "NGX_HTTP_POSTPONE",
-    ],
-    deps = [
-        ":core",
-        ":http",
-    ],
-)
-
-cc_library(
     name = "http_proxy",
     srcs = [
         "src/http/modules/ngx_http_proxy_module.c",
@@ -911,7 +896,6 @@
     deps = [
         ":core",
         ":http",
-        ":http_postpone",
     ],
 )
 
@@ -945,7 +929,6 @@
     deps = [
         ":core",
         ":http",
-        ":http_postpone",
     ],
 )
 
@@ -1537,5 +1520,5 @@
     preinst = "@nginx_pkgoss//:debian_preinst",
     prerm = "@nginx_pkgoss//:debian_prerm",
     section = "httpd",
-    version = "1.15.12",
+    version = "1.17.0",
 )
diff --git a/auto/modules b/auto/modules
index 846028c..ac662a2 100644
--- a/auto/modules
+++ b/auto/modules
@@ -102,21 +102,6 @@
     fi
 
 
-    if [ $HTTP_SSI = YES ]; then
-        HTTP_POSTPONE=YES
-    fi
-
-
-    if [ $HTTP_SLICE = YES ]; then
-        HTTP_POSTPONE=YES
-    fi
-
-
-    if [ $HTTP_ADDITION = YES ]; then
-        HTTP_POSTPONE=YES
-    fi
-
-
     # the module order is important
     #     ngx_http_static_module
     #     ngx_http_gzip_static_module
@@ -252,13 +237,13 @@
         . $NGX_AUTO/module
     fi
 
-    if [ $HTTP_POSTPONE = YES ]; then
+    if :; then
         ngx_module_name=ngx_http_postpone_filter_module
         ngx_module_incs=
         ngx_module_deps=
         ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c
         ngx_module_libs=
-        ngx_module_link=$HTTP_POSTPONE
+        ngx_module_link=YES
 
         . $NGX_AUTO/module
     fi
diff --git a/auto/options b/auto/options
index 6466741..ec2c5e9 100644
--- a/auto/options
+++ b/auto/options
@@ -60,7 +60,6 @@
 HTTP_SSL=NO
 HTTP_V2=NO
 HTTP_SSI=YES
-HTTP_POSTPONE=NO
 HTTP_REALIP=NO
 HTTP_XSLT=NO
 HTTP_IMAGE_FILTER=NO
diff --git a/build.bzl b/build.bzl
index 89b3b38..609ad51 100644
--- a/build.bzl
+++ b/build.bzl
@@ -673,9 +673,9 @@
         name = "nginx_pkgoss",
         build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) +
                              _PKGOSS_BUILD_FILE_TAIL,
-        commit = "9fc4aba9d4045cb0ff71d5809508be69136d8ca1",  # nginx-1.15.12
+        commit = "395fb9664e0dac1bd7a8810bebdff867f9619aaa",  # nginx-1.17.0
         remote = "https://nginx.googlesource.com/nginx-pkgoss",
-        shallow_since = "1555425421 +0300",
+        shallow_since = "1558450033 +0300",
     )
 
 def nginx_repositories_zlib(bind):
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 9a28034..ae034bb 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,68 @@
 <change_log title="nginx">
 
 
+<changes ver="1.17.0" date="2019-05-21">
+
+<change type="feature">
+<para lang="ru">
+директивы limit_rate и limit_rate_after поддерживают переменные.
+</para>
+<para lang="en">
+variables support in the "limit_rate" and "limit_rate_after" directives.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+директивы proxy_upload_rate и proxy_download_rate в модуле stream
+поддерживают переменные.
+</para>
+<para lang="en">
+variables support
+in the "proxy_upload_rate" and "proxy_download_rate" directives
+in the stream module.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+минимальная поддерживаемая версия OpenSSL&mdash;0.9.8.
+</para>
+<para lang="en">
+minimum supported OpenSSL version is 0.9.8.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+теперь postpone-фильтр собирается всегда.
+</para>
+<para lang="en">
+now the postpone filter is always built.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+директива include не работала в блоках if и limit_except.
+</para>
+<para lang="en">
+the "include" directive did not work inside the "if" and "limit_except" blocks.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+в обработке byte ranges.
+</para>
+<para lang="en">
+in byte ranges processing.
+</para>
+</change>
+
+</changes>
+
+
 <changes ver="1.15.12" date="2019-04-16">
 
 <change type="bugfix">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 3883d90..644de51 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -13,8 +13,8 @@
 #define NGINX_NAME         "nginx"
 #endif
 
-#define nginx_version      1015012
-#define NGINX_VERSION      "1.15.12"
+#define nginx_version      1017000
+#define NGINX_VERSION      "1.17.0"
 #define NGINX_VER          NGINX_NAME "/" NGINX_VERSION
 
 #ifdef NGX_BUILD
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index 9cd5806..ed2d2ba 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -49,7 +49,7 @@
 #define NGX_DIRECT_CONF      0x00010000
 
 #define NGX_MAIN_CONF        0x01000000
-#define NGX_ANY_CONF         0x1F000000
+#define NGX_ANY_CONF         0xFF000000
 
 
 
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index c8c3fd9..5abd167 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -164,7 +164,6 @@
 
 #endif
 
-#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
 #ifndef SSL_OP_NO_COMPRESSION
     {
     /*
@@ -182,7 +181,6 @@
     }
     }
 #endif
-#endif
 
     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
 
@@ -927,13 +925,6 @@
         return NGX_ERROR;
     }
 
-    /*
-     * before 0.9.7h and 0.9.8 SSL_load_client_CA_file()
-     * always leaved an error in the error queue
-     */
-
-    ERR_clear_error();
-
     SSL_CTX_set_client_CA_list(ssl->ctx, list);
 
     return NGX_OK;
@@ -1099,8 +1090,8 @@
              * added to wbio, and set buffer size.
              */
 
-            rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn);
-            wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn);
+            rbio = SSL_get_rbio(ssl_conn);
+            wbio = SSL_get_wbio(ssl_conn);
 
             if (rbio != wbio) {
                 (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE);
@@ -1383,7 +1374,6 @@
 ngx_int_t
 ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
 #ifndef OPENSSL_NO_ECDH
 
     /*
@@ -1458,7 +1448,6 @@
     EC_KEY_free(ecdh);
 #endif
 #endif
-#endif
 
     return NGX_OK;
 }
@@ -3390,17 +3379,8 @@
         }
     }
 
-#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
-
     session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length);
 
-#else
-
-    session_id = sess->session_id;
-    session_id_length = sess->session_id_length;
-
-#endif
-
 #if (NGX_PTR_SIZE == 8)
 
     id = sess_id->sess_id;
@@ -3476,13 +3456,10 @@
 #endif
     u_char *id, int len, int *copy)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
-    const
-#endif
-    u_char                   *p;
     size_t                    slen;
     uint32_t                  hash;
     ngx_int_t                 rc;
+    const u_char             *p;
     ngx_shm_zone_t           *shm_zone;
     ngx_slab_pool_t          *shpool;
     ngx_rbtree_node_t        *node, *sentinel;
@@ -3604,17 +3581,8 @@
 
     cache = shm_zone->data;
 
-#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
-
     id = (u_char *) SSL_SESSION_get_id(sess, &len);
 
-#else
-
-    id = sess->session_id;
-    len = sess->session_id_length;
-
-#endif
-
     hash = ngx_crc32_short(id, len);
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
@@ -4413,17 +4381,8 @@
         return NGX_OK;
     }
 
-#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
-
     buf = (u_char *) SSL_SESSION_get_id(sess, &len);
 
-#else
-
-    buf = sess->session_id;
-    len = sess->session_id_length;
-
-#endif
-
     s->len = 2 * len;
     s->data = ngx_pnalloc(pool, 2 * len);
     if (s->data == NULL) {
diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c
index c832aa0..5a7e40e 100644
--- a/src/event/ngx_event_openssl_stapling.c
+++ b/src/event/ngx_event_openssl_stapling.c
@@ -589,15 +589,12 @@
 static void
 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
-    const
-#endif
-    u_char                *p;
     int                    n;
     size_t                 len;
     time_t                 now, valid;
     ngx_str_t              response;
     X509_STORE            *store;
+    const u_char          *p;
     STACK_OF(X509)        *chain;
     OCSP_CERTID           *id;
     OCSP_RESPONSE         *ocsp;
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index 819c5c9..ae08ebb 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -700,8 +700,9 @@
     ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
 {
     off_t              start, last;
+    ngx_int_t          rc;
     ngx_buf_t         *buf;
-    ngx_chain_t       *out, *cl, **ll;
+    ngx_chain_t       *out, *cl, *tl, **ll;
     ngx_http_range_t  *range;
 
     out = NULL;
@@ -721,8 +722,22 @@
                        "http range body buf: %O-%O", start, last);
 
         if (ngx_buf_special(buf)) {
-            *ll = cl;
-            ll = &cl->next;
+
+            if (range->end <= start) {
+                continue;
+            }
+
+            tl = ngx_alloc_chain_link(r->pool);
+            if (tl == NULL) {
+                return NGX_ERROR;
+            }
+
+            tl->buf = buf;
+            tl->next = NULL;
+
+            *ll = tl;
+            ll = &tl->next;
+
             continue;
         }
 
@@ -764,21 +779,42 @@
 
             buf->last_buf = (r == r->main) ? 1 : 0;
             buf->last_in_chain = 1;
-            *ll = cl;
-            cl->next = NULL;
 
-            break;
+            tl = ngx_alloc_chain_link(r->pool);
+            if (tl == NULL) {
+                return NGX_ERROR;
+            }
+
+            tl->buf = buf;
+            tl->next = NULL;
+
+            *ll = tl;
+            ll = &tl->next;
+
+            continue;
         }
 
-        *ll = cl;
-        ll = &cl->next;
+        tl = ngx_alloc_chain_link(r->pool);
+        if (tl == NULL) {
+            return NGX_ERROR;
+        }
+
+        tl->buf = buf;
+        tl->next = NULL;
+
+        *ll = tl;
+        ll = &tl->next;
     }
 
-    if (out == NULL) {
-        return NGX_OK;
+    rc = ngx_http_next_body_filter(r, out);
+
+    while (out) {
+        cl = out;
+        out = out->next;
+        ngx_free_chain(r->pool, cl);
     }
 
-    return ngx_http_next_body_filter(r, out);
+    return rc;
 }
 
 
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 2c0af62..110cb8a 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -479,7 +479,7 @@
     { ngx_string("limit_rate"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
                         |NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
+      ngx_http_set_complex_value_size_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_core_loc_conf_t, limit_rate),
       NULL },
@@ -487,7 +487,7 @@
     { ngx_string("limit_rate_after"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
                         |NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
+      ngx_http_set_complex_value_size_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_core_loc_conf_t, limit_rate_after),
       NULL },
@@ -1281,10 +1281,6 @@
         r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
     }
 
-    if (r->limit_rate == 0) {
-        r->limit_rate = clcf->limit_rate;
-    }
-
     if (clcf->handler) {
         r->content_handler = clcf->handler;
     }
@@ -3387,6 +3383,8 @@
      *     clcf->exact_match = 0;
      *     clcf->auto_redirect = 0;
      *     clcf->alias = 0;
+     *     clcf->limit_rate = NULL;
+     *     clcf->limit_rate_after = NULL;
      *     clcf->gzip_proxied = 0;
      *     clcf->keepalive_disable = 0;
      */
@@ -3417,8 +3415,6 @@
     clcf->send_timeout = NGX_CONF_UNSET_MSEC;
     clcf->send_lowat = NGX_CONF_UNSET_SIZE;
     clcf->postpone_output = NGX_CONF_UNSET_SIZE;
-    clcf->limit_rate = NGX_CONF_UNSET_SIZE;
-    clcf->limit_rate_after = NGX_CONF_UNSET_SIZE;
     clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
     clcf->keepalive_header = NGX_CONF_UNSET;
     clcf->keepalive_requests = NGX_CONF_UNSET_UINT;
@@ -3647,9 +3643,15 @@
     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
                               1460);
-    ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
-    ngx_conf_merge_size_value(conf->limit_rate_after, prev->limit_rate_after,
-                              0);
+
+    if (conf->limit_rate == NULL) {
+        conf->limit_rate = prev->limit_rate;
+    }
+
+    if (conf->limit_rate_after == NULL) {
+        conf->limit_rate_after = prev->limit_rate_after;
+    }
+
     ngx_conf_merge_msec_value(conf->keepalive_timeout,
                               prev->keepalive_timeout, 75000);
     ngx_conf_merge_sec_value(conf->keepalive_header,
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index aa77156..2360978 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -349,13 +349,14 @@
     size_t        client_body_buffer_size; /* client_body_buffer_size */
     size_t        send_lowat;              /* send_lowat */
     size_t        postpone_output;         /* postpone_output */
-    size_t        limit_rate;              /* limit_rate */
-    size_t        limit_rate_after;        /* limit_rate_after */
     size_t        sendfile_max_chunk;      /* sendfile_max_chunk */
     size_t        read_ahead;              /* read_ahead */
     size_t        subrequest_output_buffer_size;
                                            /* subrequest_output_buffer_size */
 
+    ngx_http_complex_value_t  *limit_rate; /* limit_rate */
+    ngx_http_complex_value_t  *limit_rate_after; /* limit_rate_after */
+
     ngx_msec_t    client_body_timeout;     /* client_body_timeout */
     ngx_msec_t    send_timeout;            /* send_timeout */
     ngx_msec_t    keepalive_timeout;       /* keepalive_timeout */
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index dd6f85e..184c35e 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -515,6 +515,9 @@
     unsigned                          limit_conn_set:1;
     unsigned                          limit_req_set:1;
 
+    unsigned                          limit_rate_set:1;
+    unsigned                          limit_rate_after_set:1;
+
 #if 0
     unsigned                          cacheable:1;
 #endif
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 4153889..f2f5a1c 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -104,6 +104,37 @@
 }
 
 
+size_t
+ngx_http_complex_value_size(ngx_http_request_t *r,
+    ngx_http_complex_value_t *val, size_t default_value)
+{
+    size_t     size;
+    ngx_str_t  value;
+
+    if (val == NULL) {
+        return default_value;
+    }
+
+    if (val->lengths == NULL) {
+        return val->u.size;
+    }
+
+    if (ngx_http_complex_value(r, val, &value) != NGX_OK) {
+        return default_value;
+    }
+
+    size = ngx_parse_size(&value);
+
+    if (size == (size_t) NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "invalid size \"%V\"", &value);
+        return default_value;
+    }
+
+    return size;
+}
+
+
 ngx_int_t
 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
 {
@@ -244,6 +275,36 @@
 }
 
 
+char *
+ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf)
+{
+    char  *p = conf;
+
+    char                      *rv;
+    ngx_http_complex_value_t  *cv;
+
+    rv = ngx_http_set_complex_value_slot(cf, cmd, conf);
+
+    if (rv != NGX_CONF_OK) {
+        return rv;
+    }
+
+    cv = *(ngx_http_complex_value_t **) (p + cmd->offset);
+
+    if (cv->lengths) {
+        return NGX_CONF_OK;
+    }
+
+    cv->u.size = ngx_parse_size(&cv->value);
+    if (cv->u.size == (size_t) NGX_ERROR) {
+        return "invalid value";
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 ngx_int_t
 ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
 {
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index 25bb6d7..a6b345e 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -68,6 +68,10 @@
     ngx_uint_t                 *flushes;
     void                       *lengths;
     void                       *values;
+
+    union {
+        size_t                  size;
+    } u;
 } ngx_http_complex_value_t;
 
 
@@ -207,9 +211,13 @@
     ngx_http_complex_value_t *val);
 ngx_int_t ngx_http_complex_value(ngx_http_request_t *r,
     ngx_http_complex_value_t *val, ngx_str_t *value);
+size_t ngx_http_complex_value_size(ngx_http_request_t *r,
+    ngx_http_complex_value_t *val, size_t default_value);
 ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv);
 char *ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+char *ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 
 
 ngx_int_t ngx_http_test_predicates(ngx_http_request_t *r,
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index fea4ea1..8b2f2b3 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -2983,6 +2983,7 @@
                              ngx_http_upstream_process_non_buffered_downstream;
 
         r->limit_rate = 0;
+        r->limit_rate_set = 1;
 
         if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
             ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
@@ -4810,6 +4811,7 @@
 
     if (n != NGX_ERROR) {
         r->limit_rate = (size_t) n;
+        r->limit_rate_set = 1;
     }
 
     return NGX_OK;
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c
index 2a08696..c630ae5 100644
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -669,10 +669,7 @@
     ngx_http_upstream_rr_peer_t   *peer;
 #if (NGX_HTTP_UPSTREAM_ZONE || NGX_COMPAT)
     int                            len;
-#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
-    const
-#endif
-    u_char                        *p;
+    const u_char                  *p;
     ngx_http_upstream_rr_peers_t  *peers;
     u_char                         buf[NGX_SSL_MAX_SESSION_SIZE];
 #endif
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index ebe9902..8cd6c9a 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -22,8 +22,6 @@
 #endif
 static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
-static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
-    ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
 
@@ -124,6 +122,8 @@
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static void ngx_http_variable_set_limit_rate(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 
 static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
@@ -321,7 +321,7 @@
     { ngx_string("sent_http_link"), NULL, ngx_http_variable_headers,
       offsetof(ngx_http_request_t, headers_out.link), 0, 0 },
 
-    { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
+    { ngx_string("limit_rate"), ngx_http_variable_set_limit_rate,
       ngx_http_variable_request_get_size,
       offsetof(ngx_http_request_t, limit_rate),
       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
@@ -788,32 +788,6 @@
 }
 
 
-static void
-ngx_http_variable_request_set_size(ngx_http_request_t *r,
-    ngx_http_variable_value_t *v, uintptr_t data)
-{
-    ssize_t    s, *sp;
-    ngx_str_t  val;
-
-    val.len = v->len;
-    val.data = v->data;
-
-    s = ngx_parse_size(&val);
-
-    if (s == NGX_ERROR) {
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "invalid size \"%V\"", &val);
-        return;
-    }
-
-    sp = (ssize_t *) ((char *) r + data);
-
-    *sp = s;
-
-    return;
-}
-
-
 static ngx_int_t
 ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
     uintptr_t data)
@@ -1993,6 +1967,29 @@
 }
 
 
+static void
+ngx_http_variable_set_limit_rate(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    ssize_t    s;
+    ngx_str_t  val;
+
+    val.len = v->len;
+    val.data = v->data;
+
+    s = ngx_parse_size(&val);
+
+    if (s == NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "invalid $limit_rate \"%V\"", &val);
+        return;
+    }
+
+    r->limit_rate = s;
+    r->limit_rate_set = 1;
+}
+
+
 static ngx_int_t
 ngx_http_variable_request_completion(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 3f18d76..6a5d957 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -250,9 +250,17 @@
         return NGX_ERROR;
     }
 
+    if (!r->limit_rate_set) {
+        r->limit_rate = ngx_http_complex_value_size(r, clcf->limit_rate, 0);
+        r->limit_rate_set = 1;
+    }
+
     if (r->limit_rate) {
-        if (r->limit_rate_after == 0) {
-            r->limit_rate_after = clcf->limit_rate_after;
+
+        if (!r->limit_rate_after_set) {
+            r->limit_rate_after = ngx_http_complex_value_size(r,
+                                                    clcf->limit_rate_after, 0);
+            r->limit_rate_after_set = 1;
         }
 
         limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1)
diff --git a/src/ngx_modules.c b/src/ngx_modules.c
index dea7b9d..584dea1 100644
--- a/src/ngx_modules.c
+++ b/src/ngx_modules.c
@@ -188,7 +188,7 @@
 #if (NGX_HTTP_BROTLI_FILTER)
 extern ngx_module_t  ngx_http_brotli_filter_module;
 #endif
-#if (NGX_HTTP_POSTPONE)
+#if (NGX_HTTP)
 extern ngx_module_t  ngx_http_postpone_filter_module;
 #endif
 #if (NGX_HTTP_SSI)
@@ -477,7 +477,7 @@
 #if (NGX_HTTP_BROTLI_FILTER)
     &ngx_http_brotli_filter_module,
 #endif
-#if (NGX_HTTP_POSTPONE)
+#if (NGX_HTTP)
     &ngx_http_postpone_filter_module,
 #endif
 #if (NGX_HTTP_SSI)
@@ -768,7 +768,7 @@
 #if (NGX_HTTP_BROTLI_FILTER)
     "ngx_http_brotli_filter_module",
 #endif
-#if (NGX_HTTP_POSTPONE)
+#if (NGX_HTTP)
     "ngx_http_postpone_filter_module",
 #endif
 #if (NGX_HTTP_SSI)
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
index 127c8a4..7484a72 100644
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -24,8 +24,8 @@
     ngx_msec_t                       timeout;
     ngx_msec_t                       next_upstream_timeout;
     size_t                           buffer_size;
-    size_t                           upload_rate;
-    size_t                           download_rate;
+    ngx_stream_complex_value_t      *upload_rate;
+    ngx_stream_complex_value_t      *download_rate;
     ngx_uint_t                       requests;
     ngx_uint_t                       responses;
     ngx_uint_t                       next_upstream_tries;
@@ -184,14 +184,14 @@
 
     { ngx_string("proxy_upload_rate"),
       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
+      ngx_stream_set_complex_value_size_slot,
       NGX_STREAM_SRV_CONF_OFFSET,
       offsetof(ngx_stream_proxy_srv_conf_t, upload_rate),
       NULL },
 
     { ngx_string("proxy_download_rate"),
       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
+      ngx_stream_set_complex_value_size_slot,
       NGX_STREAM_SRV_CONF_OFFSET,
       offsetof(ngx_stream_proxy_srv_conf_t, download_rate),
       NULL },
@@ -895,6 +895,9 @@
         u->proxy_protocol = 0;
     }
 
+    u->upload_rate = ngx_stream_complex_value_size(s, pscf->upload_rate, 0);
+    u->download_rate = ngx_stream_complex_value_size(s, pscf->download_rate, 0);
+
     u->connected = 1;
 
     pc->read->handler = ngx_stream_proxy_upstream_handler;
@@ -1532,7 +1535,7 @@
         src = pc;
         dst = c;
         b = &u->upstream_buf;
-        limit_rate = pscf->download_rate;
+        limit_rate = u->download_rate;
         received = &u->received;
         packets = &u->responses;
         out = &u->downstream_out;
@@ -1544,7 +1547,7 @@
         src = c;
         dst = pc;
         b = &u->downstream_buf;
-        limit_rate = pscf->upload_rate;
+        limit_rate = u->upload_rate;
         received = &s->received;
         packets = &u->requests;
         out = &u->upstream_out;
@@ -1955,6 +1958,8 @@
      *     conf->ssl_certificate = { 0, NULL };
      *     conf->ssl_certificate_key = { 0, NULL };
      *
+     *     conf->upload_rate = NULL;
+     *     conf->download_rate = NULL;
      *     conf->ssl = NULL;
      *     conf->upstream = NULL;
      *     conf->upstream_value = NULL;
@@ -1964,8 +1969,6 @@
     conf->timeout = NGX_CONF_UNSET_MSEC;
     conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC;
     conf->buffer_size = NGX_CONF_UNSET_SIZE;
-    conf->upload_rate = NGX_CONF_UNSET_SIZE;
-    conf->download_rate = NGX_CONF_UNSET_SIZE;
     conf->requests = NGX_CONF_UNSET_UINT;
     conf->responses = NGX_CONF_UNSET_UINT;
     conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
@@ -2005,11 +2008,13 @@
     ngx_conf_merge_size_value(conf->buffer_size,
                               prev->buffer_size, 16384);
 
-    ngx_conf_merge_size_value(conf->upload_rate,
-                              prev->upload_rate, 0);
+    if (conf->upload_rate == NULL) {
+        conf->upload_rate = prev->upload_rate;
+    }
 
-    ngx_conf_merge_size_value(conf->download_rate,
-                              prev->download_rate, 0);
+    if (conf->download_rate == NULL) {
+        conf->download_rate = prev->download_rate;
+    }
 
     ngx_conf_merge_uint_value(conf->requests,
                               prev->requests, 0);
diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c
index b00e708..a15f772 100644
--- a/src/stream/ngx_stream_script.c
+++ b/src/stream/ngx_stream_script.c
@@ -105,6 +105,37 @@
 }
 
 
+size_t
+ngx_stream_complex_value_size(ngx_stream_session_t *s,
+    ngx_stream_complex_value_t *val, size_t default_value)
+{
+    size_t     size;
+    ngx_str_t  value;
+
+    if (val == NULL) {
+        return default_value;
+    }
+
+    if (val->lengths == NULL) {
+        return val->u.size;
+    }
+
+    if (ngx_stream_complex_value(s, val, &value) != NGX_OK) {
+        return default_value;
+    }
+
+    size = ngx_parse_size(&value);
+
+    if (size == (size_t) NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+                      "invalid size \"%V\"", &value);
+        return default_value;
+    }
+
+    return size;
+}
+
+
 ngx_int_t
 ngx_stream_compile_complex_value(ngx_stream_compile_complex_value_t *ccv)
 {
@@ -246,6 +277,36 @@
 }
 
 
+char *
+ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf)
+{
+    char  *p = conf;
+
+    char                        *rv;
+    ngx_stream_complex_value_t  *cv;
+
+    rv = ngx_stream_set_complex_value_slot(cf, cmd, conf);
+
+    if (rv != NGX_CONF_OK) {
+        return rv;
+    }
+
+    cv = *(ngx_stream_complex_value_t **) (p + cmd->offset);
+
+    if (cv->lengths) {
+        return NGX_CONF_OK;
+    }
+
+    cv->u.size = ngx_parse_size(&cv->value);
+    if (cv->u.size == (size_t) NGX_ERROR) {
+        return "invalid value";
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 ngx_uint_t
 ngx_stream_script_variables_count(ngx_str_t *value)
 {
diff --git a/src/stream/ngx_stream_script.h b/src/stream/ngx_stream_script.h
index 25a450d..a481ca3 100644
--- a/src/stream/ngx_stream_script.h
+++ b/src/stream/ngx_stream_script.h
@@ -56,6 +56,10 @@
     ngx_uint_t                   *flushes;
     void                         *lengths;
     void                         *values;
+
+    union {
+        size_t                    size;
+    } u;
 } ngx_stream_complex_value_t;
 
 
@@ -102,10 +106,14 @@
     ngx_stream_complex_value_t *val);
 ngx_int_t ngx_stream_complex_value(ngx_stream_session_t *s,
     ngx_stream_complex_value_t *val, ngx_str_t *value);
+size_t ngx_stream_complex_value_size(ngx_stream_session_t *s,
+    ngx_stream_complex_value_t *val, size_t default_value);
 ngx_int_t ngx_stream_compile_complex_value(
     ngx_stream_compile_complex_value_t *ccv);
 char *ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+char *ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 
 
 ngx_uint_t ngx_stream_script_variables_count(ngx_str_t *value);
diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h
index bf893f8..7aaf628 100644
--- a/src/stream/ngx_stream_upstream.h
+++ b/src/stream/ngx_stream_upstream.h
@@ -132,6 +132,9 @@
     ngx_uint_t                         responses;
     ngx_msec_t                         start_time;
 
+    size_t                             upload_rate;
+    size_t                             download_rate;
+
     ngx_str_t                          ssl_name;
 
     ngx_stream_upstream_srv_conf_t    *upstream;
diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c
index c35e1d0..b4c1541 100644
--- a/src/stream/ngx_stream_upstream_round_robin.c
+++ b/src/stream/ngx_stream_upstream_round_robin.c
@@ -701,10 +701,7 @@
     ngx_stream_upstream_rr_peer_t   *peer;
 #if (NGX_STREAM_UPSTREAM_ZONE || NGX_COMPAT)
     int                              len;
-#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
-    const
-#endif
-    u_char                          *p;
+    const u_char                    *p;
     ngx_stream_upstream_rr_peers_t  *peers;
     u_char                           buf[NGX_SSL_MAX_SESSION_SIZE];
 #endif