Index: http/ngx_http_core_module.c =================================================================== --- http/ngx_http_core_module.c (revision 2933) +++ http/ngx_http_core_module.c (working copy) @@ -1,4 +1,3 @@ - /* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. @@ -503,6 +502,15 @@ offsetof(ngx_http_core_loc_conf_t, limit_rate_after), NULL }, + { ngx_string("limit_rate_max"), + 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_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, limit_rate_max), + NULL }, + + { ngx_string("keepalive_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, ngx_http_core_keepalive, @@ -1516,6 +1524,11 @@ r->limit_rate = clcf->limit_rate; } + if (r->limit_rate_after == 0) { + r->limit_rate_after = clcf->limit_rate_after; + } + + if (clcf->handler) { r->content_handler = clcf->handler; } @@ -3493,6 +3506,7 @@ clcf->postpone_output = NGX_CONF_UNSET_SIZE; clcf->limit_rate = NGX_CONF_UNSET_SIZE; clcf->limit_rate_after = NGX_CONF_UNSET_SIZE; + clcf->limit_rate_max = NGX_CONF_UNSET_SIZE; clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; clcf->keepalive_header = NGX_CONF_UNSET; clcf->keepalive_requests = NGX_CONF_UNSET_UINT; @@ -3716,6 +3730,8 @@ 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); + ngx_conf_merge_size_value(conf->limit_rate_max, prev->limit_rate_max, + 0); ngx_conf_merge_msec_value(conf->keepalive_timeout, prev->keepalive_timeout, 75000); ngx_conf_merge_sec_value(conf->keepalive_header, Index: http/ngx_http_core_module.h =================================================================== --- http/ngx_http_core_module.h (revision 2933) +++ http/ngx_http_core_module.h (working copy) @@ -351,6 +351,7 @@ size_t postpone_output; /* postpone_output */ size_t limit_rate; /* limit_rate */ size_t limit_rate_after; /* limit_rate_after */ + size_t limit_rate_max; /* limit_rate_max */ size_t sendfile_max_chunk; /* sendfile_max_chunk */ size_t read_ahead; /* read_ahead */ Index: http/ngx_http_request.h =================================================================== --- http/ngx_http_request.h (revision 2933) +++ http/ngx_http_request.h (working copy) @@ -418,6 +418,7 @@ #endif size_t limit_rate; + size_t limit_rate_after; /* used to learn the Apache compatible response length without a header */ size_t header_size; Index: http/ngx_http_variables.c =================================================================== --- http/ngx_http_variables.c (revision 2933) +++ http/ngx_http_variables.c (working copy) @@ -260,6 +260,11 @@ offsetof(ngx_http_request_t, limit_rate), NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("limit_rate_after"), ngx_http_variable_request_set_size, + ngx_http_variable_request_get_size, + offsetof(ngx_http_request_t, limit_rate_after), + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, 0, 0, 0 }, Index: http/ngx_http_write_filter_module.c =================================================================== --- http/ngx_http_write_filter_module.c (revision 2933) +++ http/ngx_http_write_filter_module.c (working copy) @@ -211,13 +211,18 @@ } if (r->limit_rate) { + if((unsigned)c->sent < r->limit_rate_after && clcf->limit_rate_max) { + limit = clcf->limit_rate_max * (ngx_time() - r->start_sec + 1) + - c->sent; + } else { limit = r->limit_rate * (ngx_time() - r->start_sec + 1) - (c->sent - r->limit_rate_after); + } if (limit <= 0) { c->write->delayed = 1; ngx_add_timer(c->write, - (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1)); + (ngx_msec_t) (- limit * 1000 / (((unsigned)c->sent < r->limit_rate_after && clcf->limit_rate_max)?clcf->limit_rate_max:r->limit_rate) + 1)); c->buffered |= NGX_HTTP_WRITE_BUFFERED; @@ -253,20 +258,27 @@ nsent = c->sent; - if (clcf->limit_rate_after) { + if (r->limit_rate_after && (unsigned)c->sent >= r->limit_rate_after) { - sent -= clcf->limit_rate_after; + sent -= r->limit_rate_after; if (sent < 0) { sent = 0; } - nsent -= clcf->limit_rate_after; + nsent -= r->limit_rate_after; if (nsent < 0) { nsent = 0; } } + if((unsigned)c->sent < r->limit_rate_after && clcf->limit_rate_max) + { + delay = (ngx_msec_t) ((nsent - sent) * 1000 / clcf->limit_rate_max); + } + else + { delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate); + } if (delay > 0) { limit = 0;