diff src/http/modules/ngx_http_rewrite_module.c @ 126:df17fbafec8f NGINX_0_3_10

nginx 0.3.10 *) Change: the "valid_referers" directive and the "$invalid_referer" variable were moved to the new ngx_http_referer_module from the ngx_http_rewrite_module. *) Change: the "$apache_bytes_sent" variable name was changed to "$body_bytes_sent". *) Feature: the "$sent_http_..." variables. *) Feature: the "if" directive supports the "=" and "!=" operations. *) Feature: the "proxy_pass" directive supports the HTTPS protocol. *) Feature: the "proxy_set_body" directive. *) Feature: the "post_action" directive. *) Feature: the ngx_http_empty_gif_module. *) Feature: the "worker_cpu_affinity" directive for Linux. *) Bugfix: the "rewrite" directive did not unescape URI part in redirect, now it is unescaped except the %00-%25 and %7F-%FF characters. *) Bugfix: nginx could not be built by the icc 9.0 compiler. *) Bugfix: if the SSI was enabled for zero size static file, then the chunked response was encoded incorrectly.
author Igor Sysoev <http://sysoev.ru>
date Tue, 15 Nov 2005 00:00:00 +0300
parents d25a1d6034f1
children 4cd3e70c4d60
line wrap: on
line diff
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -10,22 +10,12 @@
 
 
 typedef struct {
-    ngx_str_t                   name;
-    ngx_uint_t                  wildcard;
-} ngx_http_rewrite_referer_t;
-
+    ngx_array_t  *codes;        /* uintptr_t */
 
-typedef struct {
-    ngx_array_t                *codes;        /* uintptr_t */
-    ngx_array_t                *referers;     /* ngx_http_rewrite_referer_t */
+    ngx_uint_t    captures;
+    ngx_uint_t    stack_size;
 
-    ngx_uint_t                  captures;
-    ngx_uint_t                  stack_size;
-
-    ngx_flag_t                  log;
-
-    ngx_flag_t                  no_referer;
-    ngx_flag_t                  blocked_referer;
+    ngx_flag_t    log;
 } ngx_http_rewrite_loc_conf_t;
 
 
@@ -44,10 +34,10 @@ static char * ngx_http_rewrite_if_condit
     ngx_http_rewrite_loc_conf_t *lcf);
 static char *ngx_http_rewrite_variable(ngx_conf_t *cf,
     ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value);
-static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf,
-    ngx_command_t *cmd, void *conf);
 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static char * ngx_http_rewrite_value(ngx_conf_t *cf,
+    ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value);
 
 
 static ngx_command_t  ngx_http_rewrite_commands[] = {
@@ -83,12 +73,14 @@ static ngx_command_t  ngx_http_rewrite_c
       0,
       NULL },
 
+#if 0
     { ngx_string("valid_referers"),
       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
       ngx_http_rewrite_valid_referers,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
       NULL },
+#endif
 
     { ngx_string("set"),
       NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
@@ -127,7 +119,7 @@ ngx_http_module_t  ngx_http_rewrite_modu
 
 ngx_module_t  ngx_http_rewrite_module = {
     NGX_MODULE_V1,
-    &ngx_http_rewrite_module_ctx,          /* module context */ 
+    &ngx_http_rewrite_module_ctx,          /* module context */
     ngx_http_rewrite_commands,             /* module directives */
     NGX_HTTP_MODULE,                       /* module type */
     NULL,                                  /* init master */
@@ -141,10 +133,6 @@ ngx_module_t  ngx_http_rewrite_module = 
 };
 
 
-static ngx_http_variable_value_t  ngx_http_rewrite_null_value =
-    ngx_http_variable("");
-
-
 static ngx_int_t
 ngx_http_rewrite_handler(ngx_http_request_t *r)
 {
@@ -194,121 +182,6 @@ ngx_http_rewrite_handler(ngx_http_reques
 }
 
 
-static void
-ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e)
-{
-    u_char                       *ref;
-    size_t                        len;
-    ngx_uint_t                    i, n;
-    ngx_http_request_t           *r;
-    ngx_http_rewrite_referer_t   *refs;
-    ngx_http_rewrite_loc_conf_t  *cf;
-
-    r = e->request;
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http rewrite invalid referer");
-
-    cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
-
-    e->ip += sizeof(uintptr_t);
-
-    if (cf->referers == NULL) {
-        e->sp->data = (u_char *) "";
-        e->sp->len = 0;
-        e->sp++;
-
-        return;
-    }
-
-    if (r->headers_in.referer == NULL) {
-        if (cf->no_referer) {
-            e->sp->data = (u_char *) "";
-            e->sp->len = 0;
-            e->sp++;
-
-            return;
-
-        } else {
-            e->sp->data = (u_char *) "1";
-            e->sp->len = 1;
-            e->sp++;
-
-            return;
-        }
-    }
-
-    len = r->headers_in.referer->value.len;
-    ref = r->headers_in.referer->value.data;
-
-    if (len < sizeof("http://i.ru") - 1
-        || (ngx_strncasecmp(ref, "http://", 7) != 0))
-    {
-        if (cf->blocked_referer) {
-            e->sp->data = (u_char *) "";
-            e->sp->len = 0;
-            e->sp++;
-
-            return;
-
-        } else {
-            e->sp->data = (u_char *) "1";
-            e->sp->len = 1;
-            e->sp++;
-
-            return;
-        }
-    }
-
-    len -= 7;
-    ref += 7;
-
-    refs = cf->referers->elts;
-    for (i = 0; i < cf->referers->nelts; i++ ){
-
-        if (refs[i].name.len > len) {
-            continue;
-        }
-
-        if (refs[i].wildcard) {
-            for (n = 0; n < len; n++) {
-                if (ref[n] == '/' || ref[n] == ':') {
-                    break;
-                }
-
-                if (ref[n] != '.') {
-                    continue;
-                }
-
-                if (ngx_strncmp(&ref[n], refs[i].name.data,
-                                refs[i].name.len) == 0)
-                {
-                    e->sp->data = (u_char *) "";
-                    e->sp->len = 0;
-                    e->sp++;
-
-                    return;
-                }
-            }
-
-        } else {
-            if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0)
-            {
-                e->sp->data = (u_char *) "";
-                e->sp->len = 0;
-                e->sp++;
-
-                return;
-            }
-        }
-    }
-
-    e->sp->data = (u_char *) "1";
-    e->sp->len = 1;
-    e->sp++;
-}
-
-
 static ngx_int_t
 ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v,
     uintptr_t data)
@@ -329,7 +202,7 @@ ngx_http_rewrite_var(ngx_http_request_t 
     ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                   "using uninitialized \"%V\" variable", &var[data].name);
 
-    *v = ngx_http_rewrite_null_value;
+    *v = ngx_http_variable_null_value;
 
     return NGX_OK;
 }
@@ -347,8 +220,6 @@ ngx_http_rewrite_create_loc_conf(ngx_con
 
     conf->stack_size = NGX_CONF_UNSET_UINT;
     conf->log = NGX_CONF_UNSET;
-    conf->no_referer = NGX_CONF_UNSET;
-    conf->blocked_referer = NGX_CONF_UNSET;
 
     return conf;
 }
@@ -365,20 +236,6 @@ ngx_http_rewrite_merge_loc_conf(ngx_conf
     ngx_conf_merge_value(conf->log, prev->log, 0);
     ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10);
 
-    if (conf->referers == NULL) {
-        conf->referers = prev->referers;
-        ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
-        ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
-    }
-
-    if (conf->no_referer == NGX_CONF_UNSET) {
-        conf->no_referer = 0;
-    }
-
-    if (conf->blocked_referer == NGX_CONF_UNSET) {
-        conf->blocked_referer = 0;
-    }
-
     if (conf->codes == NULL) {
         return NGX_CONF_OK;
     }
@@ -400,7 +257,7 @@ ngx_http_rewrite_merge_loc_conf(ngx_conf
 
 static ngx_int_t
 ngx_http_rewrite_init(ngx_cycle_t *cycle)
-{   
+{
     ngx_http_handler_pt        *h;
     ngx_http_core_main_conf_t  *cmcf;
 
@@ -421,14 +278,14 @@ ngx_http_rewrite_init(ngx_cycle_t *cycle
     *h = ngx_http_rewrite_handler;
 
     return NGX_OK;
-}   
+}
 
 
 static char *
 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
-    
+    ngx_http_rewrite_loc_conf_t  *lcf = conf;
+
     ngx_str_t                         *value, err;
     ngx_int_t                          n;
     ngx_uint_t                         last;
@@ -592,7 +449,7 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com
 static char *
 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
+    ngx_http_rewrite_loc_conf_t  *lcf = conf;
 
     ngx_str_t                      *value;
     ngx_http_script_return_code_t  *ret;
@@ -639,7 +496,7 @@ ngx_http_rewrite_break(ngx_conf_t *cf, n
 static char *
 ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
+    ngx_http_rewrite_loc_conf_t  *lcf = conf;
 
     void                         *mconf;
     char                         *rv;
@@ -659,7 +516,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_
 
     pctx = cf->ctx;
     ctx->main_conf = pctx->main_conf;
-    ctx->srv_conf = pctx->srv_conf; 
+    ctx->srv_conf = pctx->srv_conf;
 
     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
     if (ctx->loc_conf == NULL) {
@@ -672,7 +529,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_
         }
 
         module = ngx_modules[i]->ctx;
-    
+
         if (module->create_loc_conf) {
 
             mconf = module->create_loc_conf(cf);
@@ -774,6 +631,7 @@ ngx_http_rewrite_if_condition(ngx_conf_t
 {
     ngx_str_t                     *value, err;
     ngx_uint_t                     cur, last, n;
+    ngx_http_script_code_pt       *code;
     ngx_http_script_regex_code_t  *regex;
     u_char                         errstr[NGX_MAX_CONF_ERRSTR];
 
@@ -817,7 +675,7 @@ ngx_http_rewrite_if_condition(ngx_conf_t
             return NGX_CONF_ERROR;
         }
 
-        if (ngx_http_rewrite_variable(cf, lcf, &value[cur])!= NGX_CONF_OK) {
+        if (ngx_http_rewrite_variable(cf, lcf, &value[cur]) != NGX_CONF_OK) {
             return NGX_CONF_ERROR;
         }
 
@@ -827,51 +685,85 @@ ngx_http_rewrite_if_condition(ngx_conf_t
 
         cur++;
 
-        if ((value[cur].len == 1 && value[cur].data[0] != '~')
-            || (value[cur].len == 2
-                && value[cur].data[0] != '~' && value[cur].data[1] != '*'))
-        {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "unexpected \"%V\" in condition", &value[cur]);
-            return NGX_CONF_ERROR;
+        if (value[cur].len == 1 && value[cur].data[0] == '=') {
+
+            if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
+                return NGX_CONF_ERROR;
+            }
+
+            code = ngx_http_script_start_code(cf->pool, &lcf->codes,
+                                              sizeof(uintptr_t));
+            if (code == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            *code = ngx_http_script_equal_code;
+
+            return NGX_CONF_OK;
         }
 
-        regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
-                                         sizeof(ngx_http_script_regex_code_t));
-        if (regex == NULL) {
-            return NGX_CONF_ERROR;
+        if (value[cur].len == 2
+            && value[cur].data[0] == '!' && value[cur].data[1] == '=')
+        {
+            if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
+                return NGX_CONF_ERROR;
+            }
+
+            code = ngx_http_script_start_code(cf->pool, &lcf->codes,
+                                              sizeof(uintptr_t));
+            if (code == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            *code = ngx_http_script_not_equal_code;
+            return NGX_CONF_OK;
         }
 
-        ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
+        if ((value[cur].len == 1 && value[cur].data[0] == '~')
+            || (value[cur].len == 2
+                && value[cur].data[0] == '~' && value[cur].data[1] == '*'))
+        {
+            regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
+                                         sizeof(ngx_http_script_regex_code_t));
+            if (regex == NULL) {
+                return NGX_CONF_ERROR;
+            }
 
-        err.len = NGX_MAX_CONF_ERRSTR;
-        err.data = errstr;
+            ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
+
+            err.len = NGX_MAX_CONF_ERRSTR;
+            err.data = errstr;
+
+            regex->regex = ngx_regex_compile(&value[last],
+                                 (value[cur].len == 2) ? NGX_REGEX_CASELESS : 0,
+                                 cf->pool, &err);
 
-        regex->regex = ngx_regex_compile(&value[last],
-                                (value[cur].len == 2) ? NGX_REGEX_CASELESS : 0,
-                                cf->pool, &err);
+            if (regex->regex == NULL) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+                return NGX_CONF_ERROR;
+            }
+
+            regex->code = ngx_http_script_regex_start_code;
+            regex->next = sizeof(ngx_http_script_regex_code_t);
+            regex->test = 1;
+            regex->name = value[last];
 
-        if (regex->regex == NULL) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
-            return NGX_CONF_ERROR;
+            n = ngx_regex_capture_count(regex->regex);
+
+            if (n) {
+                regex->ncaptures = (n + 1) * 3;
+
+                if (lcf->captures < regex->ncaptures) {
+                    lcf->captures = regex->ncaptures;
+                }
+            }
+
+            return NGX_CONF_OK;
         }
 
-        regex->code = ngx_http_script_regex_start_code;
-        regex->next = sizeof(ngx_http_script_regex_code_t);
-        regex->test = 1;
-        regex->name = value[last];
-
-        n = ngx_regex_capture_count(regex->regex);
-
-        if (n) {
-            regex->ncaptures = (n + 1) * 3;
-
-            if (lcf->captures < regex->ncaptures) {
-                lcf->captures = regex->ncaptures;
-            }
-        }
-
-        return NGX_CONF_OK;
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "unexpected \"%V\" in condition", &value[cur]);
+        return NGX_CONF_ERROR;
     }
 
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -886,135 +778,25 @@ ngx_http_rewrite_variable(ngx_conf_t *cf
     ngx_str_t *value)
 {
     ngx_int_t                    index;
-    ngx_http_script_code_pt     *code;
     ngx_http_script_var_code_t  *var_code;
 
     value->len--;
     value->data++;
 
-    if (value->len == sizeof("invalid_referer") - 1
-        && ngx_strncmp(value->data, "invalid_referer",
-                       sizeof("invalid_referer") - 1) == 0)
-    {
-        code = ngx_http_script_start_code(cf->pool, &lcf->codes,
-                                          sizeof(ngx_http_script_code_pt));
-        if (code == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        *code = ngx_http_rewrite_invalid_referer_code;
-
-    } else {
-        index = ngx_http_get_variable_index(cf, value);
-
-        if (index == NGX_ERROR) {
-            return NGX_CONF_ERROR;
-        }
-
-        var_code = ngx_http_script_start_code(cf->pool, &lcf->codes,
-                                           sizeof(ngx_http_script_var_code_t));
-        if (var_code == NULL) {
-            return NGX_CONF_ERROR;
-        }
+    index = ngx_http_get_variable_index(cf, value);
 
-        var_code->code = ngx_http_script_var_code;
-        var_code->index = index;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
-
-    ngx_uint_t                   i, server_names;
-    ngx_str_t                   *value;
-    ngx_http_server_name_t      *sn;
-    ngx_http_core_srv_conf_t    *cscf;
-    ngx_http_rewrite_referer_t  *ref;
-
-    cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
-
-    if (lcf->referers == NULL) {
-        lcf->referers = ngx_array_create(cf->pool,
-                                    cf->args->nelts + cscf->server_names.nelts,
-                                    sizeof(ngx_http_rewrite_referer_t));
-        if (lcf->referers == NULL) {
-            return NGX_CONF_ERROR;
-        }
+    if (index == NGX_ERROR) {
+        return NGX_CONF_ERROR;
     }
 
-    value = cf->args->elts;
-    server_names = 0;
-
-    for (i = 1; i < cf->args->nelts; i++) {
-        if (value[i].len == 0) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid referer \"%V\"", &value[i]);
-            return NGX_CONF_ERROR;
-        }
-
-        if (ngx_strcmp(value[i].data, "none") == 0) {
-            lcf->no_referer = 1;
-            continue;
-        }
-
-        if (ngx_strcmp(value[i].data, "blocked") == 0) {
-            lcf->blocked_referer = 1;
-            continue;
-        }
-
-        if (ngx_strcmp(value[i].data, "server_names") == 0) {
-            server_names = 1;
-            continue;
-        }
-
-        ref = ngx_array_push(lcf->referers);
-        if (ref == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        if (value[i].data[0] != '*') {
-            ref->name = value[i];
-            ref->wildcard = 0;
-            continue;
-        }
-
-        if (value[i].data[1] != '.') {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid wildcard referer \"%V\"", &value[i]);
-            return NGX_CONF_ERROR;
-        }
-
-        ref->name.len = value[i].len - 1;
-        ref->name.data = value[i].data + 1;
-        ref->wildcard = 1;
+    var_code = ngx_http_script_start_code(cf->pool, &lcf->codes,
+                                          sizeof(ngx_http_script_var_code_t));
+    if (var_code == NULL) {
+        return NGX_CONF_ERROR;
     }
 
-    if (!server_names) {
-        return NGX_CONF_OK;
-    }
-
-    sn = cscf->server_names.elts;
-    for (i = 0; i < cscf->server_names.nelts; i++) {
-        ref = ngx_array_push(lcf->referers);
-        if (ref == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        ref->name.len = sn[i].name.len + 1;
-        ref->name.data = ngx_palloc(cf->pool, ref->name.len);
-        if (ref->name.data == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        ngx_memcpy(ref->name.data, sn[i].name.data, sn[i].name.len);
-        ref->name.data[sn[i].name.len] = '/';
-        ref->wildcard = sn[i].wildcard;
-    }
+    var_code->code = ngx_http_script_var_code;
+    var_code->index = index;
 
     return NGX_CONF_OK;
 }
@@ -1023,15 +805,12 @@ ngx_http_rewrite_valid_referers(ngx_conf
 static char *
 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
+    ngx_http_rewrite_loc_conf_t  *lcf = conf;
 
-    ngx_int_t                              n, index;
-    ngx_str_t                             *value;
-    ngx_http_variable_t                   *v;
-    ngx_http_script_compile_t              sc;
-    ngx_http_script_var_code_t            *var;
-    ngx_http_script_value_code_t          *val;
-    ngx_http_script_complex_value_code_t  *complex;
+    ngx_int_t                     index;
+    ngx_str_t                    *value;
+    ngx_http_variable_t          *v;
+    ngx_http_script_var_code_t   *var;
 
     value = cf->args->elts;
 
@@ -1059,48 +838,8 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx
         v->data = index;
     }
 
-    n = ngx_http_script_variables_count(&value[2]);
-
-    if (n == 0) {
-        val = ngx_http_script_start_code(cf->pool, &lcf->codes,
-                                         sizeof(ngx_http_script_value_code_t));
-        if (val == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        n = ngx_atoi(value[2].data, value[2].len);
-
-        if (n == NGX_ERROR) {
-            n = 0;
-        }
-
-        val->code = ngx_http_script_value_code;
-        val->value = (uintptr_t) n;
-        val->text_len = (uintptr_t) value[2].len;
-        val->text_data = (uintptr_t) value[2].data;
-
-    } else {
-        complex = ngx_http_script_start_code(cf->pool, &lcf->codes,
-                                 sizeof(ngx_http_script_complex_value_code_t));
-        if (complex == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        complex->code = ngx_http_script_complex_value_code;
-        complex->lengths = NULL;
-
-        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
-        sc.cf = cf; 
-        sc.source = &value[2];
-        sc.lengths = &complex->lengths;
-        sc.values = &lcf->codes;
-        sc.variables = n;
-        sc.complete_lengths = 1;
-
-        if (ngx_http_script_compile(&sc) != NGX_OK) {
-            return NGX_CONF_ERROR;
-        }
+    if (ngx_http_rewrite_value(cf, lcf, &value[2]) != NGX_CONF_OK) {
+        return NGX_CONF_ERROR;
     }
 
     var = ngx_http_script_start_code(cf->pool, &lcf->codes,
@@ -1114,3 +853,61 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx
 
     return NGX_CONF_OK;
 }
+
+
+static char *
+ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
+    ngx_str_t *value)
+{
+    ngx_int_t                              n;
+    ngx_http_script_compile_t              sc;
+    ngx_http_script_value_code_t          *val;
+    ngx_http_script_complex_value_code_t  *complex;
+
+    n = ngx_http_script_variables_count(value);
+
+    if (n == 0) {
+        val = ngx_http_script_start_code(cf->pool, &lcf->codes,
+                                         sizeof(ngx_http_script_value_code_t));
+        if (val == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        n = ngx_atoi(value->data, value->len);
+
+        if (n == NGX_ERROR) {
+            n = 0;
+        }
+
+        val->code = ngx_http_script_value_code;
+        val->value = (uintptr_t) n;
+        val->text_len = (uintptr_t) value->len;
+        val->text_data = (uintptr_t) value->data;
+
+        return NGX_CONF_OK;
+    }
+
+    complex = ngx_http_script_start_code(cf->pool, &lcf->codes,
+                                 sizeof(ngx_http_script_complex_value_code_t));
+    if (complex == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    complex->code = ngx_http_script_complex_value_code;
+    complex->lengths = NULL;
+
+    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+    sc.cf = cf;
+    sc.source = value;
+    sc.lengths = &complex->lengths;
+    sc.values = &lcf->codes;
+    sc.variables = n;
+    sc.complete_lengths = 1;
+
+    if (ngx_http_script_compile(&sc) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}