2 * Copyright (C) Igor Sysoev
6 #include <ngx_config.h>
11 static ngx_int_t
ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
);
12 static ngx_int_t
ngx_http_script_done(ngx_http_script_compile_t
*sc
);
13 static ngx_int_t
ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
,
14 ngx_str_t
*value
, ngx_uint_t last
);
15 static ngx_int_t
ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
,
17 static ngx_int_t
ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
);
19 static ngx_int_t
ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
,
23 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
);
24 static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
);
25 static void ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
);
28 #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
30 static uintptr_t ngx_http_script_exit_code
= (uintptr_t) NULL
;
34 ngx_http_script_flush_complex_value(ngx_http_request_t
*r
,
35 ngx_http_complex_value_t
*val
)
42 while (*index
!= (ngx_uint_t
) -1) {
44 if (r
->variables
[*index
].no_cacheable
) {
45 r
->variables
[*index
].valid
= 0;
46 r
->variables
[*index
].not_found
= 0;
56 ngx_http_complex_value(ngx_http_request_t
*r
, ngx_http_complex_value_t
*val
,
60 ngx_http_script_code_pt code
;
61 ngx_http_script_len_code_pt lcode
;
62 ngx_http_script_engine_t e
;
64 if (val
->lengths
== NULL
) {
69 ngx_http_script_flush_complex_value(r
, val
);
71 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
79 while (*(uintptr_t *) e
.ip
) {
80 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
85 value
->data
= ngx_pnalloc(r
->pool
, len
);
86 if (value
->data
== NULL
) {
94 while (*(uintptr_t *) e
.ip
) {
95 code
= *(ngx_http_script_code_pt
*) e
.ip
;
96 code((ngx_http_script_engine_t
*) &e
);
106 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t
*ccv
)
109 ngx_uint_t i
, n
, nv
, nc
;
110 ngx_array_t flushes
, lengths
, values
, *pf
, *pl
, *pv
;
111 ngx_http_script_compile_t sc
;
116 ngx_conf_log_error(NGX_LOG_EMERG
, ccv
->cf
, 0, "empty parameter");
123 for (i
= 0; i
< v
->len
; i
++) {
124 if (v
->data
[i
] == '$') {
125 if (v
->data
[i
+ 1] >= '1' && v
->data
[i
+ 1] <= '9') {
134 if (v
->data
[0] != '$' && (ccv
->conf_prefix
|| ccv
->root_prefix
)) {
136 if (ngx_conf_full_name(ccv
->cf
->cycle
, v
, ccv
->conf_prefix
) != NGX_OK
) {
140 ccv
->conf_prefix
= 0;
141 ccv
->root_prefix
= 0;
144 ccv
->complex_value
->value
= *v
;
145 ccv
->complex_value
->flushes
= NULL
;
146 ccv
->complex_value
->lengths
= NULL
;
147 ccv
->complex_value
->values
= NULL
;
149 if (nv
== 0 && nc
== 0) {
155 if (ngx_array_init(&flushes
, ccv
->cf
->pool
, n
, sizeof(ngx_uint_t
))
161 n
= nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
162 + sizeof(ngx_http_script_var_code_t
))
165 if (ngx_array_init(&lengths
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
169 n
= (nv
* (2 * sizeof(ngx_http_script_copy_code_t
)
170 + sizeof(ngx_http_script_var_code_t
))
173 + sizeof(uintptr_t) - 1)
174 & ~(sizeof(uintptr_t) - 1);
176 if (ngx_array_init(&values
, ccv
->cf
->pool
, n
, 1) != NGX_OK
) {
184 ngx_memzero(&sc
, sizeof(ngx_http_script_compile_t
));
191 sc
.complete_lengths
= 1;
192 sc
.complete_values
= 1;
194 sc
.conf_prefix
= ccv
->conf_prefix
;
195 sc
.root_prefix
= ccv
->root_prefix
;
197 if (ngx_http_script_compile(&sc
) != NGX_OK
) {
202 ccv
->complex_value
->flushes
= flushes
.elts
;
203 ccv
->complex_value
->flushes
[flushes
.nelts
] = (ngx_uint_t
) -1;
206 ccv
->complex_value
->lengths
= lengths
.elts
;
207 ccv
->complex_value
->values
= values
.elts
;
214 ngx_http_script_variables_count(ngx_str_t
*value
)
218 for (n
= 0, i
= 0; i
< value
->len
; i
++) {
219 if (value
->data
[i
] == '$') {
229 ngx_http_script_compile(ngx_http_script_compile_t
*sc
)
233 ngx_uint_t i
, bracket
;
235 if (ngx_http_script_init_arrays(sc
) != NGX_OK
) {
239 for (i
= 0; i
< sc
->source
->len
; /* void */ ) {
243 if (sc
->source
->data
[i
] == '$') {
245 if (++i
== sc
->source
->len
) {
246 goto invalid_variable
;
253 if (sc
->source
->data
[i
] >= '1' && sc
->source
->data
[i
] <= '9') {
255 n
= sc
->source
->data
[i
] - '0';
257 if (sc
->captures_mask
& (1 << n
)) {
261 sc
->captures_mask
|= 1 << n
;
263 if (ngx_http_script_add_capture_code(sc
, n
) != NGX_OK
) {
274 if (sc
->source
->data
[i
] == '{') {
277 if (++i
== sc
->source
->len
) {
278 goto invalid_variable
;
281 name
.data
= &sc
->source
->data
[i
];
285 name
.data
= &sc
->source
->data
[i
];
288 for ( /* void */ ; i
< sc
->source
->len
; i
++, name
.len
++) {
289 ch
= sc
->source
->data
[i
];
291 if (ch
== '}' && bracket
) {
297 if ((ch
>= 'A' && ch
<= 'Z')
298 || (ch
>= 'a' && ch
<= 'z')
299 || (ch
>= '0' && ch
<= '9')
310 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0,
311 "the closing bracket in \"%V\" "
312 "variable is missing", &name
);
317 goto invalid_variable
;
322 if (ngx_http_script_add_var_code(sc
, &name
) != NGX_OK
) {
329 if (sc
->source
->data
[i
] == '?' && sc
->compile_args
) {
331 sc
->compile_args
= 0;
333 if (ngx_http_script_add_args_code(sc
) != NGX_OK
) {
342 name
.data
= &sc
->source
->data
[i
];
344 while (i
< sc
->source
->len
) {
346 if (sc
->source
->data
[i
] == '$') {
350 if (sc
->source
->data
[i
] == '?') {
354 if (sc
->compile_args
) {
363 sc
->size
+= name
.len
;
365 if (ngx_http_script_add_copy_code(sc
, &name
, (i
== sc
->source
->len
))
372 return ngx_http_script_done(sc
);
376 ngx_conf_log_error(NGX_LOG_EMERG
, sc
->cf
, 0, "invalid variable name");
383 ngx_http_script_run(ngx_http_request_t
*r
, ngx_str_t
*value
,
384 void *code_lengths
, size_t len
, void *code_values
)
387 ngx_http_script_code_pt code
;
388 ngx_http_script_len_code_pt lcode
;
389 ngx_http_script_engine_t e
;
390 ngx_http_core_main_conf_t
*cmcf
;
392 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
394 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
395 if (r
->variables
[i
].no_cacheable
) {
396 r
->variables
[i
].valid
= 0;
397 r
->variables
[i
].not_found
= 0;
401 ngx_memzero(&e
, sizeof(ngx_http_script_engine_t
));
407 while (*(uintptr_t *) e
.ip
) {
408 lcode
= *(ngx_http_script_len_code_pt
*) e
.ip
;
414 value
->data
= ngx_pnalloc(r
->pool
, len
);
415 if (value
->data
== NULL
) {
422 while (*(uintptr_t *) e
.ip
) {
423 code
= *(ngx_http_script_code_pt
*) e
.ip
;
424 code((ngx_http_script_engine_t
*) &e
);
432 ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t
*r
,
433 ngx_array_t
*indices
)
435 ngx_uint_t n
, *index
;
438 index
= indices
->elts
;
439 for (n
= 0; n
< indices
->nelts
; n
++) {
440 if (r
->variables
[index
[n
]].no_cacheable
) {
441 r
->variables
[index
[n
]].valid
= 0;
442 r
->variables
[index
[n
]].not_found
= 0;
450 ngx_http_script_force_flush_variables(ngx_http_request_t
*r
,
451 ngx_array_t
*indices
)
453 ngx_uint_t n
, *index
;
456 index
= indices
->elts
;
457 for (n
= 0; n
< indices
->nelts
; n
++) {
458 r
->variables
[index
[n
]].valid
= 0;
459 r
->variables
[index
[n
]].not_found
= 0;
466 ngx_http_script_init_arrays(ngx_http_script_compile_t
*sc
)
470 if (sc
->flushes
&& *sc
->flushes
== NULL
) {
471 n
= sc
->variables
? sc
->variables
: 1;
472 *sc
->flushes
= ngx_array_create(sc
->cf
->pool
, n
, sizeof(ngx_uint_t
));
473 if (*sc
->flushes
== NULL
) {
478 if (*sc
->lengths
== NULL
) {
479 n
= sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
480 + sizeof(ngx_http_script_var_code_t
))
483 *sc
->lengths
= ngx_array_create(sc
->cf
->pool
, n
, 1);
484 if (*sc
->lengths
== NULL
) {
489 if (*sc
->values
== NULL
) {
490 n
= (sc
->variables
* (2 * sizeof(ngx_http_script_copy_code_t
)
491 + sizeof(ngx_http_script_var_code_t
))
494 + sizeof(uintptr_t) - 1)
495 & ~(sizeof(uintptr_t) - 1);
497 *sc
->values
= ngx_array_create(sc
->cf
->pool
, n
, 1);
498 if (*sc
->values
== NULL
) {
510 ngx_http_script_done(ngx_http_script_compile_t
*sc
)
518 zero
.data
= (u_char
*) "\0";
520 if (ngx_http_script_add_copy_code(sc
, &zero
, 0) != NGX_OK
) {
525 if (sc
->conf_prefix
|| sc
->root_prefix
) {
526 if (ngx_http_script_add_full_name_code(sc
) != NGX_OK
) {
531 if (sc
->complete_lengths
) {
532 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
537 *code
= (uintptr_t) NULL
;
540 if (sc
->complete_values
) {
541 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t),
547 *code
= (uintptr_t) NULL
;
555 ngx_http_script_start_code(ngx_pool_t
*pool
, ngx_array_t
**codes
, size_t size
)
557 if (*codes
== NULL
) {
558 *codes
= ngx_array_create(pool
, 256, 1);
559 if (*codes
== NULL
) {
564 return ngx_array_push_n(*codes
, size
);
569 ngx_http_script_add_code(ngx_array_t
*codes
, size_t size
, void *code
)
576 new = ngx_array_push_n(codes
, size
);
582 if (elts
!= codes
->elts
) {
584 *p
+= (u_char
*) codes
->elts
- elts
;
593 ngx_http_script_add_copy_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*value
,
597 size_t size
, len
, zero
;
598 ngx_http_script_copy_code_t
*code
;
600 zero
= (sc
->zero
&& last
);
601 len
= value
->len
+ zero
;
603 code
= ngx_http_script_add_code(*sc
->lengths
,
604 sizeof(ngx_http_script_copy_code_t
), NULL
);
609 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_len_code
;
612 size
= (sizeof(ngx_http_script_copy_code_t
) + len
+ sizeof(uintptr_t) - 1)
613 & ~(sizeof(uintptr_t) - 1);
615 code
= ngx_http_script_add_code(*sc
->values
, size
, &sc
->main
);
620 code
->code
= ngx_http_script_copy_code
;
623 p
= ngx_cpymem((u_char
*) code
+ sizeof(ngx_http_script_copy_code_t
),
624 value
->data
, value
->len
);
636 ngx_http_script_copy_len_code(ngx_http_script_engine_t
*e
)
638 ngx_http_script_copy_code_t
*code
;
640 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
642 e
->ip
+= sizeof(ngx_http_script_copy_code_t
);
649 ngx_http_script_copy_code(ngx_http_script_engine_t
*e
)
652 ngx_http_script_copy_code_t
*code
;
654 code
= (ngx_http_script_copy_code_t
*) e
->ip
;
659 e
->pos
= ngx_copy(p
, e
->ip
+ sizeof(ngx_http_script_copy_code_t
),
663 e
->ip
+= sizeof(ngx_http_script_copy_code_t
)
664 + ((code
->len
+ sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
666 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
667 "http script copy: \"%*s\"", e
->pos
- p
, p
);
672 ngx_http_script_add_var_code(ngx_http_script_compile_t
*sc
, ngx_str_t
*name
)
675 ngx_http_script_var_code_t
*code
;
677 index
= ngx_http_get_variable_index(sc
->cf
, name
);
679 if (index
== NGX_ERROR
) {
684 p
= ngx_array_push(*sc
->flushes
);
692 code
= ngx_http_script_add_code(*sc
->lengths
,
693 sizeof(ngx_http_script_var_code_t
), NULL
);
698 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_copy_var_len_code
;
699 code
->index
= (uintptr_t) index
;
701 code
= ngx_http_script_add_code(*sc
->values
,
702 sizeof(ngx_http_script_var_code_t
),
708 code
->code
= ngx_http_script_copy_var_code
;
709 code
->index
= (uintptr_t) index
;
716 ngx_http_script_copy_var_len_code(ngx_http_script_engine_t
*e
)
718 ngx_http_variable_value_t
*value
;
719 ngx_http_script_var_code_t
*code
;
721 code
= (ngx_http_script_var_code_t
*) e
->ip
;
723 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
726 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
729 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
732 if (value
&& !value
->not_found
) {
741 ngx_http_script_copy_var_code(ngx_http_script_engine_t
*e
)
744 ngx_http_variable_value_t
*value
;
745 ngx_http_script_var_code_t
*code
;
747 code
= (ngx_http_script_var_code_t
*) e
->ip
;
749 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
754 value
= ngx_http_get_indexed_variable(e
->request
, code
->index
);
757 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
760 if (value
&& !value
->not_found
) {
762 e
->pos
= ngx_copy(p
, value
->data
, value
->len
);
764 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
,
765 e
->request
->connection
->log
, 0,
766 "http script var: \"%*s\"", e
->pos
- p
, p
);
773 ngx_http_script_add_args_code(ngx_http_script_compile_t
*sc
)
777 code
= ngx_http_script_add_code(*sc
->lengths
, sizeof(uintptr_t), NULL
);
782 *code
= (uintptr_t) ngx_http_script_mark_args_code
;
784 code
= ngx_http_script_add_code(*sc
->values
, sizeof(uintptr_t), &sc
->main
);
789 *code
= (uintptr_t) ngx_http_script_start_args_code
;
796 ngx_http_script_mark_args_code(ngx_http_script_engine_t
*e
)
799 e
->ip
+= sizeof(uintptr_t);
806 ngx_http_script_start_args_code(ngx_http_script_engine_t
*e
)
808 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
813 e
->ip
+= sizeof(uintptr_t);
820 ngx_http_script_regex_start_code(ngx_http_script_engine_t
*e
)
825 ngx_http_request_t
*r
;
826 ngx_http_script_engine_t le
;
827 ngx_http_script_len_code_pt lcode
;
828 ngx_http_script_regex_code_t
*code
;
830 code
= (ngx_http_script_regex_code_t
*) e
->ip
;
834 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
835 "http script regex: \"%V\"", &code
->name
);
841 e
->line
.len
= e
->sp
->len
;
842 e
->line
.data
= e
->sp
->data
;
845 rc
= ngx_http_regex_exec(r
, code
->regex
, &e
->line
);
847 if (rc
== NGX_DECLINED
) {
848 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
849 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
850 "\"%V\" does not match \"%V\"",
851 &code
->name
, &e
->line
);
857 if (code
->negative_test
) {
859 e
->sp
->data
= (u_char
*) "1";
863 e
->sp
->data
= (u_char
*) "";
868 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
876 if (rc
== NGX_ERROR
) {
877 e
->ip
= ngx_http_script_exit
;
878 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
882 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
883 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
884 "\"%V\" matches \"%V\"", &code
->name
, &e
->line
);
888 if (code
->negative_test
) {
890 e
->sp
->data
= (u_char
*) "";
894 e
->sp
->data
= (u_char
*) "1";
899 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
904 e
->status
= code
->status
;
906 if (!code
->redirect
) {
907 e
->ip
= ngx_http_script_exit
;
914 r
->valid_unparsed_uri
= 0;
916 if (code
->break_cycle
) {
917 r
->valid_location
= 0;
925 if (code
->lengths
== NULL
) {
926 e
->buf
.len
= code
->size
;
929 if (r
->ncaptures
&& (r
->quoted_uri
|| r
->plus_in_uri
)) {
930 e
->buf
.len
+= 2 * ngx_escape_uri(NULL
, r
->uri
.data
, r
->uri
.len
,
935 for (n
= 2; n
< r
->ncaptures
; n
+= 2) {
936 e
->buf
.len
+= r
->captures
[n
+ 1] - r
->captures
[n
];
940 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
942 le
.ip
= code
->lengths
->elts
;
945 le
.quote
= code
->redirect
;
949 while (*(uintptr_t *) le
.ip
) {
950 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
955 e
->is_args
= le
.is_args
;
958 if (code
->add_args
&& r
->args
.len
) {
959 e
->buf
.len
+= r
->args
.len
+ 1;
962 e
->buf
.data
= ngx_pnalloc(r
->pool
, e
->buf
.len
);
963 if (e
->buf
.data
== NULL
) {
964 e
->ip
= ngx_http_script_exit
;
965 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
969 e
->quote
= code
->redirect
;
971 e
->pos
= e
->buf
.data
;
973 e
->ip
+= sizeof(ngx_http_script_regex_code_t
);
978 ngx_http_script_regex_end_code(ngx_http_script_engine_t
*e
)
981 ngx_http_request_t
*r
;
982 ngx_http_core_srv_conf_t
*cscf
;
983 ngx_http_core_loc_conf_t
**clcfp
;
984 ngx_http_script_regex_end_code_t
*code
;
986 code
= (ngx_http_script_regex_end_code_t
*) e
->ip
;
992 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
993 "http script regex end");
995 if (code
->redirect
) {
1000 ngx_unescape_uri(&dst
, &src
, e
->pos
- e
->buf
.data
,
1001 NGX_UNESCAPE_REDIRECT
);
1004 dst
= ngx_copy(dst
, src
, e
->pos
- src
);
1009 if (code
->add_args
&& r
->args
.len
) {
1010 *e
->pos
++ = (u_char
) (code
->args
? '&' : '?');
1011 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
1014 e
->buf
.len
= e
->pos
- e
->buf
.data
;
1016 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
1017 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1018 "rewritten redirect: \"%V\"", &e
->buf
);
1021 r
->headers_out
.location
= ngx_list_push(&r
->headers_out
.headers
);
1022 if (r
->headers_out
.location
== NULL
) {
1023 e
->ip
= ngx_http_script_exit
;
1024 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1028 r
->headers_out
.location
->hash
= 1;
1029 ngx_str_set(&r
->headers_out
.location
->key
, "Location");
1030 r
->headers_out
.location
->value
= e
->buf
;
1032 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1037 e
->buf
.len
= e
->args
- e
->buf
.data
;
1039 if (code
->add_args
&& r
->args
.len
) {
1041 e
->pos
= ngx_copy(e
->pos
, r
->args
.data
, r
->args
.len
);
1044 r
->args
.len
= e
->pos
- e
->args
;
1045 r
->args
.data
= e
->args
;
1050 e
->buf
.len
= e
->pos
- e
->buf
.data
;
1052 if (!code
->add_args
) {
1057 if (e
->log
|| (r
->connection
->log
->log_level
& NGX_LOG_DEBUG_HTTP
)) {
1058 ngx_log_error(NGX_LOG_NOTICE
, r
->connection
->log
, 0,
1059 "rewritten data: \"%V\", args: \"%V\"",
1064 if (code
->named_redirect
) {
1065 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1067 if (!cscf
->named_locations
) {
1068 e
->ip
= ngx_http_script_exit
;
1069 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1073 for (clcfp
= cscf
->named_locations
; *clcfp
; clcfp
++) {
1075 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1076 "test location: \"%V\"", &(*clcfp
)->name
);
1078 if (e
->buf
.len
!= (*clcfp
)->name
.len
1079 || ngx_strncmp(e
->buf
.data
,
1080 (*clcfp
)->name
.data
, e
->buf
.len
) != 0) {
1084 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1085 "using location: %V \"%V?%V\"",
1086 &e
->buf
, &r
->uri
, &r
->args
);
1090 r
->loc_conf
= (*clcfp
)->loc_conf
;
1092 ngx_http_update_location_config(r
);
1099 if (r
->uri
.len
== 0) {
1100 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
1101 "the rewritten URI has a zero length");
1102 e
->ip
= ngx_http_script_exit
;
1103 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1108 ngx_http_set_exten(r
);
1111 e
->ip
+= sizeof(ngx_http_script_regex_end_code_t
);
1116 ngx_http_script_add_capture_code(ngx_http_script_compile_t
*sc
, ngx_uint_t n
)
1118 ngx_http_script_copy_capture_code_t
*code
;
1120 code
= ngx_http_script_add_code(*sc
->lengths
,
1121 sizeof(ngx_http_script_copy_capture_code_t
),
1127 code
->code
= (ngx_http_script_code_pt
)
1128 ngx_http_script_copy_capture_len_code
;
1132 code
= ngx_http_script_add_code(*sc
->values
,
1133 sizeof(ngx_http_script_copy_capture_code_t
),
1139 code
->code
= ngx_http_script_copy_capture_code
;
1142 if (sc
->ncaptures
< n
) {
1151 ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t
*e
)
1156 ngx_http_request_t
*r
;
1157 ngx_http_script_copy_capture_code_t
*code
;
1161 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1163 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1167 if (n
< r
->ncaptures
) {
1171 if ((e
->is_args
|| e
->quote
)
1172 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1174 p
= r
->captures_data
;
1176 return cap
[n
+ 1] - cap
[n
]
1177 + 2 * ngx_escape_uri(NULL
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
],
1180 return cap
[n
+ 1] - cap
[n
];
1189 ngx_http_script_copy_capture_code(ngx_http_script_engine_t
*e
)
1194 ngx_http_request_t
*r
;
1195 ngx_http_script_copy_capture_code_t
*code
;
1199 code
= (ngx_http_script_copy_capture_code_t
*) e
->ip
;
1201 e
->ip
+= sizeof(ngx_http_script_copy_capture_code_t
);
1207 if (n
< r
->ncaptures
) {
1210 p
= r
->captures_data
;
1212 if ((e
->is_args
|| e
->quote
)
1213 && (e
->request
->quoted_uri
|| e
->request
->plus_in_uri
))
1215 e
->pos
= (u_char
*) ngx_escape_uri(pos
, &p
[cap
[n
]],
1216 cap
[n
+ 1] - cap
[n
],
1219 e
->pos
= ngx_copy(pos
, &p
[cap
[n
]], cap
[n
+ 1] - cap
[n
]);
1223 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1224 "http script capture: \"%*s\"", e
->pos
- pos
, pos
);
1231 ngx_http_script_add_full_name_code(ngx_http_script_compile_t
*sc
)
1233 ngx_http_script_full_name_code_t
*code
;
1235 code
= ngx_http_script_add_code(*sc
->lengths
,
1236 sizeof(ngx_http_script_full_name_code_t
),
1242 code
->code
= (ngx_http_script_code_pt
) ngx_http_script_full_name_len_code
;
1243 code
->conf_prefix
= sc
->conf_prefix
;
1245 code
= ngx_http_script_add_code(*sc
->values
,
1246 sizeof(ngx_http_script_full_name_code_t
),
1252 code
->code
= ngx_http_script_full_name_code
;
1253 code
->conf_prefix
= sc
->conf_prefix
;
1260 ngx_http_script_full_name_len_code(ngx_http_script_engine_t
*e
)
1262 ngx_http_script_full_name_code_t
*code
;
1264 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1266 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1268 return code
->conf_prefix
? ngx_cycle
->conf_prefix
.len
:
1269 ngx_cycle
->prefix
.len
;
1274 ngx_http_script_full_name_code(ngx_http_script_engine_t
*e
)
1276 ngx_http_script_full_name_code_t
*code
;
1280 code
= (ngx_http_script_full_name_code_t
*) e
->ip
;
1282 value
.data
= e
->buf
.data
;
1283 value
.len
= e
->pos
- e
->buf
.data
;
1285 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &value
, code
->conf_prefix
)
1288 e
->ip
= ngx_http_script_exit
;
1289 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1295 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1296 "http script fullname: \"%V\"", &value
);
1298 e
->ip
+= sizeof(ngx_http_script_full_name_code_t
);
1303 ngx_http_script_return_code(ngx_http_script_engine_t
*e
)
1305 ngx_http_script_return_code_t
*code
;
1307 code
= (ngx_http_script_return_code_t
*) e
->ip
;
1309 e
->status
= code
->status
;
1311 if (code
->status
== NGX_HTTP_NO_CONTENT
) {
1312 e
->request
->header_only
= 1;
1313 e
->request
->zero_body
= 1;
1316 e
->ip
+= sizeof(ngx_http_script_return_code_t
) - sizeof(uintptr_t);
1321 ngx_http_script_break_code(ngx_http_script_engine_t
*e
)
1323 e
->request
->uri_changed
= 0;
1325 e
->ip
= ngx_http_script_exit
;
1330 ngx_http_script_if_code(ngx_http_script_engine_t
*e
)
1332 ngx_http_script_if_code_t
*code
;
1334 code
= (ngx_http_script_if_code_t
*) e
->ip
;
1336 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1341 if (e
->sp
->len
&& e
->sp
->data
[0] != '0') {
1342 if (code
->loc_conf
) {
1343 e
->request
->loc_conf
= code
->loc_conf
;
1344 ngx_http_update_location_config(e
->request
);
1347 e
->ip
+= sizeof(ngx_http_script_if_code_t
);
1351 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1352 "http script if: false");
1354 e
->ip
+= code
->next
;
1359 ngx_http_script_equal_code(ngx_http_script_engine_t
*e
)
1361 ngx_http_variable_value_t
*val
, *res
;
1363 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1364 "http script equal");
1370 e
->ip
+= sizeof(uintptr_t);
1372 if (val
->len
== res
->len
1373 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1375 *res
= ngx_http_variable_true_value
;
1379 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1380 "http script equal: no");
1382 *res
= ngx_http_variable_null_value
;
1387 ngx_http_script_not_equal_code(ngx_http_script_engine_t
*e
)
1389 ngx_http_variable_value_t
*val
, *res
;
1391 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1392 "http script not equal");
1398 e
->ip
+= sizeof(uintptr_t);
1400 if (val
->len
== res
->len
1401 && ngx_strncmp(val
->data
, res
->data
, res
->len
) == 0)
1403 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1404 "http script not equal: no");
1406 *res
= ngx_http_variable_null_value
;
1410 *res
= ngx_http_variable_true_value
;
1415 ngx_http_script_more_code(ngx_http_script_engine_t
*e
)
1419 ngx_http_variable_value_t
*val
, *res
;
1421 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1422 "http script more");
1428 e
->ip
+= sizeof(uintptr_t);
1430 v
= ngx_atoi(val
->data
, val
->len
);
1431 if (v
== NGX_ERROR
) {
1432 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1433 "http script more: val isn't number");
1435 *res
= ngx_http_variable_null_value
;
1439 r
= ngx_atoi(res
->data
, res
->len
);
1440 if (r
== NGX_ERROR
) {
1441 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1442 "http script more: res isn't number");
1444 *res
= ngx_http_variable_null_value
;
1449 *res
= ngx_http_variable_true_value
;
1453 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1454 "http script more: no");
1456 *res
= ngx_http_variable_null_value
;
1461 ngx_http_script_not_more_code(ngx_http_script_engine_t
*e
)
1465 ngx_http_variable_value_t
*val
, *res
;
1467 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1468 "http script not more");
1474 e
->ip
+= sizeof(uintptr_t);
1476 v
= ngx_atoi(val
->data
, val
->len
);
1477 if (v
== NGX_ERROR
) {
1478 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1479 "http script not more: val isn't number");
1481 *res
= ngx_http_variable_null_value
;
1485 r
= ngx_atoi(res
->data
, res
->len
);
1486 if (r
== NGX_ERROR
) {
1487 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1488 "http script more: res isn't number");
1490 *res
= ngx_http_variable_null_value
;
1495 *res
= ngx_http_variable_true_value
;
1499 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1500 "http script not more: no");
1502 *res
= ngx_http_variable_true_value
;
1507 ngx_http_script_less_code(ngx_http_script_engine_t
*e
)
1511 ngx_http_variable_value_t
*val
, *res
;
1513 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1514 "http script less");
1520 e
->ip
+= sizeof(uintptr_t);
1522 v
= ngx_atoi(val
->data
, val
->len
);
1523 if (v
== NGX_ERROR
) {
1524 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1525 "http script less: val isn't number");
1527 *res
= ngx_http_variable_null_value
;
1531 r
= ngx_atoi(res
->data
, res
->len
);
1532 if (r
== NGX_ERROR
) {
1533 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1534 "http script less: res isn't number");
1536 *res
= ngx_http_variable_null_value
;
1541 *res
= ngx_http_variable_true_value
;
1545 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1546 "http script less: no");
1548 *res
= ngx_http_variable_null_value
;
1553 ngx_http_script_not_less_code(ngx_http_script_engine_t
*e
)
1557 ngx_http_variable_value_t
*val
, *res
;
1559 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1560 "http script not less");
1566 e
->ip
+= sizeof(uintptr_t);
1568 v
= ngx_atoi(val
->data
, val
->len
);
1569 if (v
== NGX_ERROR
) {
1570 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1571 "http script not less: val isn't number");
1573 *res
= ngx_http_variable_null_value
;
1577 r
= ngx_atoi(res
->data
, res
->len
);
1578 if (r
== NGX_ERROR
) {
1579 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1580 "http script less: res isn't number");
1582 *res
= ngx_http_variable_null_value
;
1587 *res
= ngx_http_variable_true_value
;
1591 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1592 "http script not less: no");
1594 *res
= ngx_http_variable_null_value
;
1599 ngx_http_script_file_code(ngx_http_script_engine_t
*e
)
1602 ngx_http_request_t
*r
;
1603 ngx_open_file_info_t of
;
1604 ngx_http_core_loc_conf_t
*clcf
;
1605 ngx_http_variable_value_t
*value
;
1606 ngx_http_script_file_code_t
*code
;
1610 code
= (ngx_http_script_file_code_t
*) e
->ip
;
1611 e
->ip
+= sizeof(ngx_http_script_file_code_t
);
1613 path
.len
= value
->len
- 1;
1614 path
.data
= value
->data
;
1618 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1619 "http script file op %p \"%V\"", code
->op
, &path
);
1621 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1623 ngx_memzero(&of
, sizeof(ngx_open_file_info_t
));
1625 of
.read_ahead
= clcf
->read_ahead
;
1626 of
.directio
= clcf
->directio
;
1627 of
.valid
= clcf
->open_file_cache_valid
;
1628 of
.min_uses
= clcf
->open_file_cache_min_uses
;
1630 of
.errors
= clcf
->open_file_cache_errors
;
1631 of
.events
= clcf
->open_file_cache_events
;
1633 if (ngx_open_cached_file(clcf
->open_file_cache
, &path
, &of
, r
->pool
)
1636 if (of
.err
!= NGX_ENOENT
1637 && of
.err
!= NGX_ENOTDIR
1638 && of
.err
!= NGX_ENAMETOOLONG
)
1640 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, of
.err
,
1641 "%s \"%s\" failed", of
.failed
, value
->data
);
1646 case ngx_http_script_file_plain
:
1647 case ngx_http_script_file_dir
:
1648 case ngx_http_script_file_exists
:
1649 case ngx_http_script_file_exec
:
1652 case ngx_http_script_file_not_plain
:
1653 case ngx_http_script_file_not_dir
:
1654 case ngx_http_script_file_not_exists
:
1655 case ngx_http_script_file_not_exec
:
1663 case ngx_http_script_file_plain
:
1669 case ngx_http_script_file_not_plain
:
1675 case ngx_http_script_file_dir
:
1681 case ngx_http_script_file_not_dir
:
1687 case ngx_http_script_file_exists
:
1688 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1693 case ngx_http_script_file_not_exists
:
1694 if (of
.is_file
|| of
.is_dir
|| of
.is_link
) {
1699 case ngx_http_script_file_exec
:
1705 case ngx_http_script_file_not_exec
:
1714 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1715 "http script file op false");
1717 *value
= ngx_http_variable_null_value
;
1722 *value
= ngx_http_variable_true_value
;
1728 ngx_http_script_complex_value_code(ngx_http_script_engine_t
*e
)
1731 ngx_http_script_engine_t le
;
1732 ngx_http_script_len_code_pt lcode
;
1733 ngx_http_script_complex_value_code_t
*code
;
1735 code
= (ngx_http_script_complex_value_code_t
*) e
->ip
;
1737 e
->ip
+= sizeof(ngx_http_script_complex_value_code_t
);
1739 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1740 "http script complex value");
1742 ngx_memzero(&le
, sizeof(ngx_http_script_engine_t
));
1744 le
.ip
= code
->lengths
->elts
;
1746 le
.request
= e
->request
;
1747 le
.quote
= e
->quote
;
1749 for (len
= 0; *(uintptr_t *) le
.ip
; len
+= lcode(&le
)) {
1750 lcode
= *(ngx_http_script_len_code_pt
*) le
.ip
;
1754 e
->buf
.data
= ngx_pnalloc(e
->request
->pool
, len
);
1755 if (e
->buf
.data
== NULL
) {
1756 e
->ip
= ngx_http_script_exit
;
1757 e
->status
= NGX_HTTP_INTERNAL_SERVER_ERROR
;
1761 e
->pos
= e
->buf
.data
;
1763 e
->sp
->len
= e
->buf
.len
;
1764 e
->sp
->data
= e
->buf
.data
;
1770 ngx_http_script_value_code(ngx_http_script_engine_t
*e
)
1772 ngx_http_script_value_code_t
*code
;
1774 code
= (ngx_http_script_value_code_t
*) e
->ip
;
1776 e
->ip
+= sizeof(ngx_http_script_value_code_t
);
1778 e
->sp
->len
= code
->text_len
;
1779 e
->sp
->data
= (u_char
*) code
->text_data
;
1781 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1782 "http script value: \"%v\"", e
->sp
);
1789 ngx_http_script_set_var_code(ngx_http_script_engine_t
*e
)
1791 ngx_http_request_t
*r
;
1792 ngx_http_script_var_code_t
*code
;
1794 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1796 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1802 r
->variables
[code
->index
].len
= e
->sp
->len
;
1803 r
->variables
[code
->index
].valid
= 1;
1804 r
->variables
[code
->index
].no_cacheable
= 0;
1805 r
->variables
[code
->index
].not_found
= 0;
1806 r
->variables
[code
->index
].data
= e
->sp
->data
;
1810 ngx_http_variable_t
*v
;
1811 ngx_http_core_main_conf_t
*cmcf
;
1813 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
1815 v
= cmcf
->variables
.elts
;
1817 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1818 "http script set $%V", &v
[code
->index
].name
);
1825 ngx_http_script_var_set_handler_code(ngx_http_script_engine_t
*e
)
1827 ngx_http_script_var_handler_code_t
*code
;
1829 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1830 "http script set var handler");
1832 code
= (ngx_http_script_var_handler_code_t
*) e
->ip
;
1834 e
->ip
+= sizeof(ngx_http_script_var_handler_code_t
);
1838 code
->handler(e
->request
, e
->sp
, code
->data
);
1843 ngx_http_script_var_code(ngx_http_script_engine_t
*e
)
1845 ngx_http_variable_value_t
*value
;
1846 ngx_http_script_var_code_t
*code
;
1848 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1851 code
= (ngx_http_script_var_code_t
*) e
->ip
;
1853 e
->ip
+= sizeof(ngx_http_script_var_code_t
);
1855 value
= ngx_http_get_flushed_variable(e
->request
, code
->index
);
1857 if (value
&& !value
->not_found
) {
1858 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, e
->request
->connection
->log
, 0,
1859 "http script var: \"%v\"", value
);
1867 *e
->sp
= ngx_http_variable_null_value
;
1873 ngx_http_script_nop_code(ngx_http_script_engine_t
*e
)
1875 e
->ip
+= sizeof(uintptr_t);