3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
14 ngx_array_t
*codes
; /* uintptr_t */
16 ngx_uint_t stack_size
;
19 ngx_flag_t uninitialized_variable_warn
;
20 } ngx_http_rewrite_loc_conf_t
;
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
,
30 static char *ngx_http_rewrite_break(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
32 static char *ngx_http_rewrite_if(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
34 static char * ngx_http_rewrite_if_condition(ngx_conf_t
*cf
,
35 ngx_http_rewrite_loc_conf_t
*lcf
);
36 static char *ngx_http_rewrite_variable(ngx_conf_t
*cf
,
37 ngx_http_rewrite_loc_conf_t
*lcf
, ngx_str_t
*value
);
38 static char *ngx_http_rewrite_set(ngx_conf_t
*cf
, ngx_command_t
*cmd
,
40 static char * ngx_http_rewrite_value(ngx_conf_t
*cf
,
41 ngx_http_rewrite_loc_conf_t
*lcf
, ngx_str_t
*value
);
44 static ngx_command_t ngx_http_rewrite_commands
[] = {
46 { ngx_string("rewrite"),
47 NGX_HTTP_SRV_CONF
|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
50 NGX_HTTP_LOC_CONF_OFFSET
,
54 { ngx_string("return"),
55 NGX_HTTP_SRV_CONF
|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
57 ngx_http_rewrite_return
,
58 NGX_HTTP_LOC_CONF_OFFSET
,
62 { ngx_string("break"),
63 NGX_HTTP_SRV_CONF
|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
65 ngx_http_rewrite_break
,
66 NGX_HTTP_LOC_CONF_OFFSET
,
71 NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF
|NGX_CONF_BLOCK
|NGX_CONF_1MORE
,
73 NGX_HTTP_LOC_CONF_OFFSET
,
78 NGX_HTTP_SRV_CONF
|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF
|NGX_HTTP_LIF_CONF
81 NGX_HTTP_LOC_CONF_OFFSET
,
85 { ngx_string("rewrite_log"),
86 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF
87 |NGX_HTTP_LIF_CONF
|NGX_CONF_FLAG
,
88 ngx_conf_set_flag_slot
,
89 NGX_HTTP_LOC_CONF_OFFSET
,
90 offsetof(ngx_http_rewrite_loc_conf_t
, log
),
93 { ngx_string("uninitialized_variable_warn"),
94 NGX_HTTP_MAIN_CONF
|NGX_HTTP_SRV_CONF
|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF
95 |NGX_HTTP_LIF_CONF
|NGX_CONF_FLAG
,
96 ngx_conf_set_flag_slot
,
97 NGX_HTTP_LOC_CONF_OFFSET
,
98 offsetof(ngx_http_rewrite_loc_conf_t
, uninitialized_variable_warn
),
105 static ngx_http_module_t ngx_http_rewrite_module_ctx
= {
106 NULL
, /* preconfiguration */
107 ngx_http_rewrite_init
, /* postconfiguration */
109 NULL
, /* create main configuration */
110 NULL
, /* init main configuration */
112 NULL
, /* create server configuration */
113 NULL
, /* merge server configuration */
115 ngx_http_rewrite_create_loc_conf
, /* create location configuration */
116 ngx_http_rewrite_merge_loc_conf
/* merge location configuration */
120 ngx_module_t ngx_http_rewrite_module
= {
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 */
132 NGX_MODULE_V1_PADDING
137 ngx_http_rewrite_handler(ngx_http_request_t
*r
)
140 ngx_http_script_code_pt code
;
141 ngx_http_script_engine_t
*e
;
142 ngx_http_core_srv_conf_t
*cscf
;
143 ngx_http_core_main_conf_t
*cmcf
;
144 ngx_http_rewrite_loc_conf_t
*rlcf
;
146 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
147 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
148 index
= cmcf
->phase_engine
.location_rewrite_index
;
150 if (r
->phase_handler
== index
&& r
->loc_conf
== cscf
->ctx
->loc_conf
) {
151 /* skipping location rewrite phase for server null location */
155 rlcf
= ngx_http_get_module_loc_conf(r
, ngx_http_rewrite_module
);
157 if (rlcf
->codes
== NULL
) {
161 e
= ngx_pcalloc(r
->pool
, sizeof(ngx_http_script_engine_t
));
163 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
166 e
->sp
= ngx_pcalloc(r
->pool
,
167 rlcf
->stack_size
* sizeof(ngx_http_variable_value_t
));
169 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
172 e
->ip
= rlcf
->codes
->elts
;
176 e
->status
= NGX_DECLINED
;
178 while (*(uintptr_t *) e
->ip
) {
179 code
= *(ngx_http_script_code_pt
*) e
->ip
;
183 if (e
->status
< NGX_HTTP_BAD_REQUEST
) {
187 if (r
->err_status
== 0) {
191 return r
->err_status
;
196 ngx_http_rewrite_var(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
199 ngx_http_variable_t
*var
;
200 ngx_http_core_main_conf_t
*cmcf
;
201 ngx_http_rewrite_loc_conf_t
*rlcf
;
203 rlcf
= ngx_http_get_module_loc_conf(r
, ngx_http_rewrite_module
);
205 if (rlcf
->uninitialized_variable_warn
== 0) {
206 *v
= ngx_http_variable_null_value
;
210 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
212 var
= cmcf
->variables
.elts
;
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
220 ngx_log_error(NGX_LOG_WARN
, r
->connection
->log
, 0,
221 "using uninitialized \"%V\" variable", &var
[data
].name
);
223 *v
= ngx_http_variable_null_value
;
230 ngx_http_rewrite_create_loc_conf(ngx_conf_t
*cf
)
232 ngx_http_rewrite_loc_conf_t
*conf
;
234 conf
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_rewrite_loc_conf_t
));
239 conf
->stack_size
= NGX_CONF_UNSET_UINT
;
240 conf
->log
= NGX_CONF_UNSET
;
241 conf
->uninitialized_variable_warn
= NGX_CONF_UNSET
;
248 ngx_http_rewrite_merge_loc_conf(ngx_conf_t
*cf
, void *parent
, void *child
)
250 ngx_http_rewrite_loc_conf_t
*prev
= parent
;
251 ngx_http_rewrite_loc_conf_t
*conf
= child
;
255 ngx_conf_merge_value(conf
->log
, prev
->log
, 0);
256 ngx_conf_merge_value(conf
->uninitialized_variable_warn
,
257 prev
->uninitialized_variable_warn
, 1);
258 ngx_conf_merge_uint_value(conf
->stack_size
, prev
->stack_size
, 10);
260 if (conf
->codes
== NULL
) {
264 if (conf
->codes
== prev
->codes
) {
268 code
= ngx_array_push_n(conf
->codes
, sizeof(uintptr_t));
270 return NGX_CONF_ERROR
;
273 *code
= (uintptr_t) NULL
;
280 ngx_http_rewrite_init(ngx_conf_t
*cf
)
282 ngx_http_handler_pt
*h
;
283 ngx_http_core_main_conf_t
*cmcf
;
285 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
287 h
= ngx_array_push(&cmcf
->phases
[NGX_HTTP_SERVER_REWRITE_PHASE
].handlers
);
292 *h
= ngx_http_rewrite_handler
;
294 h
= ngx_array_push(&cmcf
->phases
[NGX_HTTP_REWRITE_PHASE
].handlers
);
299 *h
= ngx_http_rewrite_handler
;
306 ngx_http_rewrite(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
308 ngx_http_rewrite_loc_conf_t
*lcf
= conf
;
312 ngx_regex_compile_t rc
;
313 ngx_http_script_code_pt
*code
;
314 ngx_http_script_compile_t sc
;
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
];
319 regex
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
320 sizeof(ngx_http_script_regex_code_t
));
322 return NGX_CONF_ERROR
;
325 ngx_memzero(regex
, sizeof(ngx_http_script_regex_code_t
));
327 value
= cf
->args
->elts
;
329 ngx_memzero(&rc
, sizeof(ngx_regex_compile_t
));
331 rc
.pattern
= value
[1];
332 rc
.err
.len
= NGX_MAX_CONF_ERRSTR
;
333 rc
.err
.data
= errstr
;
335 /* TODO: NGX_REGEX_CASELESS */
337 regex
->regex
= ngx_http_regex_compile(cf
, &rc
);
338 if (regex
->regex
== NULL
) {
339 return NGX_CONF_ERROR
;
342 regex
->code
= ngx_http_script_regex_start_code
;
344 regex
->name
= value
[1];
346 if (value
[2].data
[value
[2].len
- 1] == '?') {
348 /* the last "?" drops the original arguments */
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)
361 regex
->status
= NGX_HTTP_MOVED_TEMPORARILY
;
366 if (cf
->args
->nelts
== 4) {
367 if (ngx_strcmp(value
[3].data
, "last") == 0) {
370 } else if (ngx_strcmp(value
[3].data
, "break") == 0) {
371 regex
->break_cycle
= 1;
374 } else if (ngx_strcmp(value
[3].data
, "redirect") == 0) {
375 regex
->status
= NGX_HTTP_MOVED_TEMPORARILY
;
379 } else if (ngx_strcmp(value
[3].data
, "permanent") == 0) {
380 regex
->status
= NGX_HTTP_MOVED_PERMANENTLY
;
385 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
386 "invalid parameter \"%V\"", &value
[3]);
387 return NGX_CONF_ERROR
;
391 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
394 sc
.source
= &value
[2];
395 sc
.lengths
= ®ex
->lengths
;
396 sc
.values
= &lcf
->codes
;
397 sc
.variables
= ngx_http_script_variables_count(&value
[2]);
399 sc
.complete_lengths
= 1;
400 sc
.compile_args
= !regex
->redirect
;
402 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
403 return NGX_CONF_ERROR
;
408 regex
->size
= sc
.size
;
409 regex
->args
= sc
.args
;
411 if (sc
.variables
== 0 && !sc
.dup_capture
) {
412 regex
->lengths
= NULL
;
415 regex_end
= ngx_http_script_add_code(lcf
->codes
,
416 sizeof(ngx_http_script_regex_end_code_t
),
418 if (regex_end
== NULL
) {
419 return NGX_CONF_ERROR
;
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
;
429 code
= ngx_http_script_add_code(lcf
->codes
, sizeof(uintptr_t), ®ex
);
431 return NGX_CONF_ERROR
;
437 regex
->next
= (u_char
*) lcf
->codes
->elts
+ lcf
->codes
->nelts
445 ngx_http_rewrite_return(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
447 ngx_http_rewrite_loc_conf_t
*lcf
= conf
;
450 ngx_str_t
*value
, *v
;
451 ngx_http_script_return_code_t
*ret
;
452 ngx_http_compile_complex_value_t ccv
;
454 ret
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
455 sizeof(ngx_http_script_return_code_t
));
457 return NGX_CONF_ERROR
;
460 value
= cf
->args
->elts
;
462 ngx_memzero(ret
, sizeof(ngx_http_script_return_code_t
));
464 ret
->code
= ngx_http_script_return_code
;
468 ret
->status
= ngx_atoi(p
, value
[1].len
);
470 if (ret
->status
== (uintptr_t) NGX_ERROR
) {
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))
477 ret
->status
= NGX_HTTP_MOVED_TEMPORARILY
;
481 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
482 "invalid return code \"%V\"", &value
[1]);
483 return NGX_CONF_ERROR
;
488 if (ret
->status
> 999) {
489 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
490 "invalid return code \"%V\"", &value
[1]);
491 return NGX_CONF_ERROR
;
494 if (cf
->args
->nelts
== 2) {
501 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
505 ccv
.complex_value
= &ret
->text
;
507 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
508 return NGX_CONF_ERROR
;
516 ngx_http_rewrite_break(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
518 ngx_http_rewrite_loc_conf_t
*lcf
= conf
;
520 ngx_http_script_code_pt
*code
;
522 code
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
, sizeof(uintptr_t));
524 return NGX_CONF_ERROR
;
527 *code
= ngx_http_script_break_code
;
534 ngx_http_rewrite_if(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
536 ngx_http_rewrite_loc_conf_t
*lcf
= conf
;
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
;
547 ngx_http_rewrite_loc_conf_t
*nlcf
;
549 ctx
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_conf_ctx_t
));
551 return NGX_CONF_ERROR
;
555 ctx
->main_conf
= pctx
->main_conf
;
556 ctx
->srv_conf
= pctx
->srv_conf
;
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
;
563 for (i
= 0; ngx_modules
[i
]; i
++) {
564 if (ngx_modules
[i
]->type
!= NGX_HTTP_MODULE
) {
568 module
= ngx_modules
[i
]->ctx
;
570 if (module
->create_loc_conf
) {
572 mconf
= module
->create_loc_conf(cf
);
574 return NGX_CONF_ERROR
;
577 ctx
->loc_conf
[ngx_modules
[i
]->ctx_index
] = mconf
;
581 pclcf
= pctx
->loc_conf
[ngx_http_core_module
.ctx_index
];
583 clcf
= ctx
->loc_conf
[ngx_http_core_module
.ctx_index
];
584 clcf
->loc_conf
= ctx
->loc_conf
;
585 clcf
->name
= pclcf
->name
;
588 if (ngx_http_add_location(cf
, &pclcf
->locations
, clcf
) != NGX_OK
) {
589 return NGX_CONF_ERROR
;
592 if (ngx_http_rewrite_if_condition(cf
, lcf
) != NGX_CONF_OK
) {
593 return NGX_CONF_ERROR
;
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
;
601 if_code
->code
= ngx_http_script_if_code
;
603 elts
= lcf
->codes
->elts
;
606 /* the inner directives must be compiled to the same code array */
608 nlcf
= ctx
->loc_conf
[ngx_http_rewrite_module
.ctx_index
];
609 nlcf
->codes
= lcf
->codes
;
615 if (pclcf
->name
.len
== 0) {
616 if_code
->loc_conf
= NULL
;
617 cf
->cmd_type
= NGX_HTTP_SIF_CONF
;
620 if_code
->loc_conf
= ctx
->loc_conf
;
621 cf
->cmd_type
= NGX_HTTP_LIF_CONF
;
624 rv
= ngx_conf_parse(cf
, NULL
);
628 if (rv
!= NGX_CONF_OK
) {
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
));
638 if_code
->next
= (u_char
*) lcf
->codes
->elts
+ lcf
->codes
->nelts
639 - (u_char
*) if_code
;
641 /* the code array belong to parent block */
650 ngx_http_rewrite_if_condition(ngx_conf_t
*cf
, ngx_http_rewrite_loc_conf_t
*lcf
)
655 ngx_uint_t cur
, last
;
656 ngx_regex_compile_t rc
;
657 ngx_http_script_code_pt
*code
;
658 ngx_http_script_file_code_t
*fop
;
659 ngx_http_script_regex_code_t
*regex
;
660 u_char errstr
[NGX_MAX_CONF_ERRSTR
];
662 value
= cf
->args
->elts
;
663 last
= cf
->args
->nelts
- 1;
665 if (value
[1].len
< 1 || value
[1].data
[0] != '(') {
666 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
667 "invalid condition \"%V\"", &value
[1]);
668 return NGX_CONF_ERROR
;
671 if (value
[1].len
== 1) {
680 if (value
[last
].len
< 1 || value
[last
].data
[value
[last
].len
- 1] != ')') {
681 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
682 "invalid condition \"%V\"", &value
[last
]);
683 return NGX_CONF_ERROR
;
686 if (value
[last
].len
== 1) {
691 value
[last
].data
[value
[last
].len
] = '\0';
694 len
= value
[cur
].len
;
697 if (len
> 1 && p
[0] == '$') {
699 if (cur
!= last
&& cur
+ 2 != last
) {
700 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
701 "invalid condition \"%V\"", &value
[cur
]);
702 return NGX_CONF_ERROR
;
705 if (ngx_http_rewrite_variable(cf
, lcf
, &value
[cur
]) != NGX_CONF_OK
) {
706 return NGX_CONF_ERROR
;
715 len
= value
[cur
].len
;
718 if (len
== 1 && p
[0] == '=') {
720 if (ngx_http_rewrite_value(cf
, lcf
, &value
[last
]) != NGX_CONF_OK
) {
721 return NGX_CONF_ERROR
;
724 code
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
727 return NGX_CONF_ERROR
;
730 *code
= ngx_http_script_equal_code
;
735 if (len
== 2 && p
[0] == '!' && p
[1] == '=') {
737 if (ngx_http_rewrite_value(cf
, lcf
, &value
[last
]) != NGX_CONF_OK
) {
738 return NGX_CONF_ERROR
;
741 code
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
744 return NGX_CONF_ERROR
;
747 *code
= ngx_http_script_not_equal_code
;
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] == '*'))
756 regex
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
757 sizeof(ngx_http_script_regex_code_t
));
759 return NGX_CONF_ERROR
;
762 ngx_memzero(regex
, sizeof(ngx_http_script_regex_code_t
));
764 ngx_memzero(&rc
, sizeof(ngx_regex_compile_t
));
766 rc
.pattern
= value
[last
];
767 rc
.options
= (p
[len
- 1] == '*') ? NGX_REGEX_CASELESS
: 0;
768 rc
.err
.len
= NGX_MAX_CONF_ERRSTR
;
769 rc
.err
.data
= errstr
;
771 regex
->regex
= ngx_http_regex_compile(cf
, &rc
);
772 if (regex
->regex
== NULL
) {
773 return NGX_CONF_ERROR
;
776 regex
->code
= ngx_http_script_regex_start_code
;
777 regex
->next
= sizeof(ngx_http_script_regex_code_t
);
780 regex
->negative_test
= 1;
782 regex
->name
= value
[last
];
787 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
788 "unexpected \"%V\" in condition", &value
[cur
]);
789 return NGX_CONF_ERROR
;
791 } else if ((len
== 2 && p
[0] == '-')
792 || (len
== 3 && p
[0] == '!' && p
[1] == '-'))
794 if (cur
+ 1 != last
) {
795 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
796 "invalid condition \"%V\"", &value
[cur
]);
797 return NGX_CONF_ERROR
;
800 value
[last
].data
[value
[last
].len
] = '\0';
803 if (ngx_http_rewrite_value(cf
, lcf
, &value
[last
]) != NGX_CONF_OK
) {
804 return NGX_CONF_ERROR
;
807 fop
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
808 sizeof(ngx_http_script_file_code_t
));
810 return NGX_CONF_ERROR
;
813 fop
->code
= ngx_http_script_file_code
;
816 fop
->op
= ngx_http_script_file_plain
;
821 fop
->op
= ngx_http_script_file_dir
;
826 fop
->op
= ngx_http_script_file_exists
;
831 fop
->op
= ngx_http_script_file_exec
;
837 fop
->op
= ngx_http_script_file_not_plain
;
842 fop
->op
= ngx_http_script_file_not_dir
;
847 fop
->op
= ngx_http_script_file_not_exists
;
852 fop
->op
= ngx_http_script_file_not_exec
;
857 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
858 "invalid condition \"%V\"", &value
[cur
]);
859 return NGX_CONF_ERROR
;
862 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
863 "invalid condition \"%V\"", &value
[cur
]);
865 return NGX_CONF_ERROR
;
870 ngx_http_rewrite_variable(ngx_conf_t
*cf
, ngx_http_rewrite_loc_conf_t
*lcf
,
874 ngx_http_script_var_code_t
*var_code
;
879 index
= ngx_http_get_variable_index(cf
, value
);
881 if (index
== NGX_ERROR
) {
882 return NGX_CONF_ERROR
;
885 var_code
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
886 sizeof(ngx_http_script_var_code_t
));
887 if (var_code
== NULL
) {
888 return NGX_CONF_ERROR
;
891 var_code
->code
= ngx_http_script_var_code
;
892 var_code
->index
= index
;
899 ngx_http_rewrite_set(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
901 ngx_http_rewrite_loc_conf_t
*lcf
= conf
;
905 ngx_http_variable_t
*v
;
906 ngx_http_script_var_code_t
*vcode
;
907 ngx_http_script_var_handler_code_t
*vhcode
;
909 value
= cf
->args
->elts
;
911 if (value
[1].data
[0] != '$') {
912 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
913 "invalid variable name \"%V\"", &value
[1]);
914 return NGX_CONF_ERROR
;
920 v
= ngx_http_add_variable(cf
, &value
[1], NGX_HTTP_VAR_CHANGEABLE
);
922 return NGX_CONF_ERROR
;
925 index
= ngx_http_get_variable_index(cf
, &value
[1]);
926 if (index
== NGX_ERROR
) {
927 return NGX_CONF_ERROR
;
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)
935 v
->get_handler
= ngx_http_rewrite_var
;
939 if (ngx_http_rewrite_value(cf
, lcf
, &value
[2]) != NGX_CONF_OK
) {
940 return NGX_CONF_ERROR
;
943 if (v
->set_handler
) {
944 vhcode
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
945 sizeof(ngx_http_script_var_handler_code_t
));
946 if (vhcode
== NULL
) {
947 return NGX_CONF_ERROR
;
950 vhcode
->code
= ngx_http_script_var_set_handler_code
;
951 vhcode
->handler
= v
->set_handler
;
952 vhcode
->data
= v
->data
;
957 vcode
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
958 sizeof(ngx_http_script_var_code_t
));
960 return NGX_CONF_ERROR
;
963 vcode
->code
= ngx_http_script_set_var_code
;
964 vcode
->index
= (uintptr_t) index
;
971 ngx_http_rewrite_value(ngx_conf_t
*cf
, ngx_http_rewrite_loc_conf_t
*lcf
,
975 ngx_http_script_compile_t sc
;
976 ngx_http_script_value_code_t
*val
;
977 ngx_http_script_complex_value_code_t
*complex;
979 n
= ngx_http_script_variables_count(value
);
982 val
= ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
983 sizeof(ngx_http_script_value_code_t
));
985 return NGX_CONF_ERROR
;
988 n
= ngx_atoi(value
->data
, value
->len
);
990 if (n
== NGX_ERROR
) {
994 val
->code
= ngx_http_script_value_code
;
995 val
->value
= (uintptr_t) n
;
996 val
->text_len
= (uintptr_t) value
->len
;
997 val
->text_data
= (uintptr_t) value
->data
;
1002 complex = ngx_http_script_start_code(cf
->pool
, &lcf
->codes
,
1003 sizeof(ngx_http_script_complex_value_code_t
));
1004 if (complex == NULL
) {
1005 return NGX_CONF_ERROR
;
1008 complex->code
= ngx_http_script_complex_value_code
;
1009 complex->lengths
= NULL
;
1011 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
1015 sc
.lengths
= &complex->lengths
;
1016 sc
.values
= &lcf
->codes
;
1018 sc
.complete_lengths
= 1;
1020 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
1021 return NGX_CONF_ERROR
;