# HG changeset patch # User Igor Sysoev # Date 1236341707 0 # Node ID 912ce4113f218a5967f6f852e40e9a620486e32f # Parent 8b9861c2a32f5308a4c2663c3c1035e1a9c3ae3f now regex captures are per-request entities diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -12,7 +12,6 @@ typedef struct { ngx_array_t *codes; /* uintptr_t */ - ngx_uint_t captures; ngx_uint_t stack_size; ngx_flag_t log; @@ -157,16 +156,6 @@ ngx_http_rewrite_handler(ngx_http_reques return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (rlcf->captures) { - e->captures = ngx_palloc(r->pool, rlcf->captures * sizeof(int)); - if (e->captures == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - } else { - e->captures = NULL; - } - e->ip = rlcf->codes->elts; e->request = r; e->quote = 1; @@ -436,10 +425,6 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com if (regex->ncaptures) { regex->ncaptures = (regex->ncaptures + 1) * 3; - - if (lcf->captures < regex->ncaptures) { - lcf->captures = regex->ncaptures; - } } regex_end = ngx_http_script_add_code(lcf->codes, @@ -618,11 +603,6 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_ } - if (lcf->captures < nlcf->captures) { - lcf->captures = nlcf->captures; - } - - if (elts != lcf->codes->elts) { if_code = (ngx_http_script_if_code_t *) ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); @@ -777,10 +757,6 @@ ngx_http_rewrite_if_condition(ngx_conf_t if (n) { regex->ncaptures = (n + 1) * 3; - - if (lcf->captures < regex->ncaptures) { - lcf->captures = regex->ncaptures; - } } return NGX_CONF_OK; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -10,6 +10,7 @@ #define NGX_HTTP_MAX_URI_CHANGES 10 #define NGX_HTTP_MAX_SUBREQUESTS 50 +#define NGX_HTTP_MAX_CAPTURES 9 /* must be 2^n */ #define NGX_HTTP_LC_HEADER_LEN 32 @@ -390,6 +391,12 @@ struct ngx_http_request_s { ngx_http_variable_value_t *variables; +#if (NGX_PCRE) + ngx_uint_t ncaptures; + int *captures; + u_char *captures_data; +#endif + size_t limit_rate; /* used to learn the Apache compatible response length without a header */ diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -40,7 +40,9 @@ ngx_http_script_compile(ngx_http_script_ ngx_uint_t i, n, bracket; ngx_http_script_var_code_t *var_code; ngx_http_script_copy_code_t *copy; +#if (NGX_PCRE) ngx_http_script_copy_capture_code_t *copy_capture; +#endif if (sc->flushes && *sc->flushes == NULL) { n = sc->variables ? sc->variables : 1; @@ -89,6 +91,10 @@ ngx_http_script_compile(ngx_http_script_ goto invalid_variable; } +#if (NGX_PCRE) + + /* NGX_HTTP_MAX_CAPTURES is 9 */ + if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { n = sc->source->data[i] - '0'; @@ -130,6 +136,8 @@ ngx_http_script_compile(ngx_http_script_ continue; } +#endif + if (sc->source->data[i] == '{') { bracket = 1; @@ -519,65 +527,6 @@ ngx_http_script_copy_var_code(ngx_http_s size_t -ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e) -{ - ngx_http_script_copy_capture_code_t *code; - - code = (ngx_http_script_copy_capture_code_t *) e->ip; - - e->ip += sizeof(ngx_http_script_copy_capture_code_t); - - if (code->n < e->ncaptures) { - if ((e->is_args || e->quote) - && (e->request->quoted_uri || e->request->plus_in_uri)) - { - return e->captures[code->n + 1] - e->captures[code->n] - + 2 * ngx_escape_uri(NULL, - &e->line.data[e->captures[code->n]], - e->captures[code->n + 1] - e->captures[code->n], - NGX_ESCAPE_ARGS); - } else { - return e->captures[code->n + 1] - e->captures[code->n]; - } - } - - return 0; -} - - -void -ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e) -{ - u_char *p; - ngx_http_script_copy_capture_code_t *code; - - code = (ngx_http_script_copy_capture_code_t *) e->ip; - - e->ip += sizeof(ngx_http_script_copy_capture_code_t); - - p = e->pos; - - if (code->n < e->ncaptures) { - if ((e->is_args || e->quote) - && (e->request->quoted_uri || e->request->plus_in_uri)) - { - e->pos = (u_char *) ngx_escape_uri(p, - &e->line.data[e->captures[code->n]], - e->captures[code->n + 1] - e->captures[code->n], - NGX_ESCAPE_ARGS); - } else { - e->pos = ngx_copy(p, - &e->line.data[e->captures[code->n]], - e->captures[code->n + 1] - e->captures[code->n]); - } - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, - "http script capture: \"%*s\"", e->pos - p, p); -} - - -size_t ngx_http_script_mark_args_code(ngx_http_script_engine_t *e) { e->is_args = 1; @@ -599,7 +548,6 @@ ngx_http_script_start_args_code(ngx_http } - #if (NGX_PCRE) void @@ -628,7 +576,18 @@ ngx_http_script_regex_start_code(ngx_htt e->line.data = e->sp->data; } - rc = ngx_regex_exec(code->regex, &e->line, e->captures, code->ncaptures); + if (code->ncaptures && r->captures == NULL) { + + r->captures = ngx_palloc(r->pool, + (NGX_HTTP_MAX_CAPTURES + 1) * 3 * sizeof(int)); + if (r->captures == NULL) { + e->ip = ngx_http_script_exit; + e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; + return; + } + } + + rc = ngx_regex_exec(code->regex, &e->line, r->captures, code->ncaptures); if (rc == NGX_REGEX_NO_MATCHED) { if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { @@ -637,7 +596,7 @@ ngx_http_script_regex_start_code(ngx_htt &code->name, &e->line); } - e->ncaptures = 0; + r->ncaptures = 0; if (code->test) { if (code->negative_test) { @@ -674,7 +633,8 @@ ngx_http_script_regex_start_code(ngx_htt "\"%V\" matches \"%V\"", &code->name, &e->line); } - e->ncaptures = code->ncaptures; + r->ncaptures = code->ncaptures; + r->captures_data = e->line.data; if (code->test) { if (code->negative_test) { @@ -725,7 +685,7 @@ ngx_http_script_regex_start_code(ngx_htt } for (n = 1; n < (ngx_uint_t) rc; n++) { - e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n]; + e->buf.len += r->captures[2 * n + 1] - r->captures[2 * n]; } } else { @@ -734,8 +694,6 @@ ngx_http_script_regex_start_code(ngx_htt le.ip = code->lengths->elts; le.line = e->line; le.request = r; - le.captures = e->captures; - le.ncaptures = e->ncaptures; le.quote = code->redirect; len = 0; @@ -874,6 +832,84 @@ ngx_http_script_regex_end_code(ngx_http_ e->ip += sizeof(ngx_http_script_regex_end_code_t); } + +size_t +ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e) +{ + int *cap; + u_char *p; + ngx_uint_t n; + ngx_http_request_t *r; + ngx_http_script_copy_capture_code_t *code; + + r = e->request; + + code = (ngx_http_script_copy_capture_code_t *) e->ip; + + e->ip += sizeof(ngx_http_script_copy_capture_code_t); + + n = code->n; + + if (n < r->ncaptures) { + + cap = r->captures; + + if ((e->is_args || e->quote) + && (e->request->quoted_uri || e->request->plus_in_uri)) + { + p = r->captures_data; + + return cap[n + 1] - cap[n] + + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n], + NGX_ESCAPE_ARGS); + } else { + return cap[n + 1] - cap[n]; + } + } + + return 0; +} + + +void +ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e) +{ + int *cap; + u_char *p, *pos; + ngx_uint_t n; + ngx_http_request_t *r; + ngx_http_script_copy_capture_code_t *code; + + r = e->request; + + code = (ngx_http_script_copy_capture_code_t *) e->ip; + + e->ip += sizeof(ngx_http_script_copy_capture_code_t); + + n = code->n; + + pos = e->pos; + + if (n < r->ncaptures) { + + cap = r->captures; + p = r->captures_data; + + if ((e->is_args || e->quote) + && (e->request->quoted_uri || e->request->plus_in_uri)) + { + e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]], + cap[n + 1] - cap[n], + NGX_ESCAPE_ARGS); + } else { + e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]); + } + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, + "http script capture: \"%*s\"", e->pos - pos, pos); +} + #endif @@ -1133,8 +1169,6 @@ ngx_http_script_complex_value_code(ngx_h le.ip = code->lengths->elts; le.line = e->line; le.request = e->request; - le.captures = e->captures; - le.ncaptures = e->ncaptures; le.quote = e->quote; for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) { diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -30,9 +30,6 @@ typedef struct { unsigned is_args:1; unsigned log:1; - int *captures; - ngx_uint_t ncaptures; - ngx_int_t status; ngx_http_request_t *request; } ngx_http_script_engine_t;