Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_rewrite_module.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
13 typedef struct {
14  ngx_array_t *codes; /* uintptr_t */
15 
17 
21 
22 
23 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf);
24 static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf,
25  void *parent, void *child);
26 static ngx_int_t ngx_http_rewrite_init(ngx_conf_t *cf);
27 static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
28 static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd,
29  void *conf);
30 static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd,
31  void *conf);
32 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd,
33  void *conf);
34 static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf,
36 static char *ngx_http_rewrite_variable(ngx_conf_t *cf,
38 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd,
39  void *conf);
40 static char * ngx_http_rewrite_value(ngx_conf_t *cf,
42 
43 
44 static ngx_command_t ngx_http_rewrite_commands[] = {
45 
46  { ngx_string("rewrite"),
49  ngx_http_rewrite,
51  0,
52  NULL },
53 
54  { ngx_string("return"),
57  ngx_http_rewrite_return,
59  0,
60  NULL },
61 
62  { ngx_string("break"),
65  ngx_http_rewrite_break,
67  0,
68  NULL },
69 
70  { ngx_string("if"),
72  ngx_http_rewrite_if,
74  0,
75  NULL },
76 
77  { ngx_string("set"),
80  ngx_http_rewrite_set,
82  0,
83  NULL },
84 
85  { ngx_string("rewrite_log"),
90  offsetof(ngx_http_rewrite_loc_conf_t, log),
91  NULL },
92 
93  { ngx_string("uninitialized_variable_warn"),
98  offsetof(ngx_http_rewrite_loc_conf_t, uninitialized_variable_warn),
99  NULL },
100 
102 };
103 
104 
105 static ngx_http_module_t ngx_http_rewrite_module_ctx = {
106  NULL, /* preconfiguration */
107  ngx_http_rewrite_init, /* postconfiguration */
108 
109  NULL, /* create main configuration */
110  NULL, /* init main configuration */
111 
112  NULL, /* create server configuration */
113  NULL, /* merge server configuration */
114 
115  ngx_http_rewrite_create_loc_conf, /* create location configuration */
116  ngx_http_rewrite_merge_loc_conf /* merge location configuration */
117 };
118 
119 
122  &ngx_http_rewrite_module_ctx, /* module context */
123  ngx_http_rewrite_commands, /* module directives */
124  NGX_HTTP_MODULE, /* module type */
125  NULL, /* init master */
126  NULL, /* init module */
127  NULL, /* init process */
128  NULL, /* init thread */
129  NULL, /* exit thread */
130  NULL, /* exit process */
131  NULL, /* exit master */
133 };
134 
135 
136 static ngx_int_t
137 ngx_http_rewrite_handler(ngx_http_request_t *r)
138 {
145 
148  index = cmcf->phase_engine.location_rewrite_index;
149 
150  if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) {
151  /* skipping location rewrite phase for server null location */
152  return NGX_DECLINED;
153  }
154 
155  rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
156 
157  if (rlcf->codes == NULL) {
158  return NGX_DECLINED;
159  }
160 
161  e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t));
162  if (e == NULL) {
164  }
165 
166  e->sp = ngx_pcalloc(r->pool,
167  rlcf->stack_size * sizeof(ngx_http_variable_value_t));
168  if (e->sp == NULL) {
170  }
171 
172  e->ip = rlcf->codes->elts;
173  e->request = r;
174  e->quote = 1;
175  e->log = rlcf->log;
176  e->status = NGX_DECLINED;
177 
178  while (*(uintptr_t *) e->ip) {
179  code = *(ngx_http_script_code_pt *) e->ip;
180  code(e);
181  }
182 
183  if (e->status < NGX_HTTP_BAD_REQUEST) {
184  return e->status;
185  }
186 
187  if (r->err_status == 0) {
188  return e->status;
189  }
190 
191  return r->err_status;
192 }
193 
194 
195 static ngx_int_t
196 ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v,
197  uintptr_t data)
198 {
199  ngx_http_variable_t *var;
202 
203  rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
204 
205  if (rlcf->uninitialized_variable_warn == 0) {
207  return NGX_OK;
208  }
209 
211 
212  var = cmcf->variables.elts;
213 
214  /*
215  * the ngx_http_rewrite_module sets variables directly in r->variables,
216  * and they should be handled by ngx_http_get_indexed_variable(),
217  * so the handler is called only if the variable is not initialized
218  */
219 
221  "using uninitialized \"%V\" variable", &var[data].name);
222 
224 
225  return NGX_OK;
226 }
227 
228 
229 static void *
230 ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf)
231 {
233 
234  conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t));
235  if (conf == NULL) {
236  return NULL;
237  }
238 
240  conf->log = NGX_CONF_UNSET;
242 
243  return conf;
244 }
245 
246 
247 static char *
248 ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
249 {
250  ngx_http_rewrite_loc_conf_t *prev = parent;
251  ngx_http_rewrite_loc_conf_t *conf = child;
252 
253  uintptr_t *code;
254 
255  ngx_conf_merge_value(conf->log, prev->log, 0);
257  prev->uninitialized_variable_warn, 1);
259 
260  if (conf->codes == NULL) {
261  return NGX_CONF_OK;
262  }
263 
264  if (conf->codes == prev->codes) {
265  return NGX_CONF_OK;
266  }
267 
268  code = ngx_array_push_n(conf->codes, sizeof(uintptr_t));
269  if (code == NULL) {
270  return NGX_CONF_ERROR;
271  }
272 
273  *code = (uintptr_t) NULL;
274 
275  return NGX_CONF_OK;
276 }
277 
278 
279 static ngx_int_t
280 ngx_http_rewrite_init(ngx_conf_t *cf)
281 {
284 
286 
288  if (h == NULL) {
289  return NGX_ERROR;
290  }
291 
292  *h = ngx_http_rewrite_handler;
293 
295  if (h == NULL) {
296  return NGX_ERROR;
297  }
298 
299  *h = ngx_http_rewrite_handler;
300 
301  return NGX_OK;
302 }
303 
304 
305 static char *
306 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
307 {
308  ngx_http_rewrite_loc_conf_t *lcf = conf;
309 
310  ngx_str_t *value;
311  ngx_uint_t last;
315  ngx_http_script_regex_code_t *regex;
316  ngx_http_script_regex_end_code_t *regex_end;
317  u_char errstr[NGX_MAX_CONF_ERRSTR];
318 
319  regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
320  sizeof(ngx_http_script_regex_code_t));
321  if (regex == NULL) {
322  return NGX_CONF_ERROR;
323  }
324 
325  ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
326 
327  value = cf->args->elts;
328 
329  ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
330 
331  rc.pattern = value[1];
333  rc.err.data = errstr;
334 
335  /* TODO: NGX_REGEX_CASELESS */
336 
337  regex->regex = ngx_http_regex_compile(cf, &rc);
338  if (regex->regex == NULL) {
339  return NGX_CONF_ERROR;
340  }
341 
342  regex->code = ngx_http_script_regex_start_code;
343  regex->uri = 1;
344  regex->name = value[1];
345 
346  if (value[2].data[value[2].len - 1] == '?') {
347 
348  /* the last "?" drops the original arguments */
349  value[2].len--;
350 
351  } else {
352  regex->add_args = 1;
353  }
354 
355  last = 0;
356 
357  if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0
358  || ngx_strncmp(value[2].data, "https://", sizeof("https://") - 1) == 0
359  || ngx_strncmp(value[2].data, "$scheme", sizeof("$scheme") - 1) == 0)
360  {
361  regex->status = NGX_HTTP_MOVED_TEMPORARILY;
362  regex->redirect = 1;
363  last = 1;
364  }
365 
366  if (cf->args->nelts == 4) {
367  if (ngx_strcmp(value[3].data, "last") == 0) {
368  last = 1;
369 
370  } else if (ngx_strcmp(value[3].data, "break") == 0) {
371  regex->break_cycle = 1;
372  last = 1;
373 
374  } else if (ngx_strcmp(value[3].data, "redirect") == 0) {
375  regex->status = NGX_HTTP_MOVED_TEMPORARILY;
376  regex->redirect = 1;
377  last = 1;
378 
379  } else if (ngx_strcmp(value[3].data, "permanent") == 0) {
380  regex->status = NGX_HTTP_MOVED_PERMANENTLY;
381  regex->redirect = 1;
382  last = 1;
383 
384  } else {
386  "invalid parameter \"%V\"", &value[3]);
387  return NGX_CONF_ERROR;
388  }
389  }
390 
392 
393  sc.cf = cf;
394  sc.source = &value[2];
395  sc.lengths = &regex->lengths;
396  sc.values = &lcf->codes;
398  sc.main = regex;
399  sc.complete_lengths = 1;
400  sc.compile_args = !regex->redirect;
401 
402  if (ngx_http_script_compile(&sc) != NGX_OK) {
403  return NGX_CONF_ERROR;
404  }
405 
406  regex = sc.main;
407 
408  regex->size = sc.size;
409  regex->args = sc.args;
410 
411  if (sc.variables == 0 && !sc.dup_capture) {
412  regex->lengths = NULL;
413  }
414 
415  regex_end = ngx_http_script_add_code(lcf->codes,
416  sizeof(ngx_http_script_regex_end_code_t),
417  &regex);
418  if (regex_end == NULL) {
419  return NGX_CONF_ERROR;
420  }
421 
422  regex_end->code = ngx_http_script_regex_end_code;
423  regex_end->uri = regex->uri;
424  regex_end->args = regex->args;
425  regex_end->add_args = regex->add_args;
426  regex_end->redirect = regex->redirect;
427 
428  if (last) {
429  code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), &regex);
430  if (code == NULL) {
431  return NGX_CONF_ERROR;
432  }
433 
434  *code = NULL;
435  }
436 
437  regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
438  - (u_char *) regex;
439 
440  return NGX_CONF_OK;
441 }
442 
443 
444 static char *
445 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
446 {
447  ngx_http_rewrite_loc_conf_t *lcf = conf;
448 
449  u_char *p;
450  ngx_str_t *value, *v;
453 
454  ret = ngx_http_script_start_code(cf->pool, &lcf->codes,
456  if (ret == NULL) {
457  return NGX_CONF_ERROR;
458  }
459 
460  value = cf->args->elts;
461 
463 
465 
466  p = value[1].data;
467 
468  ret->status = ngx_atoi(p, value[1].len);
469 
470  if (ret->status == (uintptr_t) NGX_ERROR) {
471 
472  if (cf->args->nelts == 2
473  && (ngx_strncmp(p, "http://", sizeof("http://") - 1) == 0
474  || ngx_strncmp(p, "https://", sizeof("https://") - 1) == 0
475  || ngx_strncmp(p, "$scheme", sizeof("$scheme") - 1) == 0))
476  {
478  v = &value[1];
479 
480  } else {
482  "invalid return code \"%V\"", &value[1]);
483  return NGX_CONF_ERROR;
484  }
485 
486  } else {
487 
488  if (ret->status > 999) {
490  "invalid return code \"%V\"", &value[1]);
491  return NGX_CONF_ERROR;
492  }
493 
494  if (cf->args->nelts == 2) {
495  return NGX_CONF_OK;
496  }
497 
498  v = &value[2];
499  }
500 
502 
503  ccv.cf = cf;
504  ccv.value = v;
505  ccv.complex_value = &ret->text;
506 
507  if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
508  return NGX_CONF_ERROR;
509  }
510 
511  return NGX_CONF_OK;
512 }
513 
514 
515 static char *
516 ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
517 {
518  ngx_http_rewrite_loc_conf_t *lcf = conf;
519 
521 
522  code = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(uintptr_t));
523  if (code == NULL) {
524  return NGX_CONF_ERROR;
525  }
526 
528 
529  return NGX_CONF_OK;
530 }
531 
532 
533 static char *
534 ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
535 {
536  ngx_http_rewrite_loc_conf_t *lcf = conf;
537 
538  void *mconf;
539  char *rv;
540  u_char *elts;
541  ngx_uint_t i;
542  ngx_conf_t save;
543  ngx_http_module_t *module;
544  ngx_http_conf_ctx_t *ctx, *pctx;
545  ngx_http_core_loc_conf_t *clcf, *pclcf;
546  ngx_http_script_if_code_t *if_code;
548 
549  ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
550  if (ctx == NULL) {
551  return NGX_CONF_ERROR;
552  }
553 
554  pctx = cf->ctx;
555  ctx->main_conf = pctx->main_conf;
556  ctx->srv_conf = pctx->srv_conf;
557 
558  ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
559  if (ctx->loc_conf == NULL) {
560  return NGX_CONF_ERROR;
561  }
562 
563  for (i = 0; ngx_modules[i]; i++) {
564  if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
565  continue;
566  }
567 
568  module = ngx_modules[i]->ctx;
569 
570  if (module->create_loc_conf) {
571 
572  mconf = module->create_loc_conf(cf);
573  if (mconf == NULL) {
574  return NGX_CONF_ERROR;
575  }
576 
577  ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
578  }
579  }
580 
581  pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
582 
584  clcf->loc_conf = ctx->loc_conf;
585  clcf->name = pclcf->name;
586  clcf->noname = 1;
587 
588  if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
589  return NGX_CONF_ERROR;
590  }
591 
592  if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) {
593  return NGX_CONF_ERROR;
594  }
595 
596  if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t));
597  if (if_code == NULL) {
598  return NGX_CONF_ERROR;
599  }
600 
601  if_code->code = ngx_http_script_if_code;
602 
603  elts = lcf->codes->elts;
604 
605 
606  /* the inner directives must be compiled to the same code array */
607 
608  nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index];
609  nlcf->codes = lcf->codes;
610 
611 
612  save = *cf;
613  cf->ctx = ctx;
614 
615  if (pclcf->name.len == 0) {
616  if_code->loc_conf = NULL;
618 
619  } else {
620  if_code->loc_conf = ctx->loc_conf;
622  }
623 
624  rv = ngx_conf_parse(cf, NULL);
625 
626  *cf = save;
627 
628  if (rv != NGX_CONF_OK) {
629  return rv;
630  }
631 
632 
633  if (elts != lcf->codes->elts) {
634  if_code = (ngx_http_script_if_code_t *)
635  ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts));
636  }
637 
638  if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
639  - (u_char *) if_code;
640 
641  /* the code array belong to parent block */
642 
643  nlcf->codes = NULL;
644 
645  return NGX_CONF_OK;
646 }
647 
648 
649 static char *
650 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
651 {
652  u_char *p;
653  size_t len;
654  ngx_str_t *value;
655  ngx_uint_t cur, last;
659  ngx_http_script_regex_code_t *regex;
660  u_char errstr[NGX_MAX_CONF_ERRSTR];
661 
662  value = cf->args->elts;
663  last = cf->args->nelts - 1;
664 
665  if (value[1].len < 1 || value[1].data[0] != '(') {
667  "invalid condition \"%V\"", &value[1]);
668  return NGX_CONF_ERROR;
669  }
670 
671  if (value[1].len == 1) {
672  cur = 2;
673 
674  } else {
675  cur = 1;
676  value[1].len--;
677  value[1].data++;
678  }
679 
680  if (value[last].len < 1 || value[last].data[value[last].len - 1] != ')') {
682  "invalid condition \"%V\"", &value[last]);
683  return NGX_CONF_ERROR;
684  }
685 
686  if (value[last].len == 1) {
687  last--;
688 
689  } else {
690  value[last].len--;
691  value[last].data[value[last].len] = '\0';
692  }
693 
694  len = value[cur].len;
695  p = value[cur].data;
696 
697  if (len > 1 && p[0] == '$') {
698 
699  if (cur != last && cur + 2 != last) {
701  "invalid condition \"%V\"", &value[cur]);
702  return NGX_CONF_ERROR;
703  }
704 
705  if (ngx_http_rewrite_variable(cf, lcf, &value[cur]) != NGX_CONF_OK) {
706  return NGX_CONF_ERROR;
707  }
708 
709  if (cur == last) {
710  return NGX_CONF_OK;
711  }
712 
713  cur++;
714 
715  len = value[cur].len;
716  p = value[cur].data;
717 
718  if (len == 1 && p[0] == '=') {
719 
720  if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
721  return NGX_CONF_ERROR;
722  }
723 
724  code = ngx_http_script_start_code(cf->pool, &lcf->codes,
725  sizeof(uintptr_t));
726  if (code == NULL) {
727  return NGX_CONF_ERROR;
728  }
729 
731 
732  return NGX_CONF_OK;
733  }
734 
735  if (len == 2 && p[0] == '!' && p[1] == '=') {
736 
737  if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
738  return NGX_CONF_ERROR;
739  }
740 
741  code = ngx_http_script_start_code(cf->pool, &lcf->codes,
742  sizeof(uintptr_t));
743  if (code == NULL) {
744  return NGX_CONF_ERROR;
745  }
746 
748  return NGX_CONF_OK;
749  }
750 
751  if ((len == 1 && p[0] == '~')
752  || (len == 2 && p[0] == '~' && p[1] == '*')
753  || (len == 2 && p[0] == '!' && p[1] == '~')
754  || (len == 3 && p[0] == '!' && p[1] == '~' && p[2] == '*'))
755  {
756  regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
757  sizeof(ngx_http_script_regex_code_t));
758  if (regex == NULL) {
759  return NGX_CONF_ERROR;
760  }
761 
762  ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
763 
764  ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
765 
766  rc.pattern = value[last];
767  rc.options = (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0;
769  rc.err.data = errstr;
770 
771  regex->regex = ngx_http_regex_compile(cf, &rc);
772  if (regex->regex == NULL) {
773  return NGX_CONF_ERROR;
774  }
775 
776  regex->code = ngx_http_script_regex_start_code;
777  regex->next = sizeof(ngx_http_script_regex_code_t);
778  regex->test = 1;
779  if (p[0] == '!') {
780  regex->negative_test = 1;
781  }
782  regex->name = value[last];
783 
784  return NGX_CONF_OK;
785  }
786 
788  "unexpected \"%V\" in condition", &value[cur]);
789  return NGX_CONF_ERROR;
790 
791  } else if ((len == 2 && p[0] == '-')
792  || (len == 3 && p[0] == '!' && p[1] == '-'))
793  {
794  if (cur + 1 != last) {
796  "invalid condition \"%V\"", &value[cur]);
797  return NGX_CONF_ERROR;
798  }
799 
800  value[last].data[value[last].len] = '\0';
801  value[last].len++;
802 
803  if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
804  return NGX_CONF_ERROR;
805  }
806 
807  fop = ngx_http_script_start_code(cf->pool, &lcf->codes,
809  if (fop == NULL) {
810  return NGX_CONF_ERROR;
811  }
812 
814 
815  if (p[1] == 'f') {
817  return NGX_CONF_OK;
818  }
819 
820  if (p[1] == 'd') {
822  return NGX_CONF_OK;
823  }
824 
825  if (p[1] == 'e') {
827  return NGX_CONF_OK;
828  }
829 
830  if (p[1] == 'x') {
832  return NGX_CONF_OK;
833  }
834 
835  if (p[0] == '!') {
836  if (p[2] == 'f') {
838  return NGX_CONF_OK;
839  }
840 
841  if (p[2] == 'd') {
843  return NGX_CONF_OK;
844  }
845 
846  if (p[2] == 'e') {
848  return NGX_CONF_OK;
849  }
850 
851  if (p[2] == 'x') {
853  return NGX_CONF_OK;
854  }
855  }
856 
858  "invalid condition \"%V\"", &value[cur]);
859  return NGX_CONF_ERROR;
860  }
861 
863  "invalid condition \"%V\"", &value[cur]);
864 
865  return NGX_CONF_ERROR;
866 }
867 
868 
869 static char *
870 ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
871  ngx_str_t *value)
872 {
874  ngx_http_script_var_code_t *var_code;
875 
876  value->len--;
877  value->data++;
878 
879  index = ngx_http_get_variable_index(cf, value);
880 
881  if (index == NGX_ERROR) {
882  return NGX_CONF_ERROR;
883  }
884 
885  var_code = ngx_http_script_start_code(cf->pool, &lcf->codes,
887  if (var_code == NULL) {
888  return NGX_CONF_ERROR;
889  }
890 
891  var_code->code = ngx_http_script_var_code;
892  var_code->index = index;
893 
894  return NGX_CONF_OK;
895 }
896 
897 
898 static char *
899 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
900 {
901  ngx_http_rewrite_loc_conf_t *lcf = conf;
902 
904  ngx_str_t *value;
908 
909  value = cf->args->elts;
910 
911  if (value[1].data[0] != '$') {
913  "invalid variable name \"%V\"", &value[1]);
914  return NGX_CONF_ERROR;
915  }
916 
917  value[1].len--;
918  value[1].data++;
919 
921  if (v == NULL) {
922  return NGX_CONF_ERROR;
923  }
924 
925  index = ngx_http_get_variable_index(cf, &value[1]);
926  if (index == NGX_ERROR) {
927  return NGX_CONF_ERROR;
928  }
929 
930  if (v->get_handler == NULL
931  && ngx_strncasecmp(value[1].data, (u_char *) "http_", 5) != 0
932  && ngx_strncasecmp(value[1].data, (u_char *) "sent_http_", 10) != 0
933  && ngx_strncasecmp(value[1].data, (u_char *) "upstream_http_", 14) != 0)
934  {
935  v->get_handler = ngx_http_rewrite_var;
936  v->data = index;
937  }
938 
939  if (ngx_http_rewrite_value(cf, lcf, &value[2]) != NGX_CONF_OK) {
940  return NGX_CONF_ERROR;
941  }
942 
943  if (v->set_handler) {
944  vhcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
946  if (vhcode == NULL) {
947  return NGX_CONF_ERROR;
948  }
949 
951  vhcode->handler = v->set_handler;
952  vhcode->data = v->data;
953 
954  return NGX_CONF_OK;
955  }
956 
957  vcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
959  if (vcode == NULL) {
960  return NGX_CONF_ERROR;
961  }
962 
964  vcode->index = (uintptr_t) index;
965 
966  return NGX_CONF_OK;
967 }
968 
969 
970 static char *
971 ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
972  ngx_str_t *value)
973 {
974  ngx_int_t n;
978 
980 
981  if (n == 0) {
982  val = ngx_http_script_start_code(cf->pool, &lcf->codes,
984  if (val == NULL) {
985  return NGX_CONF_ERROR;
986  }
987 
988  n = ngx_atoi(value->data, value->len);
989 
990  if (n == NGX_ERROR) {
991  n = 0;
992  }
993 
995  val->value = (uintptr_t) n;
996  val->text_len = (uintptr_t) value->len;
997  val->text_data = (uintptr_t) value->data;
998 
999  return NGX_CONF_OK;
1000  }
1001 
1002  complex = ngx_http_script_start_code(cf->pool, &lcf->codes,
1004  if (complex == NULL) {
1005  return NGX_CONF_ERROR;
1006  }
1007 
1009  complex->lengths = NULL;
1010 
1011  ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
1012 
1013  sc.cf = cf;
1014  sc.source = value;
1015  sc.lengths = &complex->lengths;
1016  sc.values = &lcf->codes;
1017  sc.variables = n;
1018  sc.complete_lengths = 1;
1019 
1020  if (ngx_http_script_compile(&sc) != NGX_OK) {
1021  return NGX_CONF_ERROR;
1022  }
1023 
1024  return NGX_CONF_OK;
1025 }