3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 static ngx_int_t
ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
);
13 static ngx_int_t
ngx_http_script_done(ngx_http_script_compile_t
*sc
);
14 static ngx_int_t
ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
,
15 ngx_str_t
*value
, ngx_uint_t last
);
16 static ngx_int_t
ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
,
18 static ngx_int_t
ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
);
20 static ngx_int_t
ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
,
24 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
);
25 static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
);
26 static void ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
);
29 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
31 static uintptr_t ngx_http_script_exit_code
= (uintptr_t) NULL
;
35 ngx_http_script_flush_complex_value(ngx_http_request_t
*r
,
36 ngx_http_complex_value_t
*val
)
43 while (*index
!= (ngx_uint_t
) -1) {
45 if (r
->variables
[*index
].no_cacheable
) {
46 r
->variables
[*index
].valid
= 0;
47 r
->variables
[*index
].not_found
= 0;
57 ngx_http_complex_value(ngx_http_request_t
*r
, ngx_http_complex_value_t
*val
,
61 ngx_http_script_code_pt code
;
62 ngx_http_script_len_code_pt lcode
;
63 ngx_http_script_engine_t e
;
65 if (val
->lengths
== NULL
) {
70 ngx_http_script_flush_complex_value(r
, val
);
72 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
80 while (*(uintptr_t *) e
.ip
) {
81 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
86 value
->data
= ngx_pnalloc(r
->pool
, len
);
87 if (value
->data
== NULL
) {
95 while (*(uintptr_t *) e
.ip
) {
96 code
= *(ngx_http_script_code_pt
*) e
.ip
;
97 code((ngx_http_script_engine_t
*) &e
);
107 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t
*ccv
)
110 ngx_uint_t i
, n
, nv
, nc
;
111 ngx_array_t flushes
, lengths
, values
, *pf
, *pl
, *pv
;
112 ngx_http_script_compile_t sc
;
117 ngx_conf_log_error(NGX_LOG_EMERG
, ccv
->cf
, 0, "empty parameter");
124 for (i
= 0; i
< v
->len
; i
++) {
125 if (v
->data
[i
] == '$') {
126 if (v
->data
[i
+ 1] >= '1' && v
->data
[i
+ 1] <= '9') {
135 if (v
->data
[0] != '$' && (ccv
->conf_prefix
|| ccv
->root_prefix
)) {
137 if (ngx_conf_full_name(ccv
->cf
->cycle
, v
, ccv
->conf_prefix
) != NGX_OK
) {
141 ccv
->conf_prefix
= 0;
142 ccv
->root_prefix
= 0;
145 ccv
->complex_value
->value
= *v
;
146 ccv
->complex_value
->flushes
= NULL
;
147 ccv
->complex_value
->lengths
= NULL
;
148 ccv
->complex_value
->values
= NULL
;
150 if (nv
== 0 && nc
== 0) {
156 if (ngx_array_init(&flushes
, ccv
->cf
->pool
, n
, sizeof(ngx_uint_t
))
162 n
= nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
163 + sizeof(ngx_http_script_var_code_t
))
166 if (ngx_array_init(&lengths
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
170 n
= (nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
171 + sizeof(ngx_http_script_var_code_t
))
174 + sizeof(uintptr_t) - 1)
175 & ~(sizeof(uintptr_t) - 1);
177 if (ngx_array_init(&values
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
185 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
192 sc
.complete_lengths
= 1;
193 sc
.complete_values
= 1;
195 sc
.conf_prefix
= ccv
->conf_prefix
;
196 sc
.root_prefix
= ccv
->root_prefix
;
198 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
203 ccv
->complex_value
->flushes
= flushes
.elts
;
204 ccv
->complex_value
->flushes
[flushes
.nelts
] = (ngx_uint_t
) -1;
207 ccv
->complex_value
->lengths
= lengths
.elts
;
208 ccv
->complex_value
->values
= values
.elts
;
215 ngx_http_set_complex_value_slot(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
220 ngx_http_complex_value_t
**cv
;
221 ngx_http_compile_complex_value_t ccv
;
223 cv
= (ngx_http_complex_value_t
**) (p
+ cmd
->offset
);
229 *cv
= ngx_palloc(cf
->pool
, sizeof(ngx_http_complex_value_t
));
231 return NGX_CONF_ERROR
;
234 value
= cf
->args
->elts
;
236 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
239 ccv
.value
= &value
[1];
240 ccv
.complex_value
= *cv
;
242 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
243 return NGX_CONF_ERROR
;
251 ngx_http_test_predicates(ngx_http_request_t
*r
, ngx_array_t
*predicates
)
255 ngx_http_complex_value_t
*cv
;
257 if (predicates
== NULL
) {
261 cv
= predicates
->elts
;
263 for (i
= 0; i
< predicates
->nelts
; i
++) {
264 if (ngx_http_complex_value(r
, &cv
[i
], &val
) != NGX_OK
) {
268 if (val
.len
&& (val
.len
!= 1 || val
.data
[0] != '0')) {
278 ngx_http_set_predicate_slot(ngx_conf_t
*cf
, ngx_command_t
*cmd
, void *conf
)
285 ngx_http_complex_value_t
*cv
;
286 ngx_http_compile_complex_value_t ccv
;
288 a
= (ngx_array_t
**) (p
+ cmd
->offset
);
290 if (*a
== NGX_CONF_UNSET_PTR
) {
291 *a
= ngx_array_create(cf
->pool
, 1, sizeof(ngx_http_complex_value_t
));
293 return NGX_CONF_ERROR
;
297 value
= cf
->args
->elts
;
299 for (i
= 1; i
< cf
->args
->nelts
; i
++) {
300 cv
= ngx_array_push(*a
);
302 return NGX_CONF_ERROR
;
305 ngx_memzero(&ccv
, sizeof(ngx_http_compile_complex_value_t
));
308 ccv
.value
= &value
[i
];
309 ccv
.complex_value
= cv
;
311 if (ngx_http_compile_complex_value(&ccv
) != NGX_OK
) {
312 return NGX_CONF_ERROR
;
321 ngx_http_script_variables_count(ngx_str_t
*value
)
325 for (n
= 0, i
= 0; i
< value
->len
; i
++) {
326 if (value
->data
[i
] == '$') {
336 ngx_http_script_compile(ngx_http_script_compile_t
*sc
)
340 ngx_uint_t i
, bracket
;
342 if (ngx_http_script_init_arrays(sc
) != NGX_OK
) {
346 for (i
= 0; i
< sc
->source
->len
; /* void */ ) {
350 if (sc
->source
->data
[i
] == '$') {
352 if (++i
== sc
->source
->len
) {
353 goto invalid_variable
;
360 if (sc
->source
->data
[i
] >= '1' && sc
->source
->data
[i
] <= '9') {
362 n
= sc
->source
->data
[i
] - '0';
364 if (sc
->captures_mask
& (1 << n
)) {
368 sc
->captures_mask
|= 1 << n
;
370 if (ngx_http_script_add_capture_code(sc
, n
) != NGX_OK
) {
381 if (sc
->source
->data
[i
] == '{') {
384 if (++i
== sc
->source
->len
) {
385 goto invalid_variable
;
388 name
.data
= &sc
->source
->data
[i
];
392 name
.data
= &sc
->source
->data
[i
];
395 for ( /* void */ ; i
< sc
->source
->len
; i
++, name
.len
++) {
396 ch
= sc
->source
->data
[i
];
398 if (ch
== '}' && bracket
) {
404 if ((ch
>= 'A' && ch
<= 'Z')
405 || (ch
>= 'a' && ch
<= 'z')
406 || (ch
>= '0' && ch
<= '9')
416 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0,
417 "the closing bracket in \"%V\" "
418 "variable is missing", &name
);
423 goto invalid_variable
;
428 if (ngx_http_script_add_var_code(sc
, &name
) != NGX_OK
) {
435 if (sc
->source
->data
[i
] == '?' && sc
->compile_args
) {
437 sc
->compile_args
= 0;
439 if (ngx_http_script_add_args_code(sc
) != NGX_OK
) {
448 name
.data
= &sc
->source
->data
[i
];
450 while (i
< sc
->source
->len
) {
452 if (sc
->source
->data
[i
] == '$') {
456 if (sc
->source
->data
[i
] == '?') {
460 if (sc
->compile_args
) {
469 sc
->size
+= name
.len
;
471 if (ngx_http_script_add_copy_code(sc
, &name
, (i
== sc
->source
->len
))
478 return ngx_http_script_done(sc
);
482 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0, "invalid variable name");
489 ngx_http_script_run(ngx_http_request_t
*r
, ngx_str_t
*value
,
490 void *code_lengths
, size_t len
, void *code_values
)
493 ngx_http_script_code_pt code
;
494 ngx_http_script_len_code_pt lcode
;
495 ngx_http_script_engine_t e
;
496 ngx_http_core_main_conf_t
*cmcf
;
498 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
500 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
501 if (r
->variables
[i
].no_cacheable
) {
502 r
->variables
[i
].valid
= 0;
503 r
->variables
[i
].not_found
= 0;
507 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
513 while (*(uintptr_t *) e
.ip
) {
514 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
520 value
->data
= ngx_pnalloc(r
->pool
, len
);
521 if (value
->data
== NULL
) {
528 while (*(uintptr_t *) e
.ip
) {
529 code
= *(ngx_http_script_code_pt
*) e
.ip
;
530 code((ngx_http_script_engine_t
*) &e
);
538 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t
*r
,
539 ngx_array_t
*indices
)
541 ngx_uint_t n
, *index
;
544 index
= indices
->elts
;
545 for (n
= 0; n
< indices
->nelts
; n
++) {
546 if (r
->variables
[index
[n
]].no_cacheable
) {
547 r
->variables
[index
[n
]].valid
= 0;
548 r
->variables
[index
[n
]].not_found
= 0;
556 ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
)
560 if (sc
->flushes
&& *sc
->flushes
== NULL
) {
561 n
= sc
->variables
? sc
->variables
: 1;
562 *sc
->flushes
= ngx_array_create(sc
->cf
->pool
, n
, sizeof(ngx_uint_t
));
563 if (*sc
->flushes
== NULL
) {
568 if (*sc
->lengths
== NULL
) {
569 n
= sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
570 + sizeof(ngx_http_script_var_code_t
))
573 *sc
->lengths
= ngx_array_create(sc
->cf
->pool
, n
, 1);
574 if (*sc
->lengths
== NULL
) {
579 if (*sc
->values
== NULL
) {
580 n
= (sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
581 + sizeof(ngx_http_script_var_code_t
))
584 + sizeof(uintptr_t) - 1)
585 & ~(sizeof(uintptr_t) - 1);
587 *sc
->values
= ngx_array_create(sc
->cf
->pool
, n
, 1);
588 if (*sc
->values
== NULL
) {
600 ngx_http_script_done(ngx_http_script_compile_t
*sc
)
608 zero
.data
= (u_char
*) "\0";
610 if (ngx_http_script_add_copy_code(sc
, &zero
, 0) != NGX_OK
) {
615 if (sc
->conf_prefix
|| sc
->root_prefix
) {
616 if (ngx_http_script_add_full_name_code(sc
) != NGX_OK
) {
621 if (sc
->complete_lengths
) {
622 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
627 *code
= (uintptr_t) NULL
;
630 if (sc
->complete_values
) {
631 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t),
637 *code
= (uintptr_t) NULL
;
645 ngx_http_script_start_code(ngx_pool_t
*pool
, ngx_array_t
**codes
, size_t size
)
647 if (*codes
== NULL
) {
648 *codes
= ngx_array_create(pool
, 256, 1);
649 if (*codes
== NULL
) {
654 return ngx_array_push_n(*codes
, size
);
659 ngx_http_script_add_code(ngx_array_t
*codes
, size_t size
, void *code
)
666 new = ngx_array_push_n(codes
, size
);
672 if (elts
!= codes
->elts
) {
674 *p
+= (u_char
*) codes
->elts
- elts
;
683 ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*value
,
687 size_t size
, len
, zero
;
688 ngx_http_script_copy_code_t
*code
;
690 zero
= (sc
->zero
&& last
);
691 len
= value
->len
+ zero
;
693 code
= ngx_http_script_add_code(*sc
->lengths
,
694 sizeof(ngx_http_script_copy_code_t
), NULL
);
699 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
702 size
= (sizeof(ngx_http_script_copy_code_t
) + len
+ sizeof(uintptr_t) - 1)
703 & ~(sizeof(uintptr_t) - 1);
705 code
= ngx_http_script_add_code(*sc
->values
, size
, &sc
->main
);
710 code
->code
= ngx_http_script_copy_code
;
713 p
= ngx_cpymem((u_char
*) code
+ sizeof(ngx_http_script_copy_code_t
),
714 value
->data
, value
->len
);
726 ngx_http_script_copy_len_code(ngx_http_script_engine_t
*e
)
728 ngx_http_script_copy_code_t
*code
;
730 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
732 e
->ip
+= sizeof(ngx_http_script_copy_code_t
);
739 ngx_http_script_copy_code(ngx_http_script_engine_t
*e
)
742 ngx_http_script_copy_code_t
*code
;
744 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
749 e
->pos
= ngx_copy(p
, e
->ip
+ sizeof(ngx_http_script_copy_code_t
),
753 e
->ip
+= sizeof(ngx_http_script_copy_code_t
)
754 + ((code
->len
+ sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
756 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
757 "http script copy: \"%*s\"", e
->pos
- p
, p
);
762 ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*name
)
765 ngx_http_script_var_code_t
*code
;
767 index
= ngx_http_get_variable_index(sc
->cf
, name
);
769 if (index
== NGX_ERROR
) {
774 p
= ngx_array_push(*sc
->flushes
);
782 code
= ngx_http_script_add_code(*sc
->lengths
,
783 sizeof(ngx_http_script_var_code_t
), NULL
);
788 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_var_len_code
;
789 code
->index
= (uintptr_t) index
;
791 code
= ngx_http_script_add_code(*sc
->values
,
792 sizeof(ngx_http_script_var_code_t
),
798 code
->code
= ngx_http_script_copy_var_code
;
799 code
->index
= (uintptr_t) index
;
806 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t
*e
)
808 ngx_http_variable_value_t
*value
;
809 ngx_http_script_var_code_t
*code
;
811 code
= (ngx_http_script_var_code_t
*) e
->ip
;
813 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
816 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
819 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
822 if (value
&& !value
->not_found
) {
831 ngx_http_script_copy_var_code(ngx_http_script_engine_t
*e
)
834 ngx_http_variable_value_t
*value
;
835 ngx_http_script_var_code_t
*code
;
837 code
= (ngx_http_script_var_code_t
*) e
->ip
;
839 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
844 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
847 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
850 if (value
&& !value
->not_found
) {
852 e
->pos
= ngx_copy(p
, value
->data
, value
->len
);
854 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
,
855 e
->request
->connection
->log
, 0,
856 "http script var: \"%*s\"", e
->pos
- p
, p
);
863 ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
)
867 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
872 *code
= (uintptr_t) ngx_http_script_mark_args_code
;
874 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t), &sc
->main
);
879 *code
= (uintptr_t) ngx_http_script_start_args_code
;
886 ngx_http_script_mark_args_code(ngx_http_script_engine_t
*e
)
889 e
->ip
+= sizeof(uintptr_t);
896 ngx_http_script_start_args_code(ngx_http_script_engine_t
*e
)
898 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
903 e
->ip
+= sizeof(uintptr_t);
910 ngx_http_script_regex_start_code(ngx_http_script_engine_t
*e
)
915 ngx_http_request_t
*r
;
916 ngx_http_script_engine_t le
;
917 ngx_http_script_len_code_pt lcode
;
918 ngx_http_script_regex_code_t
*code
;
920 code
= (ngx_http_script_regex_code_t
*) e
->ip
;
924 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
925 "http script regex: \"%V\"", &code
->name
);
931 e
->line
.len
= e
->sp
->len
;
932 e
->line
.data
= e
->sp
->data
;
935 rc
= ngx_http_regex_exec(r
, code
->regex
, &e
->line
);
937 if (rc
== NGX_DECLINED
) {
938 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
939 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
940 "\"%V\" does not match \"%V\"",
941 &code
->name
, &e
->line
);
947 if (code
->negative_test
) {
949 e
->sp
->data
= (u_char
*) "1";
953 e
->sp
->data
= (u_char
*) "";
958 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
966 if (rc
== NGX_ERROR
) {
967 e
->ip
= ngx_http_script_exit
;
968 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
972 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
973 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
974 "\"%V\" matches \"%V\"", &code
->name
, &e
->line
);
978 if (code
->negative_test
) {
980 e
->sp
->data
= (u_char
*) "";
984 e
->sp
->data
= (u_char
*) "1";
989 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
994 e
->status
= code
->status
;
996 if (!code
->redirect
) {
997 e
->ip
= ngx_http_script_exit
;
1004 r
->valid_unparsed_uri
= 0;
1006 if (code
->break_cycle
) {
1007 r
->valid_location
= 0;
1015 if (code
->lengths
== NULL
) {
1016 e
->buf
.len
= code
->size
;
1019 if (r
->ncaptures
&& (r
->quoted_uri
|| r
->plus_in_uri
)) {
1020 e
->buf
.len
+= 2 * ngx_escape_uri(NULL
, r
->uri
.data
, r
->uri
.len
,
1025 for (n
= 2; n
< r
->ncaptures
; n
+= 2) {
1026 e
->buf
.len
+= r
->captures
[n
+ 1] - r
->captures
[n
];
1030 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
1032 le
.ip
= code
->lengths
->elts
;
1035 le
.quote
= code
->redirect
;
1039 while (*(uintptr_t *) le
.ip
) {
1040 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
1045 e
->is_args
= le
.is_args
;
1048 if (code
->add_args
&& r
->args
.len
) {
1049 e
->buf
.len
+= r
->args
.len
+ 1;
1052 e
->buf
.data
= ngx_pnalloc(r
->pool
, e
->buf
.len
);
1053 if (e
->buf
.data
== NULL
) {
1054 e
->ip
= ngx_http_script_exit
;
1055 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1059 e
->quote
= code
->redirect
;
1061 e
->pos
= e
->buf
.data
;
1063 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
1068 ngx_http_script_regex_end_code(ngx_http_script_engine_t
*e
)
1071 ngx_http_request_t
*r
;
1072 ngx_http_script_regex_end_code_t
*code
;
1074 code
= (ngx_http_script_regex_end_code_t
*) e
->ip
;
1080 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1081 "http script regex end");
1083 if (code
->redirect
) {
1088 ngx_unescape_uri(&dst
, &src
, e
->pos
- e
->buf
.data
,
1089 NGX_UNESCAPE_REDIRECT
);
1092 dst
= ngx_movemem(dst
, src
, e
->pos
- src
);
1097 if (code
->add_args
&& r
->args
.len
) {
1098 *e
->pos
++ = (u_char
) (code
->args
? '&' : '?');
1099 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
1102 e
->buf
.len
= e
->pos
- e
->buf
.data
;
1104 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
1105 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1106 "rewritten redirect: \"%V\"", &e
->buf
);
1109 ngx_http_clear_location(r
);
1111 r
->headers_out
.location
= ngx_list_push(&r
->headers_out
.headers
);
1112 if (r
->headers_out
.location
== NULL
) {
1113 e
->ip
= ngx_http_script_exit
;
1114 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1118 r
->headers_out
.location
->hash
= 1;
1119 ngx_str_set(&r
->headers_out
.location
->key
, "Location");
1120 r
->headers_out
.location
->value
= e
->buf
;
1122 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1127 e
->buf
.len
= e
->args
- e
->buf
.data
;
1129 if (code
->add_args
&& r
->args
.len
) {
1131 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
1134 r
->args
.len
= e
->pos
- e
->args
;
1135 r
->args
.data
= e
->args
;
1140 e
->buf
.len
= e
->pos
- e
->buf
.data
;
1142 if (!code
->add_args
) {
1147 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
1148 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1149 "rewritten data: \"%V\", args: \"%V\"",
1156 if (r
->uri
.len
== 0) {
1157 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1158 "the rewritten URI has a zero length");
1159 e
->ip
= ngx_http_script_exit
;
1160 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1164 ngx_http_set_exten(r
);
1167 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1172 ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
, ngx_uint_t n
)
1174 ngx_http_script_copy_capture_code_t
*code
;
1176 code
= ngx_http_script_add_code(*sc
->lengths
,
1177 sizeof(ngx_http_script_copy_capture_code_t
),
1183 code
->code
= (ngx_http_script_code_pt
)
1184 ngx_http_script_copy_capture_len_code
;
1188 code
= ngx_http_script_add_code(*sc
->values
,
1189 sizeof(ngx_http_script_copy_capture_code_t
),
1195 code
->code
= ngx_http_script_copy_capture_code
;
1198 if (sc
->ncaptures
< n
) {
1207 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t
*e
)
1212 ngx_http_request_t
*r
;
1213 ngx_http_script_copy_capture_code_t
*code
;
1217 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1219 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1223 if (n
< r
->ncaptures
) {
1227 if ((e
->is_args
|| e
->quote
)
1228 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1230 p
= r
->captures_data
;
1232 return cap
[n
+ 1] - cap
[n
]
1233 + 2 * ngx_escape_uri(NULL
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
],
1236 return cap
[n
+ 1] - cap
[n
];
1245 ngx_http_script_copy_capture_code(ngx_http_script_engine_t
*e
)
1250 ngx_http_request_t
*r
;
1251 ngx_http_script_copy_capture_code_t
*code
;
1255 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1257 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1263 if (n
< r
->ncaptures
) {
1266 p
= r
->captures_data
;
1268 if ((e
->is_args
|| e
->quote
)
1269 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1271 e
->pos
= (u_char
*) ngx_escape_uri(pos
, &p
[cap
[n
]],
1272 cap
[n
+ 1] - cap
[n
],
1275 e
->pos
= ngx_copy(pos
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
]);
1279 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1280 "http script capture: \"%*s\"", e
->pos
- pos
, pos
);
1287 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
)
1289 ngx_http_script_full_name_code_t
*code
;
1291 code
= ngx_http_script_add_code(*sc
->lengths
,
1292 sizeof(ngx_http_script_full_name_code_t
),
1298 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_full_name_len_code
;
1299 code
->conf_prefix
= sc
->conf_prefix
;
1301 code
= ngx_http_script_add_code(*sc
->values
,
1302 sizeof(ngx_http_script_full_name_code_t
),
1308 code
->code
= ngx_http_script_full_name_code
;
1309 code
->conf_prefix
= sc
->conf_prefix
;
1316 ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
)
1318 ngx_http_script_full_name_code_t
*code
;
1320 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1322 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1324 return code
->conf_prefix
? ngx_cycle
->conf_prefix
.len
:
1325 ngx_cycle
->prefix
.len
;
1330 ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
)
1332 ngx_http_script_full_name_code_t
*code
;
1336 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1338 value
.data
= e
->buf
.data
;
1339 value
.len
= e
->pos
- e
->buf
.data
;
1341 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &value
, code
->conf_prefix
)
1344 e
->ip
= ngx_http_script_exit
;
1345 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1351 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1352 "http script fullname: \"%V\"", &value
);
1354 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1359 ngx_http_script_return_code(ngx_http_script_engine_t
*e
)
1361 ngx_http_script_return_code_t
*code
;
1363 code
= (ngx_http_script_return_code_t
*) e
->ip
;
1365 if (code
->status
< NGX_HTTP_BAD_REQUEST
1366 || code
->text
.value
.len
1367 || code
->text
.lengths
)
1369 e
->status
= ngx_http_send_response(e
->request
, code
->status
, NULL
,
1372 e
->status
= code
->status
;
1375 e
->ip
= ngx_http_script_exit
;
1380 ngx_http_script_break_code(ngx_http_script_engine_t
*e
)
1382 e
->request
->uri_changed
= 0;
1384 e
->ip
= ngx_http_script_exit
;
1389 ngx_http_script_if_code(ngx_http_script_engine_t
*e
)
1391 ngx_http_script_if_code_t
*code
;
1393 code
= (ngx_http_script_if_code_t
*) e
->ip
;
1395 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1400 if (e
->sp
->len
&& (e
->sp
->len
!=1 || e
->sp
->data
[0] != '0')) {
1401 if (code
->loc_conf
) {
1402 e
->request
->loc_conf
= code
->loc_conf
;
1403 ngx_http_update_location_config(e
->request
);
1406 e
->ip
+= sizeof(ngx_http_script_if_code_t
);
1410 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1411 "http script if: false");
1413 e
->ip
+= code
->next
;
1418 ngx_http_script_equal_code(ngx_http_script_engine_t
*e
)
1420 ngx_http_variable_value_t
*val
, *res
;
1422 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1423 "http script equal");
1429 e
->ip
+= sizeof(uintptr_t);
1431 if (val
->len
== res
->len
1432 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1434 *res
= ngx_http_variable_true_value
;
1438 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1439 "http script equal: no");
1441 *res
= ngx_http_variable_null_value
;
1446 ngx_http_script_not_equal_code(ngx_http_script_engine_t
*e
)
1448 ngx_http_variable_value_t
*val
, *res
;
1450 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1451 "http script not equal");
1457 e
->ip
+= sizeof(uintptr_t);
1459 if (val
->len
== res
->len
1460 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1462 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1463 "http script not equal: no");
1465 *res
= ngx_http_variable_null_value
;
1469 *res
= ngx_http_variable_true_value
;
1474 ngx_http_script_file_code(ngx_http_script_engine_t
*e
)
1477 ngx_http_request_t
*r
;
1478 ngx_open_file_info_t of
;
1479 ngx_http_core_loc_conf_t
*clcf
;
1480 ngx_http_variable_value_t
*value
;
1481 ngx_http_script_file_code_t
*code
;
1485 code
= (ngx_http_script_file_code_t
*) e
->ip
;
1486 e
->ip
+= sizeof(ngx_http_script_file_code_t
);
1488 path
.len
= value
->len
- 1;
1489 path
.data
= value
->data
;
1493 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1494 "http script file op %p \"%V\"", code
->op
, &path
);
1496 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1498 ngx_memzero(&of
, sizeof(ngx_open_file_info_t
));
1500 of
.read_ahead
= clcf
->read_ahead
;
1501 of
.directio
= clcf
->directio
;
1502 of
.valid
= clcf
->open_file_cache_valid
;
1503 of
.min_uses
= clcf
->open_file_cache_min_uses
;
1505 of
.errors
= clcf
->open_file_cache_errors
;
1506 of
.events
= clcf
->open_file_cache_events
;
1508 if (ngx_open_cached_file(clcf
->open_file_cache
, &path
, &of
, r
->pool
)
1511 if (of
.err
!= NGX_ENOENT
1512 && of
.err
!= NGX_ENOTDIR
1513 && of
.err
!= NGX_ENAMETOOLONG
)
1515 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, of
.err
,
1516 "%s \"%s\" failed", of
.failed
, value
->data
);
1521 case ngx_http_script_file_plain
:
1522 case ngx_http_script_file_dir
:
1523 case ngx_http_script_file_exists
:
1524 case ngx_http_script_file_exec
:
1527 case ngx_http_script_file_not_plain
:
1528 case ngx_http_script_file_not_dir
:
1529 case ngx_http_script_file_not_exists
:
1530 case ngx_http_script_file_not_exec
:
1538 case ngx_http_script_file_plain
:
1544 case ngx_http_script_file_not_plain
:
1550 case ngx_http_script_file_dir
:
1556 case ngx_http_script_file_not_dir
:
1562 case ngx_http_script_file_exists
:
1563 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1568 case ngx_http_script_file_not_exists
:
1569 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1574 case ngx_http_script_file_exec
:
1580 case ngx_http_script_file_not_exec
:
1589 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1590 "http script file op false");
1592 *value
= ngx_http_variable_null_value
;
1597 *value
= ngx_http_variable_true_value
;
1603 ngx_http_script_complex_value_code(ngx_http_script_engine_t
*e
)
1606 ngx_http_script_engine_t le
;
1607 ngx_http_script_len_code_pt lcode
;
1608 ngx_http_script_complex_value_code_t
*code
;
1610 code
= (ngx_http_script_complex_value_code_t
*) e
->ip
;
1612 e
->ip
+= sizeof(ngx_http_script_complex_value_code_t
);
1614 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1615 "http script complex value");
1617 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
1619 le
.ip
= code
->lengths
->elts
;
1621 le
.request
= e
->request
;
1622 le
.quote
= e
->quote
;
1624 for (len
= 0; *(uintptr_t *) le
.ip
; len
+= lcode(&le
)) {
1625 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
1629 e
->buf
.data
= ngx_pnalloc(e
->request
->pool
, len
);
1630 if (e
->buf
.data
== NULL
) {
1631 e
->ip
= ngx_http_script_exit
;
1632 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1636 e
->pos
= e
->buf
.data
;
1638 e
->sp
->len
= e
->buf
.len
;
1639 e
->sp
->data
= e
->buf
.data
;
1645 ngx_http_script_value_code(ngx_http_script_engine_t
*e
)
1647 ngx_http_script_value_code_t
*code
;
1649 code
= (ngx_http_script_value_code_t
*) e
->ip
;
1651 e
->ip
+= sizeof(ngx_http_script_value_code_t
);
1653 e
->sp
->len
= code
->text_len
;
1654 e
->sp
->data
= (u_char
*) code
->text_data
;
1656 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1657 "http script value: \"%v\"", e
->sp
);
1664 ngx_http_script_set_var_code(ngx_http_script_engine_t
*e
)
1666 ngx_http_request_t
*r
;
1667 ngx_http_script_var_code_t
*code
;
1669 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1671 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1677 r
->variables
[code
->index
].len
= e
->sp
->len
;
1678 r
->variables
[code
->index
].valid
= 1;
1679 r
->variables
[code
->index
].no_cacheable
= 0;
1680 r
->variables
[code
->index
].not_found
= 0;
1681 r
->variables
[code
->index
].data
= e
->sp
->data
;
1685 ngx_http_variable_t
*v
;
1686 ngx_http_core_main_conf_t
*cmcf
;
1688 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
1690 v
= cmcf
->variables
.elts
;
1692 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1693 "http script set $%V", &v
[code
->index
].name
);
1700 ngx_http_script_var_set_handler_code(ngx_http_script_engine_t
*e
)
1702 ngx_http_script_var_handler_code_t
*code
;
1704 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1705 "http script set var handler");
1707 code
= (ngx_http_script_var_handler_code_t
*) e
->ip
;
1709 e
->ip
+= sizeof(ngx_http_script_var_handler_code_t
);
1713 code
->handler(e
->request
, e
->sp
, code
->data
);
1718 ngx_http_script_var_code(ngx_http_script_engine_t
*e
)
1720 ngx_http_variable_value_t
*value
;
1721 ngx_http_script_var_code_t
*code
;
1723 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1726 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1728 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1730 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
1732 if (value
&& !value
->not_found
) {
1733 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1734 "http script var: \"%v\"", value
);
1742 *e
->sp
= ngx_http_variable_null_value
;
1748 ngx_http_script_nop_code(ngx_http_script_engine_t
*e
)
1750 e
->ip
+= sizeof(uintptr_t);