--- ngx_http_limit_req_module.c 2009-04-18 19:27:28.000000000 +0000 +++ ngx_http_limit_req_module.c.new 2009-09-04 15:17:37.000000000 +0000 @@ -7,7 +7,7 @@ #include #include #include - +#include typedef struct { u_char color; @@ -17,7 +17,7 @@ ngx_msec_t last; /* integer value, 1 corresponds to 0.001 r/s */ ngx_uint_t excess; - u_char data[1]; + u_char data[16]; } ngx_http_limit_req_node_t; @@ -33,8 +33,8 @@ ngx_slab_pool_t *shpool; /* integer value, 1 corresponds to 0.001 r/s */ ngx_uint_t rate; - ngx_int_t index; - ngx_str_t var; + ngx_http_complex_value_t key; + ngx_str_t var; } ngx_http_limit_req_ctx_t; @@ -122,10 +122,13 @@ ngx_uint_t excess; ngx_time_t *tp; ngx_rbtree_node_t *node; - ngx_http_variable_value_t *vv; + ngx_str_t *vv; + ngx_str_t value; ngx_http_limit_req_ctx_t *ctx; ngx_http_limit_req_node_t *lr; ngx_http_limit_req_conf_t *lrcf; + ngx_md5_t md5; + u_char complex_hash[16]; if (r->main->limit_req_set) { return NGX_DECLINED; @@ -139,19 +142,24 @@ ctx = lrcf->shm_zone->data; - vv = ngx_http_get_indexed_variable(r, ctx->index); - - if (vv == NULL || vv->not_found) { + if (ctx->key.value.len == 0) { return NGX_DECLINED; } - len = vv->len; + if (ngx_http_complex_value(r, &ctx->key, &value) != NGX_OK) { + return NGX_ERROR; + } + + vv = &value; - if (len == 0) { + if (vv->len == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the value of \"%V\" variable is 0 len", + &ctx->var); return NGX_DECLINED; } - if (len > 65535) { + if (vv->len > 65535) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the value of the \"%V\" variable " "is more than 65535 bytes: \"%v\"", @@ -161,13 +169,18 @@ r->main->limit_req_set = 1; - hash = ngx_crc32_short(vv->data, len); + hash = ngx_crc32_long(vv->data, vv->len); + + ngx_md5_init(&md5); + ngx_md5_update(&md5, vv->data, vv->len); + ngx_md5_final(complex_hash, &md5); + len = 16; ngx_shmtx_lock(&ctx->shpool->mutex); ngx_http_limit_req_expire(ctx, 1); - rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr); + rc = ngx_http_limit_req_lookup(lrcf, hash, complex_hash, len, &lr); if (lr) { ngx_queue_remove(&lr->queue); @@ -246,7 +259,7 @@ lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); lr->excess = 0; - ngx_memcpy(lr->data, vv->data, len); + ngx_memcpy(lr->data, complex_hash, len); ngx_rbtree_insert(&ctx->sh->rbtree, node); @@ -561,6 +574,7 @@ ngx_uint_t i; ngx_shm_zone_t *shm_zone; ngx_http_limit_req_ctx_t *ctx; + ngx_http_compile_complex_value_t ccv; value = cf->args->elts; @@ -633,8 +647,13 @@ return NGX_CONF_ERROR; } - ctx->index = ngx_http_get_variable_index(cf, &value[i]); - if (ctx->index == NGX_ERROR) { + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[i]; + ccv.complex_value = &ctx->key; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; }