Mercurial > hg > nginx
annotate src/http/modules/ngx_http_rewrite_module.c @ 6982:ac9b1df5b246
SSL: disabled renegotiation detection in client mode.
CVE-2009-3555 is no longer relevant and mitigated by the renegotiation
info extension (secure renegotiation). On the other hand, unexpected
renegotiation still introduces potential security risks, and hence we do
not allow renegotiation on the server side, as we never request renegotiation.
On the client side the situation is different though. There are backends
which explicitly request renegotiation, and disabled renegotiation
introduces interoperability problems. This change allows renegotiation
on the client side, and fixes interoperability problems as observed with
such backends (ticket #872).
Additionally, with TLSv1.3 the SSL_CB_HANDSHAKE_START flag is currently set
by OpenSSL when receiving a NewSessionTicket message, and was detected by
nginx as a renegotiation attempt. This looks like a bug in OpenSSL, though
this change also allows better interoperability till the problem is fixed.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Tue, 18 Apr 2017 16:08:44 +0300 |
parents | d2b2ff157da5 |
children | b64adc956643 |
rev | line source |
---|---|
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
1 |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
2 /* |
444
42d11f017717
nginx-0.1.0-2004-09-29-20:00:49 import; remove years from copyright
Igor Sysoev <igor@sysoev.ru>
parents:
441
diff
changeset
|
3 * Copyright (C) Igor Sysoev |
4412 | 4 * Copyright (C) Nginx, Inc. |
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
5 */ |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
6 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_config.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_core.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 #include <ngx_http.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
11 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
12 |
485 | 13 typedef struct { |
577 | 14 ngx_array_t *codes; /* uintptr_t */ |
485 | 15 |
577 | 16 ngx_uint_t stack_size; |
485 | 17 |
577 | 18 ngx_flag_t log; |
635 | 19 ngx_flag_t uninitialized_variable_warn; |
485 | 20 } ngx_http_rewrite_loc_conf_t; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
21 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
22 |
485 | 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, | |
487 | 25 void *parent, void *child); |
681 | 26 static ngx_int_t ngx_http_rewrite_init(ngx_conf_t *cf); |
485 | 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, | |
487 | 29 void *conf); |
527 | 30 static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, |
31 void *conf); | |
485 | 32 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, |
487 | 33 void *conf); |
501 | 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); | |
509 | 38 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, |
501 | 39 void *conf); |
577 | 40 static char * ngx_http_rewrite_value(ngx_conf_t *cf, |
41 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
42 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
43 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
44 static ngx_command_t ngx_http_rewrite_commands[] = { |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
45 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
46 { ngx_string("rewrite"), |
485 | 47 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
48 |NGX_CONF_TAKE23, | |
49 ngx_http_rewrite, | |
50 NGX_HTTP_LOC_CONF_OFFSET, | |
51 0, | |
52 NULL }, | |
53 | |
54 { ngx_string("return"), | |
55 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
3633 | 56 |NGX_CONF_TAKE12, |
485 | 57 ngx_http_rewrite_return, |
58 NGX_HTTP_LOC_CONF_OFFSET, | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
59 0, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
60 NULL }, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
61 |
527 | 62 { ngx_string("break"), |
63 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
64 |NGX_CONF_NOARGS, | |
65 ngx_http_rewrite_break, | |
66 NGX_HTTP_LOC_CONF_OFFSET, | |
67 0, | |
68 NULL }, | |
69 | |
485 | 70 { ngx_string("if"), |
71 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE, | |
72 ngx_http_rewrite_if, | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
73 NGX_HTTP_LOC_CONF_OFFSET, |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
74 0, |
485 | 75 NULL }, |
76 | |
501 | 77 { ngx_string("set"), |
78 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
79 |NGX_CONF_TAKE2, | |
80 ngx_http_rewrite_set, | |
81 NGX_HTTP_LOC_CONF_OFFSET, | |
82 0, | |
83 NULL }, | |
84 | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
85 { ngx_string("rewrite_log"), |
635 | 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, | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
88 ngx_conf_set_flag_slot, |
485 | 89 NGX_HTTP_LOC_CONF_OFFSET, |
90 offsetof(ngx_http_rewrite_loc_conf_t, log), | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
91 NULL }, |
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
92 |
635 | 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), | |
99 NULL }, | |
100 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
101 ngx_null_command |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
102 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
103 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
104 |
667 | 105 static ngx_http_module_t ngx_http_rewrite_module_ctx = { |
509 | 106 NULL, /* preconfiguration */ |
681 | 107 ngx_http_rewrite_init, /* postconfiguration */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
108 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
109 NULL, /* create main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
110 NULL, /* init main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
111 |
485 | 112 NULL, /* create server configuration */ |
113 NULL, /* merge server configuration */ | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
114 |
4499
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
115 ngx_http_rewrite_create_loc_conf, /* create location configuration */ |
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
116 ngx_http_rewrite_merge_loc_conf /* merge location configuration */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
117 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
118 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
119 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
120 ngx_module_t ngx_http_rewrite_module = { |
509 | 121 NGX_MODULE_V1, |
577 | 122 &ngx_http_rewrite_module_ctx, /* module context */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
123 ngx_http_rewrite_commands, /* module directives */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
124 NGX_HTTP_MODULE, /* module type */ |
541 | 125 NULL, /* init master */ |
681 | 126 NULL, /* init module */ |
541 | 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 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
133 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
134 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
135 |
487 | 136 static ngx_int_t |
137 ngx_http_rewrite_handler(ngx_http_request_t *r) | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
138 { |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
139 ngx_int_t index; |
509 | 140 ngx_http_script_code_pt code; |
141 ngx_http_script_engine_t *e; | |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
142 ngx_http_core_srv_conf_t *cscf; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
143 ngx_http_core_main_conf_t *cmcf; |
635 | 144 ngx_http_rewrite_loc_conf_t *rlcf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
145 |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
146 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
147 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
148 index = cmcf->phase_engine.location_rewrite_index; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
149 |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
150 if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) { |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
151 /* skipping location rewrite phase for server null location */ |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
152 return NGX_DECLINED; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
153 } |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
154 |
635 | 155 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
156 |
635 | 157 if (rlcf->codes == NULL) { |
485 | 158 return NGX_DECLINED; |
159 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
160 |
509 | 161 e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)); |
501 | 162 if (e == NULL) { |
485 | 163 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
164 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
165 |
509 | 166 e->sp = ngx_pcalloc(r->pool, |
635 | 167 rlcf->stack_size * sizeof(ngx_http_variable_value_t)); |
485 | 168 if (e->sp == NULL) { |
169 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
170 } | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
171 |
635 | 172 e->ip = rlcf->codes->elts; |
509 | 173 e->request = r; |
485 | 174 e->quote = 1; |
635 | 175 e->log = rlcf->log; |
485 | 176 e->status = NGX_DECLINED; |
177 | |
178 while (*(uintptr_t *) e->ip) { | |
509 | 179 code = *(ngx_http_script_code_pt *) e->ip; |
485 | 180 code(e); |
181 } | |
182 | |
4147
7f64de1cc2c0
Fix for double content when return is used in error_page handler.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3633
diff
changeset
|
183 if (e->status < NGX_HTTP_BAD_REQUEST) { |
7f64de1cc2c0
Fix for double content when return is used in error_page handler.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3633
diff
changeset
|
184 return e->status; |
739
9f983de19a1d
after redirecting by error_page any rewrite directive will return this code,
Igor Sysoev <igor@sysoev.ru>
parents:
726
diff
changeset
|
185 } |
9f983de19a1d
after redirecting by error_page any rewrite directive will return this code,
Igor Sysoev <igor@sysoev.ru>
parents:
726
diff
changeset
|
186 |
726
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
187 if (r->err_status == 0) { |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
188 return e->status; |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
189 } |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
190 |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
191 return r->err_status; |
485 | 192 } |
193 | |
194 | |
573 | 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) | |
501 | 198 { |
635 | 199 ngx_http_variable_t *var; |
200 ngx_http_core_main_conf_t *cmcf; | |
201 ngx_http_rewrite_loc_conf_t *rlcf; | |
202 | |
203 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); | |
204 | |
205 if (rlcf->uninitialized_variable_warn == 0) { | |
206 *v = ngx_http_variable_null_value; | |
207 return NGX_OK; | |
208 } | |
501 | 209 |
210 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
211 | |
212 var = cmcf->variables.elts; | |
213 | |
214 /* | |
215 * the ngx_http_rewrite_module sets variables directly in r->variables, | |
519 | 216 * and they should be handled by ngx_http_get_indexed_variable(), |
501 | 217 * so the handler is called only if the variable is not initialized |
218 */ | |
219 | |
635 | 220 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, |
501 | 221 "using uninitialized \"%V\" variable", &var[data].name); |
222 | |
577 | 223 *v = ngx_http_variable_null_value; |
573 | 224 |
225 return NGX_OK; | |
501 | 226 } |
227 | |
228 | |
487 | 229 static void * |
230 ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf) | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
231 { |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
232 ngx_http_rewrite_loc_conf_t *conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
233 |
501 | 234 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)); |
235 if (conf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2547
diff
changeset
|
236 return NULL; |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
237 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
238 |
485 | 239 conf->stack_size = NGX_CONF_UNSET_UINT; |
240 conf->log = NGX_CONF_UNSET; | |
635 | 241 conf->uninitialized_variable_warn = NGX_CONF_UNSET; |
485 | 242 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
243 return conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
244 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
245 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
246 |
487 | 247 static char * |
248 ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
249 { |
485 | 250 ngx_http_rewrite_loc_conf_t *prev = parent; |
251 ngx_http_rewrite_loc_conf_t *conf = child; | |
252 | |
509 | 253 uintptr_t *code; |
485 | 254 |
255 ngx_conf_merge_value(conf->log, prev->log, 0); | |
635 | 256 ngx_conf_merge_value(conf->uninitialized_variable_warn, |
257 prev->uninitialized_variable_warn, 1); | |
663 | 258 ngx_conf_merge_uint_value(conf->stack_size, prev->stack_size, 10); |
485 | 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 | |
501 | 268 code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)); |
269 if (code == NULL) { | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
270 return NGX_CONF_ERROR; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
271 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
272 |
485 | 273 *code = (uintptr_t) NULL; |
274 | |
275 return NGX_CONF_OK; | |
276 } | |
277 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
278 |
509 | 279 static ngx_int_t |
681 | 280 ngx_http_rewrite_init(ngx_conf_t *cf) |
577 | 281 { |
509 | 282 ngx_http_handler_pt *h; |
283 ngx_http_core_main_conf_t *cmcf; | |
284 | |
681 | 285 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
509 | 286 |
573 | 287 h = ngx_array_push(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers); |
288 if (h == NULL) { | |
289 return NGX_ERROR; | |
290 } | |
291 | |
292 *h = ngx_http_rewrite_handler; | |
293 | |
509 | 294 h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); |
295 if (h == NULL) { | |
296 return NGX_ERROR; | |
297 } | |
298 | |
299 *h = ngx_http_rewrite_handler; | |
300 | |
301 return NGX_OK; | |
577 | 302 } |
509 | 303 |
304 | |
487 | 305 static char * |
306 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 307 { |
577 | 308 ngx_http_rewrite_loc_conf_t *lcf = conf; |
309 | |
3325 | 310 ngx_str_t *value; |
509 | 311 ngx_uint_t last; |
3325 | 312 ngx_regex_compile_t rc; |
509 | 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]; | |
485 | 318 |
509 | 319 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
320 sizeof(ngx_http_script_regex_code_t)); | |
485 | 321 if (regex == NULL) { |
322 return NGX_CONF_ERROR; | |
323 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
324 |
509 | 325 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
326 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
327 value = cf->args->elts; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
328 |
3325 | 329 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); |
330 | |
331 rc.pattern = value[1]; | |
332 rc.err.len = NGX_MAX_CONF_ERRSTR; | |
333 rc.err.data = errstr; | |
485 | 334 |
335 /* TODO: NGX_REGEX_CASELESS */ | |
336 | |
3325 | 337 regex->regex = ngx_http_regex_compile(cf, &rc); |
485 | 338 if (regex->regex == NULL) { |
339 return NGX_CONF_ERROR; | |
340 } | |
341 | |
509 | 342 regex->code = ngx_http_script_regex_start_code; |
485 | 343 regex->uri = 1; |
344 regex->name = value[1]; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
345 |
509 | 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 | |
485 | 355 last = 0; |
356 | |
3524
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
357 if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0 |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
358 || ngx_strncmp(value[2].data, "https://", sizeof("https://") - 1) == 0 |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
359 || ngx_strncmp(value[2].data, "$scheme", sizeof("$scheme") - 1) == 0) |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
360 { |
2054
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
361 regex->status = NGX_HTTP_MOVED_TEMPORARILY; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
362 regex->redirect = 1; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
363 last = 1; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
364 } |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
365 |
485 | 366 if (cf->args->nelts == 4) { |
367 if (ngx_strcmp(value[3].data, "last") == 0) { | |
368 last = 1; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
369 |
487 | 370 } else if (ngx_strcmp(value[3].data, "break") == 0) { |
371 regex->break_cycle = 1; | |
372 last = 1; | |
373 | |
485 | 374 } else if (ngx_strcmp(value[3].data, "redirect") == 0) { |
375 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | |
376 regex->redirect = 1; | |
377 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
378 |
485 | 379 } else if (ngx_strcmp(value[3].data, "permanent") == 0) { |
380 regex->status = NGX_HTTP_MOVED_PERMANENTLY; | |
381 regex->redirect = 1; | |
382 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
383 |
485 | 384 } else { |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
385 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
461 | 386 "invalid parameter \"%V\"", &value[3]); |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
387 return NGX_CONF_ERROR; |
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
388 } |
485 | 389 } |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
390 |
509 | 391 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
485 | 392 |
509 | 393 sc.cf = cf; |
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]); | |
398 sc.main = regex; | |
399 sc.complete_lengths = 1; | |
400 sc.compile_args = !regex->redirect; | |
485 | 401 |
509 | 402 if (ngx_http_script_compile(&sc) != NGX_OK) { |
403 return NGX_CONF_ERROR; | |
404 } | |
485 | 405 |
509 | 406 regex = sc.main; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
407 |
509 | 408 regex->size = sc.size; |
409 regex->args = sc.args; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
410 |
641 | 411 if (sc.variables == 0 && !sc.dup_capture) { |
509 | 412 regex->lengths = NULL; |
485 | 413 } |
414 | |
509 | 415 regex_end = ngx_http_script_add_code(lcf->codes, |
416 sizeof(ngx_http_script_regex_end_code_t), | |
417 ®ex); | |
485 | 418 if (regex_end == NULL) { |
419 return NGX_CONF_ERROR; | |
420 } | |
421 | |
509 | 422 regex_end->code = ngx_http_script_regex_end_code; |
485 | 423 regex_end->uri = regex->uri; |
424 regex_end->args = regex->args; | |
509 | 425 regex_end->add_args = regex->add_args; |
485 | 426 regex_end->redirect = regex->redirect; |
427 | |
428 if (last) { | |
517 | 429 code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ®ex); |
485 | 430 if (code == NULL) { |
431 return NGX_CONF_ERROR; | |
218
05592fd7a436
nginx-0.0.1-2004-01-05-23:55:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
216
diff
changeset
|
432 } |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
433 |
3184 | 434 *code = NULL; |
485 | 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 | |
487 | 444 static char * |
445 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 446 { |
577 | 447 ngx_http_rewrite_loc_conf_t *lcf = conf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
448 |
3633 | 449 u_char *p; |
450 ngx_str_t *value, *v; | |
451 ngx_http_script_return_code_t *ret; | |
452 ngx_http_compile_complex_value_t ccv; | |
485 | 453 |
509 | 454 ret = ngx_http_script_start_code(cf->pool, &lcf->codes, |
455 sizeof(ngx_http_script_return_code_t)); | |
485 | 456 if (ret == NULL) { |
457 return NGX_CONF_ERROR; | |
458 } | |
459 | |
460 value = cf->args->elts; | |
461 | |
3633 | 462 ngx_memzero(ret, sizeof(ngx_http_script_return_code_t)); |
463 | |
509 | 464 ret->code = ngx_http_script_return_code; |
485 | 465 |
3633 | 466 p = value[1].data; |
467 | |
468 ret->status = ngx_atoi(p, value[1].len); | |
485 | 469 |
470 if (ret->status == (uintptr_t) NGX_ERROR) { | |
3633 | 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 { | |
477 ret->status = NGX_HTTP_MOVED_TEMPORARILY; | |
478 v = &value[1]; | |
479 | |
480 } else { | |
481 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
482 "invalid return code \"%V\"", &value[1]); | |
483 return NGX_CONF_ERROR; | |
484 } | |
485 | |
486 } else { | |
487 | |
4636
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
488 if (ret->status > 999) { |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
489 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
490 "invalid return code \"%V\"", &value[1]); |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
491 return NGX_CONF_ERROR; |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
492 } |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
493 |
3633 | 494 if (cf->args->nelts == 2) { |
495 return NGX_CONF_OK; | |
496 } | |
497 | |
498 v = &value[2]; | |
499 } | |
500 | |
501 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
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) { | |
485 | 508 return NGX_CONF_ERROR; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
509 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
510 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
511 return NGX_CONF_OK; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
512 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
513 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
514 |
487 | 515 static char * |
527 | 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 | |
520 ngx_http_script_code_pt *code; | |
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 | |
527 *code = ngx_http_script_break_code; | |
528 | |
529 return NGX_CONF_OK; | |
530 } | |
531 | |
532 | |
533 static char * | |
487 | 534 ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
535 { |
577 | 536 ngx_http_rewrite_loc_conf_t *lcf = conf; |
485 | 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; | |
2027 | 545 ngx_http_core_loc_conf_t *clcf, *pclcf; |
509 | 546 ngx_http_script_if_code_t *if_code; |
485 | 547 ngx_http_rewrite_loc_conf_t *nlcf; |
548 | |
501 | 549 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
550 if (ctx == NULL) { | |
485 | 551 return NGX_CONF_ERROR; |
552 } | |
553 | |
554 pctx = cf->ctx; | |
555 ctx->main_conf = pctx->main_conf; | |
577 | 556 ctx->srv_conf = pctx->srv_conf; |
485 | 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 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
563 for (i = 0; cf->cycle->modules[i]; i++) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
564 if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { |
485 | 565 continue; |
566 } | |
567 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
568 module = cf->cycle->modules[i]->ctx; |
577 | 569 |
485 | 570 if (module->create_loc_conf) { |
571 | |
501 | 572 mconf = module->create_loc_conf(cf); |
573 if (mconf == NULL) { | |
6474 | 574 return NGX_CONF_ERROR; |
485 | 575 } |
576 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
577 ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; |
485 | 578 } |
579 } | |
580 | |
581 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; | |
582 | |
583 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
584 clcf->loc_conf = ctx->loc_conf; | |
585 clcf->name = pclcf->name; | |
586 clcf->noname = 1; | |
587 | |
2027 | 588 if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { |
485 | 589 return NGX_CONF_ERROR; |
590 } | |
591 | |
501 | 592 if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { |
485 | 593 return NGX_CONF_ERROR; |
594 } | |
595 | |
509 | 596 if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t)); |
485 | 597 if (if_code == NULL) { |
3001 | 598 return NGX_CONF_ERROR; |
485 | 599 } |
600 | |
509 | 601 if_code->code = ngx_http_script_if_code; |
485 | 602 |
603 elts = lcf->codes->elts; | |
604 | |
605 | |
631 | 606 /* the inner directives must be compiled to the same code array */ |
485 | 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 | |
6244
055d1f63960a
Fixed segfault with incorrect location nesting.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5816
diff
changeset
|
615 if (cf->cmd_type == NGX_HTTP_SRV_CONF) { |
485 | 616 if_code->loc_conf = NULL; |
617 cf->cmd_type = NGX_HTTP_SIF_CONF; | |
618 | |
619 } else { | |
620 if_code->loc_conf = ctx->loc_conf; | |
621 cf->cmd_type = NGX_HTTP_LIF_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) { | |
509 | 634 if_code = (ngx_http_script_if_code_t *) |
485 | 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; | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
640 |
555 | 641 /* the code array belong to parent block */ |
642 | |
643 nlcf->codes = NULL; | |
644 | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
645 return NGX_CONF_OK; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
646 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
647 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
648 |
487 | 649 static char * |
501 | 650 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) |
651 { | |
631 | 652 u_char *p; |
653 size_t len; | |
3325 | 654 ngx_str_t *value; |
655 ngx_uint_t cur, last; | |
656 ngx_regex_compile_t rc; | |
577 | 657 ngx_http_script_code_pt *code; |
631 | 658 ngx_http_script_file_code_t *fop; |
509 | 659 ngx_http_script_regex_code_t *regex; |
660 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
501 | 661 |
662 value = cf->args->elts; | |
663 last = cf->args->nelts - 1; | |
664 | |
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; | |
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] != ')') { | |
681 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
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 | |
631 | 694 len = value[cur].len; |
695 p = value[cur].data; | |
696 | |
697 if (len > 1 && p[0] == '$') { | |
501 | 698 |
699 if (cur != last && cur + 2 != last) { | |
700 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
631 | 701 "invalid condition \"%V\"", &value[cur]); |
501 | 702 return NGX_CONF_ERROR; |
703 } | |
704 | |
577 | 705 if (ngx_http_rewrite_variable(cf, lcf, &value[cur]) != NGX_CONF_OK) { |
501 | 706 return NGX_CONF_ERROR; |
707 } | |
708 | |
709 if (cur == last) { | |
710 return NGX_CONF_OK; | |
711 } | |
712 | |
713 cur++; | |
714 | |
631 | 715 len = value[cur].len; |
716 p = value[cur].data; | |
717 | |
718 if (len == 1 && p[0] == '=') { | |
577 | 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 | |
730 *code = ngx_http_script_equal_code; | |
731 | |
732 return NGX_CONF_OK; | |
501 | 733 } |
734 | |
631 | 735 if (len == 2 && p[0] == '!' && p[1] == '=') { |
736 | |
577 | 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 | |
747 *code = ngx_http_script_not_equal_code; | |
748 return NGX_CONF_OK; | |
501 | 749 } |
750 | |
631 | 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] == '*')) | |
577 | 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 } | |
509 | 761 |
577 | 762 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
763 | |
3325 | 764 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); |
577 | 765 |
3325 | 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; | |
501 | 770 |
3325 | 771 regex->regex = ngx_http_regex_compile(cf, &rc); |
577 | 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; | |
631 | 779 if (p[0] == '!') { |
780 regex->negative_test = 1; | |
781 } | |
577 | 782 regex->name = value[last]; |
501 | 783 |
577 | 784 return NGX_CONF_OK; |
501 | 785 } |
786 | |
577 | 787 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
788 "unexpected \"%V\" in condition", &value[cur]); | |
789 return NGX_CONF_ERROR; | |
631 | 790 |
791 } else if ((len == 2 && p[0] == '-') | |
792 || (len == 3 && p[0] == '!' && p[1] == '-')) | |
793 { | |
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; | |
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, | |
808 sizeof(ngx_http_script_file_code_t)); | |
809 if (fop == NULL) { | |
810 return NGX_CONF_ERROR; | |
811 } | |
812 | |
813 fop->code = ngx_http_script_file_code; | |
814 | |
815 if (p[1] == 'f') { | |
816 fop->op = ngx_http_script_file_plain; | |
817 return NGX_CONF_OK; | |
818 } | |
819 | |
669 | 820 if (p[1] == 'd') { |
821 fop->op = ngx_http_script_file_dir; | |
822 return NGX_CONF_OK; | |
823 } | |
824 | |
825 if (p[1] == 'e') { | |
826 fop->op = ngx_http_script_file_exists; | |
827 return NGX_CONF_OK; | |
828 } | |
829 | |
830 if (p[1] == 'x') { | |
831 fop->op = ngx_http_script_file_exec; | |
832 return NGX_CONF_OK; | |
833 } | |
834 | |
631 | 835 if (p[0] == '!') { |
836 if (p[2] == 'f') { | |
837 fop->op = ngx_http_script_file_not_plain; | |
838 return NGX_CONF_OK; | |
839 } | |
669 | 840 |
841 if (p[2] == 'd') { | |
842 fop->op = ngx_http_script_file_not_dir; | |
843 return NGX_CONF_OK; | |
844 } | |
845 | |
846 if (p[2] == 'e') { | |
847 fop->op = ngx_http_script_file_not_exists; | |
848 return NGX_CONF_OK; | |
849 } | |
850 | |
851 if (p[2] == 'x') { | |
852 fop->op = ngx_http_script_file_not_exec; | |
853 return NGX_CONF_OK; | |
854 } | |
631 | 855 } |
856 | |
857 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
858 "invalid condition \"%V\"", &value[cur]); | |
859 return NGX_CONF_ERROR; | |
501 | 860 } |
861 | |
862 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
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 { | |
509 | 873 ngx_int_t index; |
874 ngx_http_script_var_code_t *var_code; | |
501 | 875 |
876 value->len--; | |
877 value->data++; | |
878 | |
577 | 879 index = ngx_http_get_variable_index(cf, value); |
501 | 880 |
577 | 881 if (index == NGX_ERROR) { |
882 return NGX_CONF_ERROR; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
883 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
884 |
577 | 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; | |
485 | 889 } |
890 | |
577 | 891 var_code->code = ngx_http_script_var_code; |
892 var_code->index = index; | |
485 | 893 |
894 return NGX_CONF_OK; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
895 } |
485 | 896 |
897 | |
501 | 898 static char * |
899 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
900 { | |
577 | 901 ngx_http_rewrite_loc_conf_t *lcf = conf; |
501 | 902 |
637 | 903 ngx_int_t index; |
904 ngx_str_t *value; | |
905 ngx_http_variable_t *v; | |
906 ngx_http_script_var_code_t *vcode; | |
907 ngx_http_script_var_handler_code_t *vhcode; | |
501 | 908 |
909 value = cf->args->elts; | |
910 | |
4972
8b635cf36ccc
Added checks that disallow adding a variable with an empty name.
Ruslan Ermilov <ru@nginx.com>
parents:
4963
diff
changeset
|
911 if (value[1].data[0] != '$') { |
501 | 912 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
913 "invalid variable name \"%V\"", &value[1]); | |
914 return NGX_CONF_ERROR; | |
915 } | |
916 | |
917 value[1].len--; | |
918 value[1].data++; | |
919 | |
6899
d2b2ff157da5
Variables: generic prefix variables.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6474
diff
changeset
|
920 v = ngx_http_add_variable(cf, &value[1], |
d2b2ff157da5
Variables: generic prefix variables.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6474
diff
changeset
|
921 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_WEAK); |
501 | 922 if (v == NULL) { |
923 return NGX_CONF_ERROR; | |
924 } | |
925 | |
509 | 926 index = ngx_http_get_variable_index(cf, &value[1]); |
927 if (index == NGX_ERROR) { | |
928 return NGX_CONF_ERROR; | |
929 } | |
501 | 930 |
6899
d2b2ff157da5
Variables: generic prefix variables.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6474
diff
changeset
|
931 if (v->get_handler == NULL) { |
637 | 932 v->get_handler = ngx_http_rewrite_var; |
555 | 933 v->data = index; |
934 } | |
509 | 935 |
577 | 936 if (ngx_http_rewrite_value(cf, lcf, &value[2]) != NGX_CONF_OK) { |
937 return NGX_CONF_ERROR; | |
515 | 938 } |
501 | 939 |
637 | 940 if (v->set_handler) { |
941 vhcode = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
942 sizeof(ngx_http_script_var_handler_code_t)); | |
943 if (vhcode == NULL) { | |
944 return NGX_CONF_ERROR; | |
945 } | |
946 | |
947 vhcode->code = ngx_http_script_var_set_handler_code; | |
948 vhcode->handler = v->set_handler; | |
949 vhcode->data = v->data; | |
950 | |
951 return NGX_CONF_OK; | |
952 } | |
953 | |
954 vcode = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
955 sizeof(ngx_http_script_var_code_t)); | |
956 if (vcode == NULL) { | |
501 | 957 return NGX_CONF_ERROR; |
958 } | |
959 | |
637 | 960 vcode->code = ngx_http_script_set_var_code; |
961 vcode->index = (uintptr_t) index; | |
501 | 962 |
963 return NGX_CONF_OK; | |
964 } | |
577 | 965 |
966 | |
967 static char * | |
968 ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | |
969 ngx_str_t *value) | |
970 { | |
971 ngx_int_t n; | |
972 ngx_http_script_compile_t sc; | |
973 ngx_http_script_value_code_t *val; | |
974 ngx_http_script_complex_value_code_t *complex; | |
975 | |
976 n = ngx_http_script_variables_count(value); | |
977 | |
978 if (n == 0) { | |
979 val = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
980 sizeof(ngx_http_script_value_code_t)); | |
981 if (val == NULL) { | |
982 return NGX_CONF_ERROR; | |
983 } | |
984 | |
985 n = ngx_atoi(value->data, value->len); | |
986 | |
987 if (n == NGX_ERROR) { | |
988 n = 0; | |
989 } | |
990 | |
991 val->code = ngx_http_script_value_code; | |
992 val->value = (uintptr_t) n; | |
993 val->text_len = (uintptr_t) value->len; | |
994 val->text_data = (uintptr_t) value->data; | |
995 | |
996 return NGX_CONF_OK; | |
997 } | |
998 | |
999 complex = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
1000 sizeof(ngx_http_script_complex_value_code_t)); | |
1001 if (complex == NULL) { | |
1002 return NGX_CONF_ERROR; | |
1003 } | |
1004 | |
1005 complex->code = ngx_http_script_complex_value_code; | |
1006 complex->lengths = NULL; | |
1007 | |
1008 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1009 | |
1010 sc.cf = cf; | |
1011 sc.source = value; | |
1012 sc.lengths = &complex->lengths; | |
1013 sc.values = &lcf->codes; | |
1014 sc.variables = n; | |
1015 sc.complete_lengths = 1; | |
1016 | |
1017 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1018 return NGX_CONF_ERROR; | |
1019 } | |
1020 | |
1021 return NGX_CONF_OK; | |
1022 } |