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 = &regex->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 &regex); 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 &regex);
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 &regex);
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 &regex); 549 }
550
551 regex_end = ngx_http_script_add_code(lcf->codes,
552 sizeof(ngx_http_script_regex_end_code_t),
553 &regex);
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 &regex); 566 &regex);
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 }