Variables support in limit_rate and limit_rate_after (ticket #293).
Ruslan Ermilov
3 years ago
478 | 478 | { ngx_string("limit_rate"), |
479 | 479 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
480 | 480 | |NGX_CONF_TAKE1, |
481 | ngx_conf_set_size_slot, | |
481 | ngx_http_set_complex_value_size_slot, | |
482 | 482 | NGX_HTTP_LOC_CONF_OFFSET, |
483 | 483 | offsetof(ngx_http_core_loc_conf_t, limit_rate), |
484 | 484 | NULL }, |
486 | 486 | { ngx_string("limit_rate_after"), |
487 | 487 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
488 | 488 | |NGX_CONF_TAKE1, |
489 | ngx_conf_set_size_slot, | |
489 | ngx_http_set_complex_value_size_slot, | |
490 | 490 | NGX_HTTP_LOC_CONF_OFFSET, |
491 | 491 | offsetof(ngx_http_core_loc_conf_t, limit_rate_after), |
492 | 492 | NULL }, |
1278 | 1278 | if (!clcf->tcp_nopush) { |
1279 | 1279 | /* disable TCP_NOPUSH/TCP_CORK use */ |
1280 | 1280 | r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED; |
1281 | } | |
1282 | ||
1283 | if (r->limit_rate == 0) { | |
1284 | r->limit_rate = clcf->limit_rate; | |
1285 | 1281 | } |
1286 | 1282 | |
1287 | 1283 | if (clcf->handler) { |
3386 | 3382 | * clcf->exact_match = 0; |
3387 | 3383 | * clcf->auto_redirect = 0; |
3388 | 3384 | * clcf->alias = 0; |
3385 | * clcf->limit_rate = NULL; | |
3386 | * clcf->limit_rate_after = NULL; | |
3389 | 3387 | * clcf->gzip_proxied = 0; |
3390 | 3388 | * clcf->keepalive_disable = 0; |
3391 | 3389 | */ |
3416 | 3414 | clcf->send_timeout = NGX_CONF_UNSET_MSEC; |
3417 | 3415 | clcf->send_lowat = NGX_CONF_UNSET_SIZE; |
3418 | 3416 | clcf->postpone_output = NGX_CONF_UNSET_SIZE; |
3419 | clcf->limit_rate = NGX_CONF_UNSET_SIZE; | |
3420 | clcf->limit_rate_after = NGX_CONF_UNSET_SIZE; | |
3421 | 3417 | clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; |
3422 | 3418 | clcf->keepalive_header = NGX_CONF_UNSET; |
3423 | 3419 | clcf->keepalive_requests = NGX_CONF_UNSET_UINT; |
3646 | 3642 | ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0); |
3647 | 3643 | ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output, |
3648 | 3644 | 1460); |
3649 | ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0); | |
3650 | ngx_conf_merge_size_value(conf->limit_rate_after, prev->limit_rate_after, | |
3651 | 0); | |
3645 | ||
3646 | if (conf->limit_rate == NULL) { | |
3647 | conf->limit_rate = prev->limit_rate; | |
3648 | } | |
3649 | ||
3650 | if (conf->limit_rate_after == NULL) { | |
3651 | conf->limit_rate_after = prev->limit_rate_after; | |
3652 | } | |
3653 | ||
3652 | 3654 | ngx_conf_merge_msec_value(conf->keepalive_timeout, |
3653 | 3655 | prev->keepalive_timeout, 75000); |
3654 | 3656 | ngx_conf_merge_sec_value(conf->keepalive_header, |
348 | 348 | size_t client_body_buffer_size; /* client_body_buffer_size */ |
349 | 349 | size_t send_lowat; /* send_lowat */ |
350 | 350 | size_t postpone_output; /* postpone_output */ |
351 | size_t limit_rate; /* limit_rate */ | |
352 | size_t limit_rate_after; /* limit_rate_after */ | |
353 | 351 | size_t sendfile_max_chunk; /* sendfile_max_chunk */ |
354 | 352 | size_t read_ahead; /* read_ahead */ |
355 | 353 | size_t subrequest_output_buffer_size; |
356 | 354 | /* subrequest_output_buffer_size */ |
355 | ||
356 | ngx_http_complex_value_t *limit_rate; /* limit_rate */ | |
357 | ngx_http_complex_value_t *limit_rate_after; /* limit_rate_after */ | |
357 | 358 | |
358 | 359 | ngx_msec_t client_body_timeout; /* client_body_timeout */ |
359 | 360 | ngx_msec_t send_timeout; /* send_timeout */ |
513 | 513 | */ |
514 | 514 | unsigned limit_conn_set:1; |
515 | 515 | unsigned limit_req_set:1; |
516 | ||
517 | unsigned limit_rate_set:1; | |
518 | unsigned limit_rate_after_set:1; | |
516 | 519 | |
517 | 520 | #if 0 |
518 | 521 | unsigned cacheable:1; |
2978 | 2978 | ngx_http_upstream_process_non_buffered_downstream; |
2979 | 2979 | |
2980 | 2980 | r->limit_rate = 0; |
2981 | r->limit_rate_set = 1; | |
2981 | 2982 | |
2982 | 2983 | if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) { |
2983 | 2984 | ngx_http_upstream_finalize_request(r, u, NGX_ERROR); |
4805 | 4806 | |
4806 | 4807 | if (n != NGX_ERROR) { |
4807 | 4808 | r->limit_rate = (size_t) n; |
4809 | r->limit_rate_set = 1; | |
4808 | 4810 | } |
4809 | 4811 | |
4810 | 4812 | return NGX_OK; |
21 | 21 | #endif |
22 | 22 | static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r, |
23 | 23 | ngx_http_variable_value_t *v, uintptr_t data); |
24 | static void ngx_http_variable_request_set_size(ngx_http_request_t *r, | |
25 | ngx_http_variable_value_t *v, uintptr_t data); | |
26 | 24 | static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r, |
27 | 25 | ngx_http_variable_value_t *v, uintptr_t data); |
28 | 26 | |
122 | 120 | static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r, |
123 | 121 | ngx_http_variable_value_t *v, uintptr_t data); |
124 | 122 | static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r, |
123 | ngx_http_variable_value_t *v, uintptr_t data); | |
124 | static void ngx_http_variable_set_limit_rate(ngx_http_request_t *r, | |
125 | 125 | ngx_http_variable_value_t *v, uintptr_t data); |
126 | 126 | |
127 | 127 | static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r, |
320 | 320 | { ngx_string("sent_http_link"), NULL, ngx_http_variable_headers, |
321 | 321 | offsetof(ngx_http_request_t, headers_out.link), 0, 0 }, |
322 | 322 | |
323 | { ngx_string("limit_rate"), ngx_http_variable_request_set_size, | |
323 | { ngx_string("limit_rate"), ngx_http_variable_set_limit_rate, | |
324 | 324 | ngx_http_variable_request_get_size, |
325 | 325 | offsetof(ngx_http_request_t, limit_rate), |
326 | 326 | NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
787 | 787 | } |
788 | 788 | |
789 | 789 | |
790 | static void | |
791 | ngx_http_variable_request_set_size(ngx_http_request_t *r, | |
792 | ngx_http_variable_value_t *v, uintptr_t data) | |
793 | { | |
794 | ssize_t s, *sp; | |
795 | ngx_str_t val; | |
796 | ||
797 | val.len = v->len; | |
798 | val.data = v->data; | |
799 | ||
800 | s = ngx_parse_size(&val); | |
801 | ||
802 | if (s == NGX_ERROR) { | |
803 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
804 | "invalid size \"%V\"", &val); | |
805 | return; | |
806 | } | |
807 | ||
808 | sp = (ssize_t *) ((char *) r + data); | |
809 | ||
810 | *sp = s; | |
811 | ||
812 | return; | |
813 | } | |
814 | ||
815 | ||
816 | 790 | static ngx_int_t |
817 | 791 | ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
818 | 792 | uintptr_t data) |
1989 | 1963 | } |
1990 | 1964 | |
1991 | 1965 | return NGX_OK; |
1966 | } | |
1967 | ||
1968 | ||
1969 | static void | |
1970 | ngx_http_variable_set_limit_rate(ngx_http_request_t *r, | |
1971 | ngx_http_variable_value_t *v, uintptr_t data) | |
1972 | { | |
1973 | ssize_t s; | |
1974 | ngx_str_t val; | |
1975 | ||
1976 | val.len = v->len; | |
1977 | val.data = v->data; | |
1978 | ||
1979 | s = ngx_parse_size(&val); | |
1980 | ||
1981 | if (s == NGX_ERROR) { | |
1982 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1983 | "invalid $limit_rate \"%V\"", &val); | |
1984 | return; | |
1985 | } | |
1986 | ||
1987 | r->limit_rate = s; | |
1988 | r->limit_rate_set = 1; | |
1992 | 1989 | } |
1993 | 1990 | |
1994 | 1991 |
249 | 249 | return NGX_ERROR; |
250 | 250 | } |
251 | 251 | |
252 | if (!r->limit_rate_set) { | |
253 | r->limit_rate = ngx_http_complex_value_size(r, clcf->limit_rate, 0); | |
254 | r->limit_rate_set = 1; | |
255 | } | |
256 | ||
252 | 257 | if (r->limit_rate) { |
253 | if (r->limit_rate_after == 0) { | |
254 | r->limit_rate_after = clcf->limit_rate_after; | |
258 | ||
259 | if (!r->limit_rate_after_set) { | |
260 | r->limit_rate_after = ngx_http_complex_value_size(r, | |
261 | clcf->limit_rate_after, 0); | |
262 | r->limit_rate_after_set = 1; | |
255 | 263 | } |
256 | 264 | |
257 | 265 | limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1) |