comparison src/http/modules/ngx_http_limit_req_module.c @ 427:ff86d646f9df NGINX_0_7_21

nginx 0.7.21 *) Changes in the ngx_http_limit_req_module. *) Feature: the EXSLT support in the ngx_http_xslt_module. Thanks to Denis F. Latypoff. *) Workaround: compatibility with glibc 2.3. Thanks to Eric Benson and Maxim Dounin. *) Bugfix: nginx could not run on MacOSX 10.4 and earlier; the bug had appeared in 0.7.6.
author Igor Sysoev <http://sysoev.ru>
date Tue, 11 Nov 2008 00:00:00 +0300
parents b4f69f2ef02c
children ad0a34a8efa6
comparison
equal deleted inserted replaced
426:735cec38a814 427:ff86d646f9df
31 31
32 32
33 typedef struct { 33 typedef struct {
34 ngx_shm_zone_t *shm_zone; 34 ngx_shm_zone_t *shm_zone;
35 float burst; 35 float burst;
36 ngx_msec_t delay; 36 ngx_uint_t nodelay; /* unsigned nodelay:1 */
37 } ngx_http_limit_req_conf_t; 37 } ngx_http_limit_req_conf_t;
38 38
39 39
40 static void ngx_http_limit_req_delay(ngx_http_request_t *r); 40 static void ngx_http_limit_req_delay(ngx_http_request_t *r);
41 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lzcf, 41 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lzcf,
176 176
177 if (rc == NGX_BUSY) { 177 if (rc == NGX_BUSY) {
178 ngx_shmtx_unlock(&ctx->shpool->mutex); 178 ngx_shmtx_unlock(&ctx->shpool->mutex);
179 179
180 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 180 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
181 "limiting requests, %.3f r/s", rate); 181 "limiting requests, excess: %.3f", rate);
182 182
183 return NGX_HTTP_SERVICE_UNAVAILABLE; 183 return NGX_HTTP_SERVICE_UNAVAILABLE;
184 } 184 }
185 185
186 if (rc == NGX_AGAIN) { 186 if (rc == NGX_AGAIN) {
187 ngx_shmtx_unlock(&ctx->shpool->mutex); 187 ngx_shmtx_unlock(&ctx->shpool->mutex);
188 188
189 if (lzcf->delay) { 189 if (lzcf->nodelay) {
190 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, 190 return NGX_DECLINED;
191 "delaying requests, %.3f r/s", rate); 191 }
192 192
193 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { 193 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
194 return NGX_HTTP_INTERNAL_SERVER_ERROR; 194 "delaying request, excess: %.3f", rate);
195 } 195
196 196 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
197 r->read_event_handler = ngx_http_test_reading; 197 return NGX_HTTP_INTERNAL_SERVER_ERROR;
198 r->write_event_handler = ngx_http_limit_req_delay; 198 }
199 ngx_add_timer(r->connection->write, lzcf->delay); 199
200 200 r->read_event_handler = ngx_http_test_reading;
201 return NGX_AGAIN; 201 r->write_event_handler = ngx_http_limit_req_delay;
202 } 202 ngx_add_timer(r->connection->write, (ngx_msec_t) (rate * 1000));
203 203
204 return NGX_DECLINED; 204 return NGX_AGAIN;
205 } 205 }
206 206
207 if (rc == NGX_OK) { 207 if (rc == NGX_OK) {
208 goto done; 208 goto done;
209 } 209 }
363 363
364 if (lz->rate > lzcf->burst) { 364 if (lz->rate > lzcf->burst) {
365 return NGX_BUSY; 365 return NGX_BUSY;
366 } 366 }
367 367
368 if (lz->rate > ctx->rate) { 368 if (lz->rate > 0.0) {
369 return NGX_AGAIN; 369 return NGX_AGAIN;
370 } 370 }
371 371
372 return NGX_OK; 372 return NGX_OK;
373 } 373 }
509 /* 509 /*
510 * set by ngx_pcalloc(): 510 * set by ngx_pcalloc():
511 * 511 *
512 * conf->shm_zone = NULL; 512 * conf->shm_zone = NULL;
513 * conf->burst = 0.0; 513 * conf->burst = 0.0;
514 * conf->delay = 0; 514 * conf->nodelay = 0;
515 */ 515 */
516 516
517 return conf; 517 return conf;
518 } 518 }
519 519
668 static char * 668 static char *
669 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 669 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
670 { 670 {
671 ngx_http_limit_req_conf_t *lzcf = conf; 671 ngx_http_limit_req_conf_t *lzcf = conf;
672 672
673 u_char *p; 673 ngx_int_t burst;
674 size_t len; 674 ngx_str_t *value, s;
675 ngx_int_t burst, scale, delay; 675 ngx_uint_t i;
676 ngx_str_t *value, s;
677 ngx_uint_t i;
678 ngx_http_limit_req_ctx_t *ctx;
679 676
680 if (lzcf->shm_zone) { 677 if (lzcf->shm_zone) {
681 return "is duplicate"; 678 return "is duplicate";
682 } 679 }
683 680
684 value = cf->args->elts; 681 value = cf->args->elts;
685 682
686 burst = 0; 683 burst = 0;
687 scale = 1;
688 delay = 0;
689 684
690 for (i = 1; i < cf->args->nelts; i++) { 685 for (i = 1; i < cf->args->nelts; i++) {
691 686
692 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { 687 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) {
693 688
703 continue; 698 continue;
704 } 699 }
705 700
706 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { 701 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) {
707 702
708 len = value[i].len; 703 burst = ngx_atoi(value[i].data + 6, value[i].len - 6);
709 p = value[i].data + len - 3;
710
711 if (ngx_strncmp(p, "r/s", 3) == 0) {
712 scale = 1;
713 len -= 3;
714
715 } else if (ngx_strncmp(p, "r/m", 3) == 0) {
716 scale = 60;
717 len -= 3;
718 }
719
720 burst = ngx_atoi(value[i].data + 6, len - 6);
721 if (burst <= 0) { 704 if (burst <= 0) {
722 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 705 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
723 "invalid burst rate \"%V\"", &value[i]); 706 "invalid burst rate \"%V\"", &value[i]);
724 return NGX_CONF_ERROR; 707 return NGX_CONF_ERROR;
725 } 708 }
726 709
727 continue; 710 continue;
728 } 711 }
729 712
730 if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { 713 if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) {
731 714 lzcf->nodelay = 1;
732 s.len = value[i].len - 6;
733 s.data = value[i].data + 6;
734
735 delay = ngx_parse_time(&s, 0);
736 if (delay < 0) {
737 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
738 "invalid clean_time value \"%V\"", &value[i]);
739 return NGX_CONF_ERROR;
740 }
741
742 continue; 715 continue;
743 } 716 }
744 717
745 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 718 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
746 "invalid parameter \"%V\"", &value[i]); 719 "invalid parameter \"%V\"", &value[i]);
759 "unknown limit_req_zone \"%V\"", 732 "unknown limit_req_zone \"%V\"",
760 &lzcf->shm_zone->name); 733 &lzcf->shm_zone->name);
761 return NGX_CONF_ERROR; 734 return NGX_CONF_ERROR;
762 } 735 }
763 736
764 if (burst) { 737 lzcf->burst = (float) burst;
765 lzcf->burst = (float) burst / scale;
766
767 } else {
768 ctx = lzcf->shm_zone->data;
769 lzcf->burst = ctx->rate;
770 }
771
772 lzcf->delay = (ngx_msec_t) delay;
773 738
774 return NGX_CONF_OK; 739 return NGX_CONF_OK;
775 } 740 }
776 741
777 742