Mercurial > hg > nginx-vendor-0-8
comparison src/http/modules/ngx_http_rewrite_module.c @ 58:b55cbf18157e NGINX_0_1_29
nginx 0.1.29
*) Feature: the ngx_http_ssi_module supports "include virtual" command.
*) Feature: the ngx_http_ssi_module supports the condition command like
'if expr="$NAME"' and "else" and "endif" commands. Only one nested
level is supported.
*) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and
DATE_GMT variables and "config timefmt" command.
*) Feature: the "ssi_ignore_recycled_buffers" directive.
*) Bugfix: the "echo" command did not show the default value for the
empty QUERY_STRING variable.
*) Change: the ngx_http_proxy_module was rewritten.
*) Feature: the "proxy_redirect", "proxy_pass_request_headers",
"proxy_pass_request_body", and "proxy_method" directives.
*) Feature: the "proxy_set_header" directive. The "proxy_x_var" was
canceled and must be replaced with the proxy_set_header directive.
*) Change: the "proxy_preserve_host" is canceled and must be replaced
with the "proxy_set_header Host $host" and the "proxy_redirect off"
directives, the "proxy_set_header Host $host:$proxy_port" directive
and the appropriate proxy_redirect directives.
*) Change: the "proxy_set_x_real_ip" is canceled and must be replaced
with the "proxy_set_header X-Real-IP $remote_addr" directive.
*) Change: the "proxy_add_x_forwarded_for" is canceled and must be
replaced with
the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for"
directive.
*) Change: the "proxy_set_x_url" is canceled and must be replaced with
the "proxy_set_header X-URL http://$host:$server_port$request_uri"
directive.
*) Feature: the "fastcgi_param" directive.
*) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params"
directive are canceled and must be replaced with the fastcgi_param
directives.
*) Feature: the "index" directive can use the variables.
*) Feature: the "index" directive can be used at http and server levels.
*) Change: the last index only in the "index" directive can be absolute.
*) Feature: the "rewrite" directive can use the variables.
*) Feature: the "internal" directive.
*) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR,
SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME,
REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables.
*) Change: nginx now passes the invalid lines in a client request
headers or a backend response header.
*) Bugfix: if the backend did not transfer response for a long time and
the "send_timeout" was less than "proxy_read_timeout", then nginx
returned the 408 response.
*) Bugfix: the segmentation fault was occurred if the backend sent an
invalid line in response header; bug appeared in 0.1.26.
*) Bugfix: the segmentation fault may occurred in FastCGI fault
tolerance configuration.
*) Bugfix: the "expires" directive did not remove the previous
"Expires" and "Cache-Control" headers.
*) Bugfix: nginx did not take into account trailing dot in "Host"
header line.
*) Bugfix: the ngx_http_auth_module did not work under Linux.
*) Bugfix: the rewrite directive worked incorrectly, if the arguments
were in a request.
*) Bugfix: nginx could not be built on MacOS X.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Thu, 12 May 2005 00:00:00 +0400 |
parents | 3050baa54a26 |
children | 5db440287648 |
comparison
equal
deleted
inserted
replaced
57:5df375c55338 | 58:b55cbf18157e |
---|---|
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 | 10 |
11 | 11 |
12 typedef struct ngx_http_rewrite_engine_s ngx_http_rewrite_engine_t; | |
13 | |
14 typedef void (*ngx_http_rewrite_code_pt) (ngx_http_rewrite_engine_t *e); | |
15 | |
16 | |
17 typedef struct { | 12 typedef struct { |
18 ngx_str_t name; | 13 ngx_str_t name; |
19 ngx_uint_t wildcard; | 14 ngx_uint_t wildcard; |
20 } ngx_http_rewrite_referer_t; | 15 } ngx_http_rewrite_referer_t; |
21 | 16 |
22 | 17 |
23 typedef struct { | 18 typedef struct { |
24 ngx_str_t *name; | 19 ngx_str_t *name; |
25 ngx_http_variable_value_t *value; | 20 ngx_http_variable_value_t *value; |
26 } ngx_http_rewrite_variable_t; | 21 } ngx_http_rewrite_variable_t; |
27 | 22 |
28 | 23 |
29 typedef struct { | 24 typedef struct { |
30 ngx_array_t *codes; /* uintptr_t */ | 25 ngx_array_t *codes; /* uintptr_t */ |
31 ngx_array_t *referers; /* ngx_http_rewrite_referer_t */ | 26 ngx_array_t *referers; /* ngx_http_rewrite_referer_t */ |
32 | 27 |
33 ngx_uint_t max_captures; | 28 ngx_uint_t max_captures; |
34 ngx_uint_t stack_size; | 29 ngx_uint_t stack_size; |
35 | 30 |
36 ngx_flag_t log; | 31 ngx_flag_t log; |
37 | 32 |
38 ngx_flag_t no_referer; | 33 ngx_flag_t no_referer; |
39 ngx_flag_t blocked_referer; | 34 ngx_flag_t blocked_referer; |
40 } ngx_http_rewrite_loc_conf_t; | 35 } ngx_http_rewrite_loc_conf_t; |
41 | 36 |
42 | 37 |
43 typedef struct { | |
44 ngx_http_rewrite_code_pt code; | |
45 ngx_regex_t *regex; | |
46 uintptr_t size; | |
47 uintptr_t ncaptures; | |
48 uintptr_t status; | |
49 uintptr_t next; | |
50 | |
51 uintptr_t test:1; | |
52 uintptr_t uri:1; | |
53 | |
54 /* add the r->args to the new arguments */ | |
55 uintptr_t args:1; | |
56 | |
57 uintptr_t redirect:1; | |
58 uintptr_t break_cycle:1; | |
59 | |
60 ngx_str_t name; | |
61 } ngx_http_rewrite_regex_code_t; | |
62 | |
63 | |
64 typedef struct { | |
65 ngx_http_rewrite_code_pt code; | |
66 | |
67 uintptr_t uri:1; | |
68 | |
69 /* add the r->args to the new arguments */ | |
70 uintptr_t args:1; | |
71 | |
72 uintptr_t redirect:1; | |
73 } ngx_http_rewrite_regex_end_code_t; | |
74 | |
75 typedef struct { | |
76 ngx_http_rewrite_code_pt code; | |
77 uintptr_t n; | |
78 } ngx_http_rewrite_copy_capture_code_t; | |
79 | |
80 | |
81 typedef struct { | |
82 ngx_http_rewrite_code_pt code; | |
83 uintptr_t len; | |
84 } ngx_http_rewrite_copy_code_t; | |
85 | |
86 | |
87 typedef struct { | |
88 ngx_http_rewrite_code_pt code; | |
89 uintptr_t status; | |
90 uintptr_t null; | |
91 } ngx_http_rewrite_return_code_t; | |
92 | |
93 | |
94 typedef struct { | |
95 ngx_http_rewrite_code_pt code; | |
96 uintptr_t next; | |
97 void **loc_conf; | |
98 } ngx_http_rewrite_if_code_t; | |
99 | |
100 | |
101 typedef struct { | |
102 ngx_http_rewrite_code_pt code; | |
103 uintptr_t value; | |
104 uintptr_t text_len; | |
105 uintptr_t text_data; | |
106 } ngx_http_rewrite_value_code_t; | |
107 | |
108 | |
109 typedef struct { | |
110 ngx_http_rewrite_code_pt code; | |
111 uintptr_t index; | |
112 } ngx_http_rewrite_var_code_t; | |
113 | |
114 | |
115 struct ngx_http_rewrite_engine_s { | |
116 u_char *ip; | |
117 ngx_http_variable_value_t *sp; | |
118 | |
119 ngx_str_t buf; | |
120 ngx_str_t *line; | |
121 | |
122 u_char *pos; | |
123 | |
124 /* the start of the rewritten arguments */ | |
125 u_char *args; | |
126 | |
127 unsigned quote:1; | |
128 | |
129 ngx_int_t status; | |
130 | |
131 int *captures; | |
132 | |
133 ngx_http_request_t *request; | |
134 ngx_http_rewrite_loc_conf_t *conf; | |
135 }; | |
136 | |
137 | |
138 static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle); | |
139 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); | 38 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); |
140 static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, | 39 static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, |
141 void *parent, void *child); | 40 void *parent, void *child); |
41 static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle); | |
142 static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 42 static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
143 static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, | 43 static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, |
144 void *conf); | 44 void *conf); |
145 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, | 45 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, |
146 void *conf); | 46 void *conf); |
148 ngx_http_rewrite_loc_conf_t *lcf); | 48 ngx_http_rewrite_loc_conf_t *lcf); |
149 static char *ngx_http_rewrite_variable(ngx_conf_t *cf, | 49 static char *ngx_http_rewrite_variable(ngx_conf_t *cf, |
150 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | 50 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); |
151 static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf, | 51 static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf, |
152 ngx_command_t *cmd, void *conf); | 52 ngx_command_t *cmd, void *conf); |
153 static char * ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, | 53 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, |
154 void *conf); | 54 void *conf); |
155 static void *ngx_http_rewrite_start_code(ngx_pool_t *pool, | |
156 ngx_array_t **codes, size_t size); | |
157 static void *ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size, | |
158 void *code); | |
159 | 55 |
160 | 56 |
161 static ngx_command_t ngx_http_rewrite_commands[] = { | 57 static ngx_command_t ngx_http_rewrite_commands[] = { |
162 | 58 |
163 { ngx_string("rewrite"), | 59 { ngx_string("rewrite"), |
209 ngx_null_command | 105 ngx_null_command |
210 }; | 106 }; |
211 | 107 |
212 | 108 |
213 ngx_http_module_t ngx_http_rewrite_module_ctx = { | 109 ngx_http_module_t ngx_http_rewrite_module_ctx = { |
214 NULL, /* pre conf */ | 110 NULL, /* preconfiguration */ |
111 NULL, /* postconfiguration */ | |
215 | 112 |
216 NULL, /* create main configuration */ | 113 NULL, /* create main configuration */ |
217 NULL, /* init main configuration */ | 114 NULL, /* init main configuration */ |
218 | 115 |
219 NULL, /* create server configuration */ | 116 NULL, /* create server configuration */ |
223 ngx_http_rewrite_merge_loc_conf /* merge location configration */ | 120 ngx_http_rewrite_merge_loc_conf /* merge location configration */ |
224 }; | 121 }; |
225 | 122 |
226 | 123 |
227 ngx_module_t ngx_http_rewrite_module = { | 124 ngx_module_t ngx_http_rewrite_module = { |
228 NGX_MODULE, | 125 NGX_MODULE_V1, |
229 &ngx_http_rewrite_module_ctx, /* module context */ | 126 &ngx_http_rewrite_module_ctx, /* module context */ |
230 ngx_http_rewrite_commands, /* module directives */ | 127 ngx_http_rewrite_commands, /* module directives */ |
231 NGX_HTTP_MODULE, /* module type */ | 128 NGX_HTTP_MODULE, /* module type */ |
232 ngx_http_rewrite_init, /* init module */ | 129 ngx_http_rewrite_init, /* init module */ |
233 NULL /* init process */ | 130 NULL /* init process */ |
234 }; | 131 }; |
235 | 132 |
236 | 133 |
237 #define ngx_http_rewrite_exit (u_char *) &ngx_http_rewrite_exit_code | |
238 | |
239 uintptr_t ngx_http_rewrite_exit_code = (uintptr_t) NULL; | |
240 | |
241 static ngx_http_variable_value_t ngx_http_rewrite_null_value = | 134 static ngx_http_variable_value_t ngx_http_rewrite_null_value = |
242 { 0, ngx_string("") }; | 135 { 0, ngx_string("") }; |
243 | 136 |
244 | 137 |
245 static ngx_int_t | 138 static ngx_int_t |
246 ngx_http_rewrite_handler(ngx_http_request_t *r) | 139 ngx_http_rewrite_handler(ngx_http_request_t *r) |
247 { | 140 { |
248 ngx_http_rewrite_code_pt code; | 141 ngx_http_script_code_pt code; |
249 ngx_http_rewrite_engine_t *e; | 142 ngx_http_script_engine_t *e; |
250 ngx_http_rewrite_loc_conf_t *cf; | 143 ngx_http_rewrite_loc_conf_t *cf; |
251 | 144 |
252 cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); | 145 cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); |
253 | 146 |
254 if (cf->codes == NULL) { | 147 if (cf->codes == NULL) { |
255 return NGX_DECLINED; | 148 return NGX_DECLINED; |
256 } | 149 } |
257 | 150 |
258 e = ngx_palloc(r->pool, sizeof(ngx_http_rewrite_engine_t)); | 151 e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)); |
259 if (e == NULL) { | 152 if (e == NULL) { |
260 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 153 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
261 } | 154 } |
262 | 155 |
263 e->sp = ngx_palloc(r->pool, | 156 e->sp = ngx_pcalloc(r->pool, |
264 cf->stack_size * sizeof(ngx_http_variable_value_t)); | 157 cf->stack_size * sizeof(ngx_http_variable_value_t)); |
265 if (e->sp == NULL) { | 158 if (e->sp == NULL) { |
266 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 159 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
267 } | 160 } |
268 | 161 |
269 if (cf->max_captures) { | 162 if (cf->max_captures) { |
275 } else { | 168 } else { |
276 e->captures = NULL; | 169 e->captures = NULL; |
277 } | 170 } |
278 | 171 |
279 e->ip = cf->codes->elts; | 172 e->ip = cf->codes->elts; |
280 e->buf.len = 0; | 173 e->request = r; |
281 e->buf.data = NULL; | |
282 e->line = NULL; | |
283 e->pos = NULL; | |
284 e->args = NULL; | |
285 e->quote = 1; | 174 e->quote = 1; |
175 e->log = cf->log; | |
286 e->status = NGX_DECLINED; | 176 e->status = NGX_DECLINED; |
287 e->request = r; | |
288 e->conf = cf; | |
289 | 177 |
290 while (*(uintptr_t *) e->ip) { | 178 while (*(uintptr_t *) e->ip) { |
291 code = *(ngx_http_rewrite_code_pt *) e->ip; | 179 code = *(ngx_http_script_code_pt *) e->ip; |
292 code(e); | 180 code(e); |
293 } | 181 } |
294 | 182 |
295 return e->status; | 183 return e->status; |
296 } | 184 } |
297 | 185 |
298 | 186 |
299 static void | 187 static void |
300 ngx_http_rewrite_regex_start_code(ngx_http_rewrite_engine_t *e) | 188 ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) |
301 { | |
302 ngx_int_t rc; | |
303 ngx_uint_t n; | |
304 ngx_http_request_t *r; | |
305 ngx_http_rewrite_regex_code_t *code; | |
306 | |
307 code = (ngx_http_rewrite_regex_code_t *) e->ip; | |
308 | |
309 r = e->request; | |
310 | |
311 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
312 "http rewrite regex: \"%V\"", &code->name); | |
313 | |
314 if (code->uri) { | |
315 e->line = &r->uri; | |
316 } else { | |
317 e->sp--; | |
318 e->line = &e->sp->text; | |
319 } | |
320 | |
321 rc = ngx_regex_exec(code->regex, e->line, e->captures, code->ncaptures); | |
322 | |
323 if (rc == NGX_REGEX_NO_MATCHED) { | |
324 if (e->conf->log) { | |
325 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, | |
326 "\"%V\" does not match \"%V\"", &code->name, e->line); | |
327 } | |
328 | |
329 if (code->test) { | |
330 e->sp->value = 0; | |
331 e->sp->text.len = 0; | |
332 e->sp->text.data = (u_char *) ""; | |
333 e->sp++; | |
334 | |
335 e->ip += sizeof(ngx_http_rewrite_regex_code_t); | |
336 return; | |
337 } | |
338 | |
339 e->ip += code->next; | |
340 return; | |
341 } | |
342 | |
343 if (rc < 0) { | |
344 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
345 ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", | |
346 rc, e->line, &code->name); | |
347 | |
348 e->ip = ngx_http_rewrite_exit; | |
349 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
350 return; | |
351 } | |
352 | |
353 if (e->conf->log) { | |
354 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, | |
355 "\"%V\" matches \"%V\"", &code->name, e->line); | |
356 } | |
357 | |
358 if (code->test) { | |
359 e->sp->value = 1; | |
360 e->sp->text.len = 1; | |
361 e->sp->text.data = (u_char *) "1"; | |
362 e->sp++; | |
363 | |
364 e->ip += sizeof(ngx_http_rewrite_regex_code_t); | |
365 return; | |
366 } | |
367 | |
368 if (code->status) { | |
369 e->status = code->status; | |
370 | |
371 if (!code->redirect) { | |
372 e->ip = ngx_http_rewrite_exit; | |
373 return; | |
374 } | |
375 } | |
376 | |
377 e->buf.len = code->size; | |
378 | |
379 if (code->uri) { | |
380 if (!code->break_cycle) { | |
381 r->uri_changed = 1; | |
382 r->valid_unparsed_uri = 1; | |
383 } | |
384 | |
385 if (rc && (r->quoted_uri || r->plus_in_uri)) { | |
386 e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, | |
387 NGX_ESCAPE_ARGS); | |
388 } | |
389 } | |
390 | |
391 for (n = 1; n < (ngx_uint_t) rc; n++) { | |
392 e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n]; | |
393 } | |
394 | |
395 if (code->args && r->args.len) { | |
396 e->buf.len += r->args.len + 1; | |
397 } | |
398 | |
399 e->buf.data = ngx_palloc(r->pool, e->buf.len); | |
400 if (e->buf.data == NULL) { | |
401 e->ip = ngx_http_rewrite_exit; | |
402 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
403 return; | |
404 } | |
405 | |
406 e->quote = code->redirect; | |
407 | |
408 e->pos = e->buf.data; | |
409 | |
410 e->ip += sizeof(ngx_http_rewrite_regex_code_t); | |
411 } | |
412 | |
413 | |
414 static void | |
415 ngx_http_rewrite_regex_end_code(ngx_http_rewrite_engine_t *e) | |
416 { | |
417 ngx_http_request_t *r; | |
418 ngx_http_rewrite_regex_end_code_t *code; | |
419 | |
420 code = (ngx_http_rewrite_regex_end_code_t *) e->ip; | |
421 | |
422 r = e->request; | |
423 | |
424 e->quote = 0; | |
425 | |
426 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
427 "http rewrite regex end"); | |
428 | |
429 if (e->args) { | |
430 e->buf.len = e->args - e->buf.data; | |
431 | |
432 if (code->args && r->args.len) { | |
433 *e->pos++ = '&'; | |
434 e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len); | |
435 } | |
436 | |
437 r->args.len = e->pos - e->args; | |
438 r->args.data = e->args; | |
439 | |
440 e->args = NULL; | |
441 | |
442 } else { | |
443 if (code->args && r->args.len) { | |
444 *e->pos++ = '?'; | |
445 e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len); | |
446 } | |
447 | |
448 e->buf.len = e->pos - e->buf.data; | |
449 } | |
450 | |
451 if (!code->redirect) { | |
452 if (e->conf->log) { | |
453 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, | |
454 "rewritten data: \"%V\", args: \"%V\"", | |
455 &e->buf, &r->args); | |
456 } | |
457 | |
458 if (code->uri) { | |
459 r->uri = e->buf; | |
460 | |
461 if (ngx_http_set_exten(r) != NGX_OK) { | |
462 e->ip = ngx_http_rewrite_exit; | |
463 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
464 return; | |
465 } | |
466 } | |
467 | |
468 e->ip += sizeof(ngx_http_rewrite_regex_end_code_t); | |
469 return; | |
470 } | |
471 | |
472 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, | |
473 "rewritten redirect: \"%V\"", &e->buf); | |
474 | |
475 r->headers_out.location = ngx_list_push(&r->headers_out.headers); | |
476 if (r->headers_out.location == NULL) { | |
477 e->ip = ngx_http_rewrite_exit; | |
478 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
479 return; | |
480 } | |
481 | |
482 if (e->buf.data[0] != '/') { | |
483 r->headers_out.location->key.len = sizeof("Location") - 1; | |
484 r->headers_out.location->key.data = (u_char *) "Location"; | |
485 } | |
486 | |
487 r->headers_out.location->value = e->buf; | |
488 | |
489 e->ip += sizeof(ngx_http_rewrite_regex_end_code_t); | |
490 } | |
491 | |
492 | |
493 static void | |
494 ngx_http_rewrite_copy_capture_code(ngx_http_rewrite_engine_t *e) | |
495 { | |
496 ngx_http_rewrite_copy_capture_code_t *code; | |
497 | |
498 code = (ngx_http_rewrite_copy_capture_code_t *) e->ip; | |
499 | |
500 e->ip += sizeof(ngx_http_rewrite_copy_capture_code_t); | |
501 | |
502 if ((e->args || e->quote) | |
503 && (e->request->quoted_uri || e->request->plus_in_uri)) | |
504 { | |
505 e->pos = (u_char *) ngx_escape_uri(e->pos, | |
506 &e->line->data[e->captures[code->n]], | |
507 e->captures[code->n + 1] - e->captures[code->n], | |
508 NGX_ESCAPE_ARGS); | |
509 } else { | |
510 e->pos = ngx_cpymem(e->pos, &e->line->data[e->captures[code->n]], | |
511 e->captures[code->n + 1] - e->captures[code->n]); | |
512 } | |
513 | |
514 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
515 "http rewrite capture: \"%V\"", &e->buf); | |
516 } | |
517 | |
518 | |
519 static void | |
520 ngx_http_rewrite_copy_code(ngx_http_rewrite_engine_t *e) | |
521 { | |
522 ngx_http_rewrite_copy_code_t *code; | |
523 | |
524 code = (ngx_http_rewrite_copy_code_t *) e->ip; | |
525 | |
526 e->pos = ngx_cpymem(e->pos, e->ip + sizeof(ngx_http_rewrite_copy_code_t), | |
527 code->len); | |
528 | |
529 e->ip += sizeof(ngx_http_rewrite_copy_code_t) | |
530 + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1)); | |
531 | |
532 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
533 "http rewrite copy: \"%V\"", &e->buf); | |
534 } | |
535 | |
536 | |
537 static void | |
538 ngx_http_rewrite_start_args_code(ngx_http_rewrite_engine_t *e) | |
539 { | |
540 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
541 "http rewrite args"); | |
542 | |
543 e->args = e->pos; | |
544 e->ip += sizeof(uintptr_t); | |
545 } | |
546 | |
547 | |
548 static void | |
549 ngx_http_rewrite_return_code(ngx_http_rewrite_engine_t *e) | |
550 { | |
551 ngx_http_rewrite_return_code_t *code; | |
552 | |
553 code = (ngx_http_rewrite_return_code_t *) e->ip; | |
554 | |
555 e->status = code->status; | |
556 | |
557 e->ip += sizeof(ngx_http_rewrite_return_code_t) - sizeof(uintptr_t); | |
558 } | |
559 | |
560 | |
561 static void | |
562 ngx_http_rewrite_if_code(ngx_http_rewrite_engine_t *e) | |
563 { | |
564 ngx_http_rewrite_if_code_t *code; | |
565 | |
566 code = (ngx_http_rewrite_if_code_t *) e->ip; | |
567 | |
568 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
569 "http rewrite if"); | |
570 | |
571 e->sp--; | |
572 | |
573 if (e->sp->value) { | |
574 if (code->loc_conf) { | |
575 e->request->loc_conf = code->loc_conf; | |
576 } | |
577 | |
578 e->ip += sizeof(ngx_http_rewrite_if_code_t); | |
579 return; | |
580 } | |
581 | |
582 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
583 "http rewrite if false"); | |
584 | |
585 e->ip += code->next; | |
586 } | |
587 | |
588 | |
589 static void | |
590 ngx_http_rewrite_value_code(ngx_http_rewrite_engine_t *e) | |
591 { | |
592 ngx_http_rewrite_value_code_t *code; | |
593 | |
594 code = (ngx_http_rewrite_value_code_t *) e->ip; | |
595 | |
596 e->ip += sizeof(ngx_http_rewrite_value_code_t); | |
597 | |
598 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
599 "http rewrite value"); | |
600 | |
601 e->sp->value = (ngx_uint_t) code->value; | |
602 e->sp->text.len = (size_t) code->text_len; | |
603 e->sp->text.data = (u_char *) code->text_data; | |
604 e->sp++; | |
605 } | |
606 | |
607 | |
608 static void | |
609 ngx_http_rewrite_set_var_code(ngx_http_rewrite_engine_t *e) | |
610 { | |
611 ngx_http_request_t *r; | |
612 ngx_http_variable_value_t *value; | |
613 ngx_http_core_main_conf_t *cmcf; | |
614 ngx_http_rewrite_var_code_t *code; | |
615 | |
616 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
617 "http rewrite set var"); | |
618 | |
619 code = (ngx_http_rewrite_var_code_t *) e->ip; | |
620 | |
621 e->ip += sizeof(ngx_http_rewrite_var_code_t); | |
622 | |
623 r = e->request; | |
624 | |
625 if (r->variables == NULL) { | |
626 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
627 | |
628 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts | |
629 * sizeof(ngx_http_variable_value_t *)); | |
630 if (r->variables == NULL) { | |
631 e->ip = ngx_http_rewrite_exit; | |
632 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
633 return; | |
634 } | |
635 } | |
636 | |
637 value = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
638 if (value == NULL) { | |
639 e->ip = ngx_http_rewrite_exit; | |
640 e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
641 return; | |
642 } | |
643 | |
644 e->sp--; | |
645 | |
646 *value = *e->sp; | |
647 | |
648 r->variables[code->index] = value; | |
649 } | |
650 | |
651 | |
652 static void | |
653 ngx_http_rewrite_var_code(ngx_http_rewrite_engine_t *e) | |
654 { | |
655 ngx_http_variable_value_t *value; | |
656 ngx_http_rewrite_var_code_t *code; | |
657 | |
658 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
659 "http rewrite var"); | |
660 | |
661 code = (ngx_http_rewrite_var_code_t *) e->ip; | |
662 | |
663 e->ip += sizeof(ngx_http_rewrite_var_code_t); | |
664 | |
665 value = ngx_http_get_indexed_variable(e->request, code->index); | |
666 | |
667 if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) { | |
668 e->sp->value = 0; | |
669 e->sp->text.len = 0; | |
670 e->sp->text.data = (u_char *) ""; | |
671 e->sp++; | |
672 | |
673 return; | |
674 } | |
675 | |
676 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, | |
677 "http rewrite var: %ui, \"%V\"", value->value, &value->text); | |
678 | |
679 *e->sp = *value; | |
680 e->sp++; | |
681 } | |
682 | |
683 | |
684 static void | |
685 ngx_http_rewrite_invalid_referer_code(ngx_http_rewrite_engine_t *e) | |
686 { | 189 { |
687 u_char *ref; | 190 u_char *ref; |
688 size_t len; | 191 size_t len; |
689 ngx_uint_t i, n; | 192 ngx_uint_t i, n; |
690 ngx_http_request_t *r; | 193 ngx_http_request_t *r; |
802 e->sp->text.data = (u_char *) "1"; | 305 e->sp->text.data = (u_char *) "1"; |
803 e->sp++; | 306 e->sp++; |
804 } | 307 } |
805 | 308 |
806 | 309 |
807 static void | |
808 ngx_http_rewrite_nop_code(ngx_http_rewrite_engine_t *e) | |
809 { | |
810 e->ip += sizeof(uintptr_t); | |
811 } | |
812 | |
813 | |
814 static ngx_http_variable_value_t * | 310 static ngx_http_variable_value_t * |
815 ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data) | 311 ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data) |
816 { | 312 { |
817 ngx_http_variable_t *var; | 313 ngx_http_variable_t *var; |
818 ngx_http_core_main_conf_t *cmcf; | 314 ngx_http_core_main_conf_t *cmcf; |
832 | 328 |
833 return &ngx_http_rewrite_null_value; | 329 return &ngx_http_rewrite_null_value; |
834 } | 330 } |
835 | 331 |
836 | 332 |
333 static void * | |
334 ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf) | |
335 { | |
336 ngx_http_rewrite_loc_conf_t *conf; | |
337 | |
338 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)); | |
339 if (conf == NULL) { | |
340 return NGX_CONF_ERROR; | |
341 } | |
342 | |
343 conf->stack_size = NGX_CONF_UNSET_UINT; | |
344 conf->log = NGX_CONF_UNSET; | |
345 conf->no_referer = NGX_CONF_UNSET; | |
346 conf->blocked_referer = NGX_CONF_UNSET; | |
347 | |
348 return conf; | |
349 } | |
350 | |
351 | |
352 static char * | |
353 ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
354 { | |
355 ngx_http_rewrite_loc_conf_t *prev = parent; | |
356 ngx_http_rewrite_loc_conf_t *conf = child; | |
357 | |
358 uintptr_t *code; | |
359 | |
360 ngx_conf_merge_value(conf->log, prev->log, 0); | |
361 ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10); | |
362 | |
363 if (conf->referers == NULL) { | |
364 conf->referers = prev->referers; | |
365 ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); | |
366 ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); | |
367 } | |
368 | |
369 if (conf->no_referer == NGX_CONF_UNSET) { | |
370 conf->no_referer = 0; | |
371 } | |
372 | |
373 if (conf->blocked_referer == NGX_CONF_UNSET) { | |
374 conf->blocked_referer = 0; | |
375 } | |
376 | |
377 if (conf->codes == NULL) { | |
378 return NGX_CONF_OK; | |
379 } | |
380 | |
381 if (conf->codes == prev->codes) { | |
382 return NGX_CONF_OK; | |
383 } | |
384 | |
385 code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)); | |
386 if (code == NULL) { | |
387 return NGX_CONF_ERROR; | |
388 } | |
389 | |
390 *code = (uintptr_t) NULL; | |
391 | |
392 return NGX_CONF_OK; | |
393 } | |
394 | |
395 | |
837 static ngx_int_t | 396 static ngx_int_t |
838 ngx_http_rewrite_init(ngx_cycle_t *cycle) | 397 ngx_http_rewrite_init(ngx_cycle_t *cycle) |
839 { | 398 { |
840 ngx_http_handler_pt *h; | 399 ngx_http_handler_pt *h; |
841 ngx_http_core_main_conf_t *cmcf; | 400 ngx_http_core_main_conf_t *cmcf; |
842 | 401 |
843 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); | 402 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); |
844 | 403 |
845 h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); | 404 h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); |
846 if (h == NULL) { | 405 if (h == NULL) { |
847 return NGX_ERROR; | 406 return NGX_ERROR; |
848 } | 407 } |
849 | 408 |
850 *h = ngx_http_rewrite_handler; | 409 *h = ngx_http_rewrite_handler; |
851 | 410 |
852 return NGX_OK; | 411 return NGX_OK; |
853 } | 412 } |
854 | 413 |
855 | 414 |
856 static void * | |
857 ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf) | |
858 { | |
859 ngx_http_rewrite_loc_conf_t *conf; | |
860 | |
861 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)); | |
862 if (conf == NULL) { | |
863 return NGX_CONF_ERROR; | |
864 } | |
865 | |
866 conf->stack_size = NGX_CONF_UNSET_UINT; | |
867 conf->log = NGX_CONF_UNSET; | |
868 conf->no_referer = NGX_CONF_UNSET; | |
869 conf->blocked_referer = NGX_CONF_UNSET; | |
870 | |
871 return conf; | |
872 } | |
873 | |
874 | |
875 static char * | |
876 ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
877 { | |
878 ngx_http_rewrite_loc_conf_t *prev = parent; | |
879 ngx_http_rewrite_loc_conf_t *conf = child; | |
880 | |
881 uintptr_t *code, *last; | |
882 ngx_http_rewrite_regex_code_t *regex; | |
883 | |
884 ngx_conf_merge_value(conf->log, prev->log, 0); | |
885 ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10); | |
886 | |
887 if (conf->referers == NULL) { | |
888 conf->referers = prev->referers; | |
889 ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); | |
890 ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); | |
891 } | |
892 | |
893 if (conf->no_referer == NGX_CONF_UNSET) { | |
894 conf->no_referer = 0; | |
895 } | |
896 | |
897 if (conf->blocked_referer == NGX_CONF_UNSET) { | |
898 conf->blocked_referer = 0; | |
899 } | |
900 | |
901 if (conf->codes == NULL) { | |
902 return NGX_CONF_OK; | |
903 } | |
904 | |
905 if (conf->codes == prev->codes) { | |
906 return NGX_CONF_OK; | |
907 } | |
908 | |
909 code = conf->codes->elts; | |
910 last = (uintptr_t *) ((u_char *) code + conf->codes->nelts); | |
911 | |
912 while (code < last) { | |
913 if (*code == (uintptr_t) NULL) { | |
914 return NGX_CONF_OK; | |
915 } | |
916 | |
917 if (*code == (uintptr_t) &ngx_http_rewrite_regex_start_code) { | |
918 regex = (ngx_http_rewrite_regex_code_t *) code; | |
919 if (conf->max_captures < regex->ncaptures) { | |
920 conf->max_captures = regex->ncaptures; | |
921 } | |
922 code = (uintptr_t *) ((u_char *) code + regex->next); | |
923 continue; | |
924 } | |
925 | |
926 if (*code == (uintptr_t) &ngx_http_rewrite_if_code) { | |
927 code += sizeof(ngx_http_rewrite_if_code_t) / sizeof(uintptr_t); | |
928 continue; | |
929 } | |
930 | |
931 if (*code == (uintptr_t) &ngx_http_rewrite_return_code) { | |
932 code += sizeof(ngx_http_rewrite_return_code_t) / sizeof(uintptr_t); | |
933 continue; | |
934 } | |
935 | |
936 if (*code == (uintptr_t) &ngx_http_rewrite_set_var_code) { | |
937 code += sizeof(ngx_http_rewrite_var_code_t) / sizeof(uintptr_t); | |
938 continue; | |
939 } | |
940 | |
941 if (*code == (uintptr_t) &ngx_http_rewrite_var_code) { | |
942 code += sizeof(ngx_http_rewrite_var_code_t) / sizeof(uintptr_t); | |
943 continue; | |
944 } | |
945 | |
946 if (*code == (uintptr_t) &ngx_http_rewrite_value_code) { | |
947 code += sizeof(ngx_http_rewrite_value_code_t) / sizeof(uintptr_t); | |
948 continue; | |
949 } | |
950 | |
951 if (*code == (uintptr_t) &ngx_http_rewrite_invalid_referer_code) { | |
952 code++; | |
953 continue; | |
954 } | |
955 | |
956 if (*code == (uintptr_t) &ngx_http_rewrite_nop_code) { | |
957 code++; | |
958 continue; | |
959 } | |
960 | |
961 #if (NGX_DEBUG) | |
962 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
963 "unknown rewrite code: %p", *code); | |
964 return NGX_CONF_ERROR; | |
965 #endif | |
966 } | |
967 | |
968 code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)); | |
969 if (code == NULL) { | |
970 return NGX_CONF_ERROR; | |
971 } | |
972 | |
973 *code = (uintptr_t) NULL; | |
974 | |
975 return NGX_CONF_OK; | |
976 } | |
977 | |
978 | |
979 static char * | 415 static char * |
980 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 416 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
981 { | 417 { |
982 ngx_http_rewrite_loc_conf_t *lcf = conf; | 418 ngx_http_rewrite_loc_conf_t *lcf = conf; |
983 | 419 |
984 u_char *data; | 420 ngx_str_t *value, err; |
985 size_t len, size; | 421 ngx_int_t n; |
986 ngx_str_t *value, err; | 422 ngx_uint_t last; |
987 ngx_int_t n; | 423 ngx_http_script_code_pt *code; |
988 ngx_uint_t i, last; | 424 ngx_http_script_compile_t sc; |
989 ngx_http_rewrite_code_pt *code; | 425 ngx_http_script_regex_code_t *regex; |
990 ngx_http_rewrite_copy_code_t *copy; | 426 ngx_http_script_regex_end_code_t *regex_end; |
991 ngx_http_rewrite_regex_code_t *regex; | 427 u_char errstr[NGX_MAX_CONF_ERRSTR]; |
992 ngx_http_rewrite_regex_end_code_t *regex_end; | 428 |
993 ngx_http_rewrite_copy_capture_code_t *copy_capture; | 429 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
994 u_char errstr[NGX_MAX_CONF_ERRSTR]; | 430 sizeof(ngx_http_script_regex_code_t)); |
995 | |
996 regex = ngx_http_rewrite_start_code(cf->pool, &lcf->codes, | |
997 sizeof(ngx_http_rewrite_regex_code_t)); | |
998 if (regex == NULL) { | 431 if (regex == NULL) { |
999 return NGX_CONF_ERROR; | 432 return NGX_CONF_ERROR; |
1000 } | 433 } |
434 | |
435 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); | |
1001 | 436 |
1002 value = cf->args->elts; | 437 value = cf->args->elts; |
1003 | 438 |
1004 err.len = NGX_MAX_CONF_ERRSTR; | 439 err.len = NGX_MAX_CONF_ERRSTR; |
1005 err.data = errstr; | 440 err.data = errstr; |
1011 if (regex->regex == NULL) { | 446 if (regex->regex == NULL) { |
1012 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | 447 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); |
1013 return NGX_CONF_ERROR; | 448 return NGX_CONF_ERROR; |
1014 } | 449 } |
1015 | 450 |
1016 regex->code = ngx_http_rewrite_regex_start_code; | 451 regex->code = ngx_http_script_regex_start_code; |
1017 regex->size = 0; | |
1018 regex->ncaptures = 0; | |
1019 regex->status = 0; | |
1020 regex->test = 0; | |
1021 regex->uri = 1; | 452 regex->uri = 1; |
1022 regex->args = 1; | |
1023 regex->redirect = 0; | |
1024 regex->break_cycle = 0; | |
1025 regex->name = value[1]; | 453 regex->name = value[1]; |
454 | |
455 if (value[2].data[value[2].len - 1] == '?') { | |
456 | |
457 /* the last "?" drops the original arguments */ | |
458 value[2].len--; | |
459 | |
460 } else { | |
461 regex->add_args = 1; | |
462 } | |
1026 | 463 |
1027 last = 0; | 464 last = 0; |
1028 | 465 |
1029 if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0) { | 466 if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0) { |
1030 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | 467 regex->status = NGX_HTTP_MOVED_TEMPORARILY; |
1055 "invalid parameter \"%V\"", &value[3]); | 492 "invalid parameter \"%V\"", &value[3]); |
1056 return NGX_CONF_ERROR; | 493 return NGX_CONF_ERROR; |
1057 } | 494 } |
1058 } | 495 } |
1059 | 496 |
1060 i = 0; | 497 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
1061 | 498 |
1062 while (i < value[2].len) { | 499 sc.cf = cf; |
1063 | 500 sc.source = &value[2]; |
1064 data = &value[2].data[i]; | 501 sc.lengths = ®ex->lengths; |
1065 | 502 sc.values = &lcf->codes; |
1066 if (value[2].data[i] == '$' && i < value[2].len | 503 sc.variables = ngx_http_script_variables_count(&value[2]); |
1067 && value[2].data[i + 1] >= '1' && value[2].data[i + 1] <= '9') | 504 sc.main = regex; |
1068 { | 505 sc.complete_lengths = 1; |
1069 | 506 sc.compile_args = !regex->redirect; |
1070 /* the "$1" - "$9" captures */ | 507 |
1071 | 508 if (ngx_http_script_compile(&sc) != NGX_OK) { |
1072 copy_capture = ngx_http_rewrite_add_code(lcf->codes, | 509 return NGX_CONF_ERROR; |
1073 sizeof(ngx_http_rewrite_copy_capture_code_t), | 510 } |
1074 ®ex); | 511 |
1075 if (copy_capture == NULL) { | 512 regex = sc.main; |
1076 return NGX_CONF_ERROR; | 513 |
1077 } | 514 regex->ncaptures = sc.ncaptures; |
1078 | 515 regex->size = sc.size; |
1079 i++; | 516 regex->args = sc.args; |
1080 | 517 |
1081 copy_capture->code = ngx_http_rewrite_copy_capture_code; | 518 if (sc.variables == 0) { |
1082 copy_capture->n = value[2].data[i] - '0'; | 519 regex->lengths = NULL; |
1083 | |
1084 if (regex->ncaptures < copy_capture->n) { | |
1085 regex->ncaptures = copy_capture->n; | |
1086 } | |
1087 | |
1088 copy_capture->n *= 2; | |
1089 | |
1090 i++; | |
1091 | |
1092 continue; | |
1093 } | |
1094 | |
1095 if (value[2].data[i] == '?') { | |
1096 | |
1097 /* the arguments */ | |
1098 | |
1099 if (i == value[2].len - 1) { | |
1100 /* the last "?" drops the original arguments */ | |
1101 regex->args = 0; | |
1102 break; | |
1103 } | |
1104 | |
1105 if (!regex->redirect) { | |
1106 code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t), | |
1107 ®ex); | |
1108 if (code == NULL) { | |
1109 return NGX_CONF_ERROR; | |
1110 } | |
1111 | |
1112 *code = ngx_http_rewrite_start_args_code; | |
1113 | |
1114 i++; | |
1115 | |
1116 continue; | |
1117 } | |
1118 } | |
1119 | |
1120 i++; | |
1121 | |
1122 /* the substituion strings */ | |
1123 | |
1124 while (i < value[2].len && value[2].data[i] != '$') { | |
1125 | |
1126 if (value[2].data[i] == '?') { | |
1127 | |
1128 if (i == value[2].len - 1) { | |
1129 /* | |
1130 * the last "?" drops the original arguments, | |
1131 * and it should not be copied to a substituion | |
1132 */ | |
1133 regex->args = 0; | |
1134 break; | |
1135 } | |
1136 | |
1137 if (!regex->redirect) { | |
1138 break; | |
1139 } | |
1140 } | |
1141 | |
1142 i++; | |
1143 } | |
1144 | |
1145 len = &value[2].data[i] - data; | |
1146 | |
1147 if (len == 0) { | |
1148 continue; | |
1149 } | |
1150 | |
1151 regex->size += len; | |
1152 | |
1153 size = (len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); | |
1154 | |
1155 copy = ngx_http_rewrite_add_code(lcf->codes, | |
1156 sizeof(ngx_http_rewrite_copy_code_t) + size, | |
1157 ®ex); | |
1158 if (copy == NULL) { | |
1159 return NGX_CONF_ERROR; | |
1160 } | |
1161 | |
1162 copy->code = ngx_http_rewrite_copy_code; | |
1163 copy->len = len; | |
1164 | |
1165 ngx_memcpy((u_char *) copy + sizeof(ngx_http_rewrite_copy_code_t), | |
1166 data, len); | |
1167 } | 520 } |
1168 | 521 |
1169 n = ngx_regex_capture_count(regex->regex); | 522 n = ngx_regex_capture_count(regex->regex); |
1170 | 523 |
1171 if (n < 0) { | 524 if (n < 0) { |
1189 | 542 |
1190 if (regex->ncaptures) { | 543 if (regex->ncaptures) { |
1191 regex->ncaptures = (regex->ncaptures + 1) * 3; | 544 regex->ncaptures = (regex->ncaptures + 1) * 3; |
1192 } | 545 } |
1193 | 546 |
1194 regex_end = ngx_http_rewrite_add_code(lcf->codes, | 547 if (lcf->max_captures < regex->ncaptures) { |
1195 sizeof(ngx_http_rewrite_regex_end_code_t), | 548 lcf->max_captures = regex->ncaptures; |
1196 ®ex); | 549 } |
550 | |
551 regex_end = ngx_http_script_add_code(lcf->codes, | |
552 sizeof(ngx_http_script_regex_end_code_t), | |
553 ®ex); | |
1197 if (regex_end == NULL) { | 554 if (regex_end == NULL) { |
1198 return NGX_CONF_ERROR; | 555 return NGX_CONF_ERROR; |
1199 } | 556 } |
1200 | 557 |
1201 regex_end->code = ngx_http_rewrite_regex_end_code; | 558 regex_end->code = ngx_http_script_regex_end_code; |
1202 regex_end->uri = regex->uri; | 559 regex_end->uri = regex->uri; |
1203 regex_end->args = regex->args; | 560 regex_end->args = regex->args; |
561 regex_end->add_args = regex->add_args; | |
1204 regex_end->redirect = regex->redirect; | 562 regex_end->redirect = regex->redirect; |
1205 | 563 |
1206 if (last) { | 564 if (last) { |
1207 code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t), | 565 code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), |
1208 ®ex); | 566 ®ex); |
1209 if (code == NULL) { | 567 if (code == NULL) { |
1210 return NGX_CONF_ERROR; | 568 return NGX_CONF_ERROR; |
1211 } | 569 } |
1212 | 570 |
1213 *code = (uintptr_t) NULL; | 571 *code = (uintptr_t) NULL; |
1223 static char * | 581 static char * |
1224 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 582 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
1225 { | 583 { |
1226 ngx_http_rewrite_loc_conf_t *lcf = conf; | 584 ngx_http_rewrite_loc_conf_t *lcf = conf; |
1227 | 585 |
1228 ngx_str_t *value; | 586 ngx_str_t *value; |
1229 ngx_http_rewrite_return_code_t *ret; | 587 ngx_http_script_return_code_t *ret; |
1230 | 588 |
1231 ret = ngx_http_rewrite_start_code(cf->pool, &lcf->codes, | 589 ret = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1232 sizeof(ngx_http_rewrite_return_code_t)); | 590 sizeof(ngx_http_script_return_code_t)); |
1233 if (ret == NULL) { | 591 if (ret == NULL) { |
1234 return NGX_CONF_ERROR; | 592 return NGX_CONF_ERROR; |
1235 } | 593 } |
1236 | 594 |
1237 value = cf->args->elts; | 595 value = cf->args->elts; |
1238 | 596 |
1239 ret->code = ngx_http_rewrite_return_code; | 597 ret->code = ngx_http_script_return_code; |
1240 ret->null = (uintptr_t) NULL; | 598 ret->null = (uintptr_t) NULL; |
1241 | 599 |
1242 ret->status = ngx_atoi(value[1].data, value[1].len); | 600 ret->status = ngx_atoi(value[1].data, value[1].len); |
1243 | 601 |
1244 if (ret->status == (uintptr_t) NGX_ERROR) { | 602 if (ret->status == (uintptr_t) NGX_ERROR) { |
1260 ngx_uint_t i; | 618 ngx_uint_t i; |
1261 ngx_conf_t save; | 619 ngx_conf_t save; |
1262 ngx_http_module_t *module; | 620 ngx_http_module_t *module; |
1263 ngx_http_conf_ctx_t *ctx, *pctx; | 621 ngx_http_conf_ctx_t *ctx, *pctx; |
1264 ngx_http_core_loc_conf_t *clcf, *pclcf, **clcfp; | 622 ngx_http_core_loc_conf_t *clcf, *pclcf, **clcfp; |
1265 ngx_http_rewrite_if_code_t *if_code; | 623 ngx_http_script_if_code_t *if_code; |
1266 ngx_http_rewrite_loc_conf_t *nlcf; | 624 ngx_http_rewrite_loc_conf_t *nlcf; |
1267 | 625 |
1268 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); | 626 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
1269 if (ctx == NULL) { | 627 if (ctx == NULL) { |
1270 return NGX_CONF_ERROR; | 628 return NGX_CONF_ERROR; |
1322 | 680 |
1323 if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { | 681 if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { |
1324 return NGX_CONF_ERROR; | 682 return NGX_CONF_ERROR; |
1325 } | 683 } |
1326 | 684 |
1327 if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_rewrite_if_code_t)); | 685 if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t)); |
1328 if (if_code == NULL) { | 686 if (if_code == NULL) { |
1329 return NULL; | 687 return NULL; |
1330 } | 688 } |
1331 | 689 |
1332 if_code->code = ngx_http_rewrite_if_code; | 690 if_code->code = ngx_http_script_if_code; |
1333 | 691 |
1334 elts = lcf->codes->elts; | 692 elts = lcf->codes->elts; |
1335 | 693 |
1336 | 694 |
1337 /* the inside directives must compile to the same code array */ | 695 /* the inside directives must compile to the same code array */ |
1360 return rv; | 718 return rv; |
1361 } | 719 } |
1362 | 720 |
1363 | 721 |
1364 if (elts != lcf->codes->elts) { | 722 if (elts != lcf->codes->elts) { |
1365 if_code = (ngx_http_rewrite_if_code_t *) | 723 if_code = (ngx_http_script_if_code_t *) |
1366 ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); | 724 ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); |
1367 } | 725 } |
1368 | 726 |
1369 if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | 727 if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts |
1370 - (u_char *) if_code; | 728 - (u_char *) if_code; |
1374 | 732 |
1375 | 733 |
1376 static char * | 734 static char * |
1377 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) | 735 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) |
1378 { | 736 { |
1379 ngx_str_t *value, err; | 737 ngx_str_t *value, err; |
1380 ngx_uint_t cur, last; | 738 ngx_uint_t cur, last; |
1381 ngx_http_rewrite_regex_code_t *regex; | 739 ngx_http_script_regex_code_t *regex; |
1382 u_char errstr[NGX_MAX_CONF_ERRSTR]; | 740 u_char errstr[NGX_MAX_CONF_ERRSTR]; |
1383 | 741 |
1384 value = cf->args->elts; | 742 value = cf->args->elts; |
1385 last = cf->args->nelts - 1; | 743 last = cf->args->nelts - 1; |
1386 | 744 |
1387 if (value[1].len < 1 || value[1].data[0] != '(') { | 745 if (value[1].len < 1 || value[1].data[0] != '(') { |
1438 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 796 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1439 "unexpected \"%V\" in condition", &value[cur]); | 797 "unexpected \"%V\" in condition", &value[cur]); |
1440 return NGX_CONF_ERROR; | 798 return NGX_CONF_ERROR; |
1441 } | 799 } |
1442 | 800 |
1443 regex = ngx_http_rewrite_start_code(cf->pool, &lcf->codes, | 801 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1444 sizeof(ngx_http_rewrite_regex_code_t)); | 802 sizeof(ngx_http_script_regex_code_t)); |
1445 if (regex == NULL) { | 803 if (regex == NULL) { |
1446 return NGX_CONF_ERROR; | 804 return NGX_CONF_ERROR; |
1447 } | 805 } |
806 | |
807 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); | |
1448 | 808 |
1449 err.len = NGX_MAX_CONF_ERRSTR; | 809 err.len = NGX_MAX_CONF_ERRSTR; |
1450 err.data = errstr; | 810 err.data = errstr; |
1451 | 811 |
1452 regex->regex = ngx_regex_compile(&value[last], | 812 regex->regex = ngx_regex_compile(&value[last], |
1456 if (regex->regex == NULL) { | 816 if (regex->regex == NULL) { |
1457 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | 817 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); |
1458 return NGX_CONF_ERROR; | 818 return NGX_CONF_ERROR; |
1459 } | 819 } |
1460 | 820 |
1461 regex->code = ngx_http_rewrite_regex_start_code; | 821 regex->code = ngx_http_script_regex_start_code; |
1462 regex->size = 0; | 822 regex->next = sizeof(ngx_http_script_regex_code_t); |
1463 regex->ncaptures = 0; | |
1464 regex->status = 0; | |
1465 regex->next = sizeof(ngx_http_rewrite_regex_code_t); | |
1466 regex->test = 1; | 823 regex->test = 1; |
1467 regex->uri = 0; | |
1468 regex->args = 0; | |
1469 regex->redirect = 0; | |
1470 regex->break_cycle = 0; | |
1471 regex->name = value[last]; | 824 regex->name = value[last]; |
1472 | 825 |
1473 return NGX_CONF_OK; | 826 return NGX_CONF_OK; |
1474 } | 827 } |
1475 | 828 |
1482 | 835 |
1483 static char * | 836 static char * |
1484 ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | 837 ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, |
1485 ngx_str_t *value) | 838 ngx_str_t *value) |
1486 { | 839 { |
1487 ngx_http_variable_t *var; | 840 ngx_int_t index; |
1488 ngx_http_rewrite_code_pt *code; | 841 ngx_http_script_code_pt *code; |
1489 ngx_http_rewrite_var_code_t *var_code; | 842 ngx_http_script_var_code_t *var_code; |
1490 | 843 |
1491 value->len--; | 844 value->len--; |
1492 value->data++; | 845 value->data++; |
1493 | 846 |
1494 if (value->len == sizeof("invalid_referer") - 1 | 847 if (value->len == sizeof("invalid_referer") - 1 |
1495 && ngx_strncmp(value->data, "invalid_referer", | 848 && ngx_strncmp(value->data, "invalid_referer", |
1496 sizeof("invalid_referer") - 1) == 0) | 849 sizeof("invalid_referer") - 1) == 0) |
1497 { | 850 { |
1498 code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes, | 851 code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1499 sizeof(ngx_http_rewrite_code_pt)); | 852 sizeof(ngx_http_script_code_pt)); |
1500 if (code == NULL) { | 853 if (code == NULL) { |
1501 return NGX_CONF_ERROR; | 854 return NGX_CONF_ERROR; |
1502 } | 855 } |
1503 | 856 |
1504 *code = ngx_http_rewrite_invalid_referer_code; | 857 *code = ngx_http_rewrite_invalid_referer_code; |
1505 | 858 |
1506 } else { | 859 } else { |
1507 var = ngx_http_add_variable(cf, value, 0); | 860 index = ngx_http_get_variable_index(cf, value); |
1508 | 861 |
1509 if (var == NULL) { | 862 if (index == NGX_ERROR) { |
1510 return NGX_CONF_ERROR; | 863 return NGX_CONF_ERROR; |
1511 } | 864 } |
1512 | 865 |
1513 var_code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes, | 866 var_code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1514 sizeof(ngx_http_rewrite_var_code_t)); | 867 sizeof(ngx_http_script_var_code_t)); |
1515 if (var_code == NULL) { | 868 if (var_code == NULL) { |
1516 return NGX_CONF_ERROR; | 869 return NGX_CONF_ERROR; |
1517 } | 870 } |
1518 | 871 |
1519 var_code->code = ngx_http_rewrite_var_code; | 872 var_code->code = ngx_http_script_var_code; |
1520 var_code->index = var->index; | 873 var_code->index = index; |
1521 } | 874 } |
1522 | 875 |
1523 return NGX_CONF_OK; | 876 return NGX_CONF_OK; |
1524 } | 877 } |
1525 | 878 |
1622 static char * | 975 static char * |
1623 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 976 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
1624 { | 977 { |
1625 ngx_http_rewrite_loc_conf_t *lcf = conf; | 978 ngx_http_rewrite_loc_conf_t *lcf = conf; |
1626 | 979 |
1627 ngx_int_t n; | 980 ngx_int_t n, index; |
1628 ngx_str_t *value; | 981 ngx_str_t *value; |
1629 ngx_http_variable_t *v; | 982 ngx_http_variable_t *v; |
1630 ngx_http_rewrite_var_code_t *var; | 983 ngx_http_script_var_code_t *var; |
1631 ngx_http_rewrite_value_code_t *val; | 984 ngx_http_script_value_code_t *val; |
1632 | 985 |
1633 value = cf->args->elts; | 986 value = cf->args->elts; |
1634 | 987 |
1635 if (value[1].data[0] != '$') { | 988 if (value[1].data[0] != '$') { |
1636 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 989 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
1639 } | 992 } |
1640 | 993 |
1641 value[1].len--; | 994 value[1].len--; |
1642 value[1].data++; | 995 value[1].data++; |
1643 | 996 |
1644 v = ngx_http_add_variable(cf, &value[1], 1); | 997 v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE); |
1645 if (v == NULL) { | 998 if (v == NULL) { |
1646 return NGX_CONF_ERROR; | 999 return NGX_CONF_ERROR; |
1647 } | 1000 } |
1648 | 1001 |
1002 index = ngx_http_get_variable_index(cf, &value[1]); | |
1003 if (index == NGX_ERROR) { | |
1004 return NGX_CONF_ERROR; | |
1005 } | |
1006 | |
1649 v->handler = ngx_http_rewrite_var; | 1007 v->handler = ngx_http_rewrite_var; |
1650 v->data = v->index; | 1008 v->data = index; |
1651 | 1009 |
1652 val = ngx_http_rewrite_start_code(cf->pool, &lcf->codes, | 1010 val = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1653 sizeof(ngx_http_rewrite_value_code_t)); | 1011 sizeof(ngx_http_script_value_code_t)); |
1654 if (val == NULL) { | 1012 if (val == NULL) { |
1655 return NGX_CONF_ERROR; | 1013 return NGX_CONF_ERROR; |
1656 } | 1014 } |
1657 | 1015 |
1658 n = ngx_atoi(value[2].data, value[2].len); | 1016 n = ngx_atoi(value[2].data, value[2].len); |
1659 | 1017 |
1660 if (n == NGX_ERROR) { | 1018 if (n == NGX_ERROR) { |
1661 n = 0; | 1019 n = 0; |
1662 } | 1020 } |
1663 | 1021 |
1664 val->code = ngx_http_rewrite_value_code; | 1022 val->code = ngx_http_script_value_code; |
1665 val->value = (uintptr_t) n; | 1023 val->value = (uintptr_t) n; |
1666 val->text_len = (uintptr_t) value[2].len; | 1024 val->text_len = (uintptr_t) value[2].len; |
1667 val->text_data = (uintptr_t) value[2].data; | 1025 val->text_data = (uintptr_t) value[2].data; |
1668 | 1026 |
1669 var = ngx_http_rewrite_start_code(cf->pool, &lcf->codes, | 1027 var = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1670 sizeof(ngx_http_rewrite_var_code_t)); | 1028 sizeof(ngx_http_script_var_code_t)); |
1671 if (var == NULL) { | 1029 if (var == NULL) { |
1672 return NGX_CONF_ERROR; | 1030 return NGX_CONF_ERROR; |
1673 } | 1031 } |
1674 | 1032 |
1675 var->code = ngx_http_rewrite_set_var_code; | 1033 var->code = ngx_http_script_set_var_code; |
1676 var->index = (uintptr_t) v->index; | 1034 var->index = (uintptr_t) index; |
1677 | 1035 |
1678 return NGX_CONF_OK; | 1036 return NGX_CONF_OK; |
1679 } | 1037 } |
1680 | |
1681 | |
1682 static void * | |
1683 ngx_http_rewrite_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size) | |
1684 { | |
1685 if (*codes == NULL) { | |
1686 *codes = ngx_array_create(pool, 256, 1); | |
1687 if (*codes == NULL) { | |
1688 return NULL; | |
1689 } | |
1690 } | |
1691 | |
1692 return ngx_array_push_n(*codes, size); | |
1693 } | |
1694 | |
1695 | |
1696 static void * | |
1697 ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size, void *code) | |
1698 { | |
1699 u_char *elts, **p; | |
1700 void *new; | |
1701 | |
1702 elts = codes->elts; | |
1703 | |
1704 new = ngx_array_push_n(codes, size); | |
1705 if (new == NULL) { | |
1706 return NGX_CONF_ERROR; | |
1707 } | |
1708 | |
1709 if (elts != codes->elts) { | |
1710 p = code; | |
1711 *p += (u_char *) codes->elts - elts; | |
1712 } | |
1713 | |
1714 return new; | |
1715 } |