Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_rewrite_module.c @ 4311:45272aab5eea
Unlock of shared memory zones on process crash.
If process exited abnormally while holding lock on some shared memory zone -
unlock it. It may be not safe thing to do (as crash with lock held may
result in corrupted shared memory structure, and other processes will
subsequently crash while trying to access shared data), therefore complain
loudly if unlock succeeds.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 23 Nov 2011 14:09:19 +0000 |
parents | 470462cfa31b |
children | d620f497c50f |
rev | line source |
---|---|
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
1 |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
2 /* |
444
42d11f017717
nginx-0.1.0-2004-09-29-20:00:49 import; remove years from copyright
Igor Sysoev <igor@sysoev.ru>
parents:
441
diff
changeset
|
3 * Copyright (C) Igor Sysoev |
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
4 */ |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
5 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
6 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 #include <ngx_config.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_core.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_http.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
11 |
485 | 12 typedef struct { |
577 | 13 ngx_array_t *codes; /* uintptr_t */ |
485 | 14 |
577 | 15 ngx_uint_t stack_size; |
485 | 16 |
577 | 17 ngx_flag_t log; |
635 | 18 ngx_flag_t uninitialized_variable_warn; |
485 | 19 } ngx_http_rewrite_loc_conf_t; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
20 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
21 |
485 | 22 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); |
23 static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, | |
487 | 24 void *parent, void *child); |
681 | 25 static ngx_int_t ngx_http_rewrite_init(ngx_conf_t *cf); |
485 | 26 static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
27 static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, | |
487 | 28 void *conf); |
527 | 29 static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, |
30 void *conf); | |
485 | 31 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, |
487 | 32 void *conf); |
501 | 33 static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, |
34 ngx_http_rewrite_loc_conf_t *lcf); | |
35 static char *ngx_http_rewrite_variable(ngx_conf_t *cf, | |
36 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | |
509 | 37 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, |
501 | 38 void *conf); |
577 | 39 static char * ngx_http_rewrite_value(ngx_conf_t *cf, |
40 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
41 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
42 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
43 static ngx_command_t ngx_http_rewrite_commands[] = { |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
44 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
45 { ngx_string("rewrite"), |
485 | 46 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
47 |NGX_CONF_TAKE23, | |
48 ngx_http_rewrite, | |
49 NGX_HTTP_LOC_CONF_OFFSET, | |
50 0, | |
51 NULL }, | |
52 | |
53 { ngx_string("return"), | |
54 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
3633 | 55 |NGX_CONF_TAKE12, |
485 | 56 ngx_http_rewrite_return, |
57 NGX_HTTP_LOC_CONF_OFFSET, | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
58 0, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
59 NULL }, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
60 |
527 | 61 { ngx_string("break"), |
62 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
63 |NGX_CONF_NOARGS, | |
64 ngx_http_rewrite_break, | |
65 NGX_HTTP_LOC_CONF_OFFSET, | |
66 0, | |
67 NULL }, | |
68 | |
485 | 69 { ngx_string("if"), |
70 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE, | |
71 ngx_http_rewrite_if, | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
72 NGX_HTTP_LOC_CONF_OFFSET, |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
73 0, |
485 | 74 NULL }, |
75 | |
501 | 76 { ngx_string("set"), |
77 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
78 |NGX_CONF_TAKE2, | |
79 ngx_http_rewrite_set, | |
80 NGX_HTTP_LOC_CONF_OFFSET, | |
81 0, | |
82 NULL }, | |
83 | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
84 { ngx_string("rewrite_log"), |
635 | 85 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF |
86 |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
87 ngx_conf_set_flag_slot, |
485 | 88 NGX_HTTP_LOC_CONF_OFFSET, |
89 offsetof(ngx_http_rewrite_loc_conf_t, log), | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
90 NULL }, |
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
91 |
635 | 92 { ngx_string("uninitialized_variable_warn"), |
93 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF | |
94 |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, | |
95 ngx_conf_set_flag_slot, | |
96 NGX_HTTP_LOC_CONF_OFFSET, | |
97 offsetof(ngx_http_rewrite_loc_conf_t, uninitialized_variable_warn), | |
98 NULL }, | |
99 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
100 ngx_null_command |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
101 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
102 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
103 |
667 | 104 static ngx_http_module_t ngx_http_rewrite_module_ctx = { |
509 | 105 NULL, /* preconfiguration */ |
681 | 106 ngx_http_rewrite_init, /* postconfiguration */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
107 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
108 NULL, /* create main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
109 NULL, /* init main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
110 |
485 | 111 NULL, /* create server configuration */ |
112 NULL, /* merge server configuration */ | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
113 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
114 ngx_http_rewrite_create_loc_conf, /* create location configration */ |
485 | 115 ngx_http_rewrite_merge_loc_conf /* merge location configration */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
116 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
117 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
118 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
119 ngx_module_t ngx_http_rewrite_module = { |
509 | 120 NGX_MODULE_V1, |
577 | 121 &ngx_http_rewrite_module_ctx, /* module context */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
122 ngx_http_rewrite_commands, /* module directives */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
123 NGX_HTTP_MODULE, /* module type */ |
541 | 124 NULL, /* init master */ |
681 | 125 NULL, /* init module */ |
541 | 126 NULL, /* init process */ |
127 NULL, /* init thread */ | |
128 NULL, /* exit thread */ | |
129 NULL, /* exit process */ | |
130 NULL, /* exit master */ | |
131 NGX_MODULE_V1_PADDING | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
132 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
133 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
134 |
487 | 135 static ngx_int_t |
136 ngx_http_rewrite_handler(ngx_http_request_t *r) | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
137 { |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
138 ngx_int_t index; |
509 | 139 ngx_http_script_code_pt code; |
140 ngx_http_script_engine_t *e; | |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
141 ngx_http_core_srv_conf_t *cscf; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
142 ngx_http_core_main_conf_t *cmcf; |
635 | 143 ngx_http_rewrite_loc_conf_t *rlcf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
144 |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
145 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
146 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
147 index = cmcf->phase_engine.location_rewrite_index; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
148 |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
149 if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) { |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
150 /* skipping location rewrite phase for server null location */ |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
151 return NGX_DECLINED; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
152 } |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
153 |
635 | 154 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
155 |
635 | 156 if (rlcf->codes == NULL) { |
485 | 157 return NGX_DECLINED; |
158 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
159 |
509 | 160 e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)); |
501 | 161 if (e == NULL) { |
485 | 162 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
163 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
164 |
509 | 165 e->sp = ngx_pcalloc(r->pool, |
635 | 166 rlcf->stack_size * sizeof(ngx_http_variable_value_t)); |
485 | 167 if (e->sp == NULL) { |
168 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
169 } | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
170 |
635 | 171 e->ip = rlcf->codes->elts; |
509 | 172 e->request = r; |
485 | 173 e->quote = 1; |
635 | 174 e->log = rlcf->log; |
485 | 175 e->status = NGX_DECLINED; |
176 | |
177 while (*(uintptr_t *) e->ip) { | |
509 | 178 code = *(ngx_http_script_code_pt *) e->ip; |
485 | 179 code(e); |
180 } | |
181 | |
4147
7f64de1cc2c0
Fix for double content when return is used in error_page handler.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3633
diff
changeset
|
182 if (e->status < NGX_HTTP_BAD_REQUEST) { |
7f64de1cc2c0
Fix for double content when return is used in error_page handler.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3633
diff
changeset
|
183 return e->status; |
739
9f983de19a1d
after redirecting by error_page any rewrite directive will return this code,
Igor Sysoev <igor@sysoev.ru>
parents:
726
diff
changeset
|
184 } |
9f983de19a1d
after redirecting by error_page any rewrite directive will return this code,
Igor Sysoev <igor@sysoev.ru>
parents:
726
diff
changeset
|
185 |
726
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
186 if (r->err_status == 0) { |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
187 return e->status; |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
188 } |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
189 |
7b71936d5299
fix: "return" always overrode "error_page" response code
Igor Sysoev <igor@sysoev.ru>
parents:
681
diff
changeset
|
190 return r->err_status; |
485 | 191 } |
192 | |
193 | |
573 | 194 static ngx_int_t |
195 ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
196 uintptr_t data) | |
501 | 197 { |
635 | 198 ngx_http_variable_t *var; |
199 ngx_http_core_main_conf_t *cmcf; | |
200 ngx_http_rewrite_loc_conf_t *rlcf; | |
201 | |
202 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); | |
203 | |
204 if (rlcf->uninitialized_variable_warn == 0) { | |
205 *v = ngx_http_variable_null_value; | |
206 return NGX_OK; | |
207 } | |
501 | 208 |
209 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
210 | |
211 var = cmcf->variables.elts; | |
212 | |
213 /* | |
214 * the ngx_http_rewrite_module sets variables directly in r->variables, | |
519 | 215 * and they should be handled by ngx_http_get_indexed_variable(), |
501 | 216 * so the handler is called only if the variable is not initialized |
217 */ | |
218 | |
635 | 219 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, |
501 | 220 "using uninitialized \"%V\" variable", &var[data].name); |
221 | |
577 | 222 *v = ngx_http_variable_null_value; |
573 | 223 |
224 return NGX_OK; | |
501 | 225 } |
226 | |
227 | |
487 | 228 static void * |
229 ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf) | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
230 { |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
231 ngx_http_rewrite_loc_conf_t *conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
232 |
501 | 233 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)); |
234 if (conf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2547
diff
changeset
|
235 return NULL; |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
236 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
237 |
485 | 238 conf->stack_size = NGX_CONF_UNSET_UINT; |
239 conf->log = NGX_CONF_UNSET; | |
635 | 240 conf->uninitialized_variable_warn = NGX_CONF_UNSET; |
485 | 241 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
242 return conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
243 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
244 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
245 |
487 | 246 static char * |
247 ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
248 { |
485 | 249 ngx_http_rewrite_loc_conf_t *prev = parent; |
250 ngx_http_rewrite_loc_conf_t *conf = child; | |
251 | |
509 | 252 uintptr_t *code; |
485 | 253 |
254 ngx_conf_merge_value(conf->log, prev->log, 0); | |
635 | 255 ngx_conf_merge_value(conf->uninitialized_variable_warn, |
256 prev->uninitialized_variable_warn, 1); | |
663 | 257 ngx_conf_merge_uint_value(conf->stack_size, prev->stack_size, 10); |
485 | 258 |
259 if (conf->codes == NULL) { | |
260 return NGX_CONF_OK; | |
261 } | |
262 | |
263 if (conf->codes == prev->codes) { | |
264 return NGX_CONF_OK; | |
265 } | |
266 | |
501 | 267 code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)); |
268 if (code == NULL) { | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
269 return NGX_CONF_ERROR; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
270 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
271 |
485 | 272 *code = (uintptr_t) NULL; |
273 | |
274 return NGX_CONF_OK; | |
275 } | |
276 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
277 |
509 | 278 static ngx_int_t |
681 | 279 ngx_http_rewrite_init(ngx_conf_t *cf) |
577 | 280 { |
509 | 281 ngx_http_handler_pt *h; |
282 ngx_http_core_main_conf_t *cmcf; | |
283 | |
681 | 284 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
509 | 285 |
573 | 286 h = ngx_array_push(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers); |
287 if (h == NULL) { | |
288 return NGX_ERROR; | |
289 } | |
290 | |
291 *h = ngx_http_rewrite_handler; | |
292 | |
509 | 293 h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); |
294 if (h == NULL) { | |
295 return NGX_ERROR; | |
296 } | |
297 | |
298 *h = ngx_http_rewrite_handler; | |
299 | |
300 return NGX_OK; | |
577 | 301 } |
509 | 302 |
303 | |
487 | 304 static char * |
305 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 306 { |
577 | 307 ngx_http_rewrite_loc_conf_t *lcf = conf; |
308 | |
3325 | 309 ngx_str_t *value; |
509 | 310 ngx_uint_t last; |
3325 | 311 ngx_regex_compile_t rc; |
509 | 312 ngx_http_script_code_pt *code; |
313 ngx_http_script_compile_t sc; | |
314 ngx_http_script_regex_code_t *regex; | |
315 ngx_http_script_regex_end_code_t *regex_end; | |
316 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
485 | 317 |
509 | 318 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
319 sizeof(ngx_http_script_regex_code_t)); | |
485 | 320 if (regex == NULL) { |
321 return NGX_CONF_ERROR; | |
322 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
323 |
509 | 324 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
325 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
326 value = cf->args->elts; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
327 |
3325 | 328 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); |
329 | |
330 rc.pattern = value[1]; | |
331 rc.err.len = NGX_MAX_CONF_ERRSTR; | |
332 rc.err.data = errstr; | |
485 | 333 |
334 /* TODO: NGX_REGEX_CASELESS */ | |
335 | |
3325 | 336 regex->regex = ngx_http_regex_compile(cf, &rc); |
485 | 337 if (regex->regex == NULL) { |
338 return NGX_CONF_ERROR; | |
339 } | |
340 | |
509 | 341 regex->code = ngx_http_script_regex_start_code; |
485 | 342 regex->uri = 1; |
343 regex->name = value[1]; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
344 |
509 | 345 if (value[2].data[value[2].len - 1] == '?') { |
346 | |
347 /* the last "?" drops the original arguments */ | |
348 value[2].len--; | |
349 | |
350 } else { | |
351 regex->add_args = 1; | |
352 } | |
353 | |
485 | 354 last = 0; |
355 | |
3524
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
356 if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0 |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
357 || ngx_strncmp(value[2].data, "https://", sizeof("https://") - 1) == 0 |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
358 || ngx_strncmp(value[2].data, "$scheme", sizeof("$scheme") - 1) == 0) |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
359 { |
2054
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
360 regex->status = NGX_HTTP_MOVED_TEMPORARILY; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
361 regex->redirect = 1; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
362 last = 1; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
363 } |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
364 |
485 | 365 if (cf->args->nelts == 4) { |
366 if (ngx_strcmp(value[3].data, "last") == 0) { | |
367 last = 1; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
368 |
487 | 369 } else if (ngx_strcmp(value[3].data, "break") == 0) { |
370 regex->break_cycle = 1; | |
371 last = 1; | |
372 | |
485 | 373 } else if (ngx_strcmp(value[3].data, "redirect") == 0) { |
374 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | |
375 regex->redirect = 1; | |
376 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
377 |
485 | 378 } else if (ngx_strcmp(value[3].data, "permanent") == 0) { |
379 regex->status = NGX_HTTP_MOVED_PERMANENTLY; | |
380 regex->redirect = 1; | |
381 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
382 |
485 | 383 } else { |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
384 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
461 | 385 "invalid parameter \"%V\"", &value[3]); |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
386 return NGX_CONF_ERROR; |
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
387 } |
485 | 388 } |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
389 |
509 | 390 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
485 | 391 |
509 | 392 sc.cf = cf; |
393 sc.source = &value[2]; | |
394 sc.lengths = ®ex->lengths; | |
395 sc.values = &lcf->codes; | |
396 sc.variables = ngx_http_script_variables_count(&value[2]); | |
397 sc.main = regex; | |
398 sc.complete_lengths = 1; | |
399 sc.compile_args = !regex->redirect; | |
485 | 400 |
509 | 401 if (ngx_http_script_compile(&sc) != NGX_OK) { |
402 return NGX_CONF_ERROR; | |
403 } | |
485 | 404 |
509 | 405 regex = sc.main; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
406 |
509 | 407 regex->size = sc.size; |
408 regex->args = sc.args; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
409 |
641 | 410 if (sc.variables == 0 && !sc.dup_capture) { |
509 | 411 regex->lengths = NULL; |
485 | 412 } |
413 | |
509 | 414 regex_end = ngx_http_script_add_code(lcf->codes, |
415 sizeof(ngx_http_script_regex_end_code_t), | |
416 ®ex); | |
485 | 417 if (regex_end == NULL) { |
418 return NGX_CONF_ERROR; | |
419 } | |
420 | |
509 | 421 regex_end->code = ngx_http_script_regex_end_code; |
485 | 422 regex_end->uri = regex->uri; |
423 regex_end->args = regex->args; | |
509 | 424 regex_end->add_args = regex->add_args; |
485 | 425 regex_end->redirect = regex->redirect; |
426 | |
427 if (last) { | |
517 | 428 code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ®ex); |
485 | 429 if (code == NULL) { |
430 return NGX_CONF_ERROR; | |
218
05592fd7a436
nginx-0.0.1-2004-01-05-23:55:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
216
diff
changeset
|
431 } |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
432 |
3184 | 433 *code = NULL; |
485 | 434 } |
435 | |
436 regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
437 - (u_char *) regex; | |
438 | |
439 return NGX_CONF_OK; | |
440 } | |
441 | |
442 | |
487 | 443 static char * |
444 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 445 { |
577 | 446 ngx_http_rewrite_loc_conf_t *lcf = conf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
447 |
3633 | 448 u_char *p; |
449 ngx_str_t *value, *v; | |
450 ngx_http_script_return_code_t *ret; | |
451 ngx_http_compile_complex_value_t ccv; | |
485 | 452 |
509 | 453 ret = ngx_http_script_start_code(cf->pool, &lcf->codes, |
454 sizeof(ngx_http_script_return_code_t)); | |
485 | 455 if (ret == NULL) { |
456 return NGX_CONF_ERROR; | |
457 } | |
458 | |
459 value = cf->args->elts; | |
460 | |
3633 | 461 ngx_memzero(ret, sizeof(ngx_http_script_return_code_t)); |
462 | |
509 | 463 ret->code = ngx_http_script_return_code; |
485 | 464 |
3633 | 465 p = value[1].data; |
466 | |
467 ret->status = ngx_atoi(p, value[1].len); | |
485 | 468 |
469 if (ret->status == (uintptr_t) NGX_ERROR) { | |
3633 | 470 |
471 if (cf->args->nelts == 2 | |
472 && (ngx_strncmp(p, "http://", sizeof("http://") - 1) == 0 | |
473 || ngx_strncmp(p, "https://", sizeof("https://") - 1) == 0 | |
474 || ngx_strncmp(p, "$scheme", sizeof("$scheme") - 1) == 0)) | |
475 { | |
476 ret->status = NGX_HTTP_MOVED_TEMPORARILY; | |
477 v = &value[1]; | |
478 | |
479 } else { | |
480 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
481 "invalid return code \"%V\"", &value[1]); | |
482 return NGX_CONF_ERROR; | |
483 } | |
484 | |
485 } else { | |
486 | |
487 if (cf->args->nelts == 2) { | |
488 return NGX_CONF_OK; | |
489 } | |
490 | |
491 v = &value[2]; | |
492 } | |
493 | |
494 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
495 | |
496 ccv.cf = cf; | |
497 ccv.value = v; | |
498 ccv.complex_value = &ret->text; | |
499 | |
500 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
485 | 501 return NGX_CONF_ERROR; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
502 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
503 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
504 return NGX_CONF_OK; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
505 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
506 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
507 |
487 | 508 static char * |
527 | 509 ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
510 { | |
511 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
512 | |
513 ngx_http_script_code_pt *code; | |
514 | |
515 code = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(uintptr_t)); | |
516 if (code == NULL) { | |
517 return NGX_CONF_ERROR; | |
518 } | |
519 | |
520 *code = ngx_http_script_break_code; | |
521 | |
522 return NGX_CONF_OK; | |
523 } | |
524 | |
525 | |
526 static char * | |
487 | 527 ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
528 { |
577 | 529 ngx_http_rewrite_loc_conf_t *lcf = conf; |
485 | 530 |
531 void *mconf; | |
532 char *rv; | |
533 u_char *elts; | |
534 ngx_uint_t i; | |
535 ngx_conf_t save; | |
536 ngx_http_module_t *module; | |
537 ngx_http_conf_ctx_t *ctx, *pctx; | |
2027 | 538 ngx_http_core_loc_conf_t *clcf, *pclcf; |
509 | 539 ngx_http_script_if_code_t *if_code; |
485 | 540 ngx_http_rewrite_loc_conf_t *nlcf; |
541 | |
501 | 542 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
543 if (ctx == NULL) { | |
485 | 544 return NGX_CONF_ERROR; |
545 } | |
546 | |
547 pctx = cf->ctx; | |
548 ctx->main_conf = pctx->main_conf; | |
577 | 549 ctx->srv_conf = pctx->srv_conf; |
485 | 550 |
551 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | |
552 if (ctx->loc_conf == NULL) { | |
553 return NGX_CONF_ERROR; | |
554 } | |
555 | |
556 for (i = 0; ngx_modules[i]; i++) { | |
557 if (ngx_modules[i]->type != NGX_HTTP_MODULE) { | |
558 continue; | |
559 } | |
560 | |
561 module = ngx_modules[i]->ctx; | |
577 | 562 |
485 | 563 if (module->create_loc_conf) { |
564 | |
501 | 565 mconf = module->create_loc_conf(cf); |
566 if (mconf == NULL) { | |
485 | 567 return NGX_CONF_ERROR; |
568 } | |
569 | |
570 ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; | |
571 } | |
572 } | |
573 | |
574 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; | |
575 | |
576 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
577 clcf->loc_conf = ctx->loc_conf; | |
578 clcf->name = pclcf->name; | |
579 clcf->noname = 1; | |
580 | |
2027 | 581 if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { |
485 | 582 return NGX_CONF_ERROR; |
583 } | |
584 | |
501 | 585 if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { |
485 | 586 return NGX_CONF_ERROR; |
587 } | |
588 | |
509 | 589 if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t)); |
485 | 590 if (if_code == NULL) { |
3001 | 591 return NGX_CONF_ERROR; |
485 | 592 } |
593 | |
509 | 594 if_code->code = ngx_http_script_if_code; |
485 | 595 |
596 elts = lcf->codes->elts; | |
597 | |
598 | |
631 | 599 /* the inner directives must be compiled to the same code array */ |
485 | 600 |
601 nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index]; | |
602 nlcf->codes = lcf->codes; | |
603 | |
604 | |
605 save = *cf; | |
606 cf->ctx = ctx; | |
607 | |
608 if (pclcf->name.len == 0) { | |
609 if_code->loc_conf = NULL; | |
610 cf->cmd_type = NGX_HTTP_SIF_CONF; | |
611 | |
612 } else { | |
613 if_code->loc_conf = ctx->loc_conf; | |
614 cf->cmd_type = NGX_HTTP_LIF_CONF; | |
615 } | |
616 | |
617 rv = ngx_conf_parse(cf, NULL); | |
618 | |
619 *cf = save; | |
620 | |
621 if (rv != NGX_CONF_OK) { | |
622 return rv; | |
623 } | |
624 | |
625 | |
626 if (elts != lcf->codes->elts) { | |
509 | 627 if_code = (ngx_http_script_if_code_t *) |
485 | 628 ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); |
629 } | |
630 | |
631 if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
632 - (u_char *) if_code; | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
633 |
555 | 634 /* the code array belong to parent block */ |
635 | |
636 nlcf->codes = NULL; | |
637 | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
638 return NGX_CONF_OK; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
639 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
640 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
641 |
487 | 642 static char * |
501 | 643 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) |
644 { | |
631 | 645 u_char *p; |
646 size_t len; | |
3325 | 647 ngx_str_t *value; |
648 ngx_uint_t cur, last; | |
649 ngx_regex_compile_t rc; | |
577 | 650 ngx_http_script_code_pt *code; |
631 | 651 ngx_http_script_file_code_t *fop; |
509 | 652 ngx_http_script_regex_code_t *regex; |
653 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
501 | 654 |
655 value = cf->args->elts; | |
656 last = cf->args->nelts - 1; | |
657 | |
658 if (value[1].len < 1 || value[1].data[0] != '(') { | |
659 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
660 "invalid condition \"%V\"", &value[1]); | |
661 return NGX_CONF_ERROR; | |
662 } | |
663 | |
664 if (value[1].len == 1) { | |
665 cur = 2; | |
666 | |
667 } else { | |
668 cur = 1; | |
669 value[1].len--; | |
670 value[1].data++; | |
671 } | |
672 | |
673 if (value[last].len < 1 || value[last].data[value[last].len - 1] != ')') { | |
674 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
675 "invalid condition \"%V\"", &value[last]); | |
676 return NGX_CONF_ERROR; | |
677 } | |
678 | |
679 if (value[last].len == 1) { | |
680 last--; | |
681 | |
682 } else { | |
683 value[last].len--; | |
684 value[last].data[value[last].len] = '\0'; | |
685 } | |
686 | |
631 | 687 len = value[cur].len; |
688 p = value[cur].data; | |
689 | |
690 if (len > 1 && p[0] == '$') { | |
501 | 691 |
692 if (cur != last && cur + 2 != last) { | |
693 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
631 | 694 "invalid condition \"%V\"", &value[cur]); |
501 | 695 return NGX_CONF_ERROR; |
696 } | |
697 | |
577 | 698 if (ngx_http_rewrite_variable(cf, lcf, &value[cur]) != NGX_CONF_OK) { |
501 | 699 return NGX_CONF_ERROR; |
700 } | |
701 | |
702 if (cur == last) { | |
703 return NGX_CONF_OK; | |
704 } | |
705 | |
706 cur++; | |
707 | |
631 | 708 len = value[cur].len; |
709 p = value[cur].data; | |
710 | |
711 if (len == 1 && p[0] == '=') { | |
577 | 712 |
713 if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) { | |
714 return NGX_CONF_ERROR; | |
715 } | |
716 | |
717 code = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
718 sizeof(uintptr_t)); | |
719 if (code == NULL) { | |
720 return NGX_CONF_ERROR; | |
721 } | |
722 | |
723 *code = ngx_http_script_equal_code; | |
724 | |
725 return NGX_CONF_OK; | |
501 | 726 } |
727 | |
631 | 728 if (len == 2 && p[0] == '!' && p[1] == '=') { |
729 | |
577 | 730 if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) { |
731 return NGX_CONF_ERROR; | |
732 } | |
733 | |
734 code = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
735 sizeof(uintptr_t)); | |
736 if (code == NULL) { | |
737 return NGX_CONF_ERROR; | |
738 } | |
739 | |
740 *code = ngx_http_script_not_equal_code; | |
741 return NGX_CONF_OK; | |
501 | 742 } |
743 | |
631 | 744 if ((len == 1 && p[0] == '~') |
745 || (len == 2 && p[0] == '~' && p[1] == '*') | |
746 || (len == 2 && p[0] == '!' && p[1] == '~') | |
747 || (len == 3 && p[0] == '!' && p[1] == '~' && p[2] == '*')) | |
577 | 748 { |
749 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
750 sizeof(ngx_http_script_regex_code_t)); | |
751 if (regex == NULL) { | |
752 return NGX_CONF_ERROR; | |
753 } | |
509 | 754 |
577 | 755 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
756 | |
3325 | 757 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); |
577 | 758 |
3325 | 759 rc.pattern = value[last]; |
760 rc.options = (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0; | |
761 rc.err.len = NGX_MAX_CONF_ERRSTR; | |
762 rc.err.data = errstr; | |
501 | 763 |
3325 | 764 regex->regex = ngx_http_regex_compile(cf, &rc); |
577 | 765 if (regex->regex == NULL) { |
766 return NGX_CONF_ERROR; | |
767 } | |
768 | |
769 regex->code = ngx_http_script_regex_start_code; | |
770 regex->next = sizeof(ngx_http_script_regex_code_t); | |
771 regex->test = 1; | |
631 | 772 if (p[0] == '!') { |
773 regex->negative_test = 1; | |
774 } | |
577 | 775 regex->name = value[last]; |
501 | 776 |
577 | 777 return NGX_CONF_OK; |
501 | 778 } |
779 | |
577 | 780 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
781 "unexpected \"%V\" in condition", &value[cur]); | |
782 return NGX_CONF_ERROR; | |
631 | 783 |
784 } else if ((len == 2 && p[0] == '-') | |
785 || (len == 3 && p[0] == '!' && p[1] == '-')) | |
786 { | |
787 if (cur + 1 != last) { | |
788 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
789 "invalid condition \"%V\"", &value[cur]); | |
790 return NGX_CONF_ERROR; | |
791 } | |
792 | |
793 value[last].data[value[last].len] = '\0'; | |
794 value[last].len++; | |
795 | |
796 if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) { | |
797 return NGX_CONF_ERROR; | |
798 } | |
799 | |
800 fop = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
801 sizeof(ngx_http_script_file_code_t)); | |
802 if (fop == NULL) { | |
803 return NGX_CONF_ERROR; | |
804 } | |
805 | |
806 fop->code = ngx_http_script_file_code; | |
807 | |
808 if (p[1] == 'f') { | |
809 fop->op = ngx_http_script_file_plain; | |
810 return NGX_CONF_OK; | |
811 } | |
812 | |
669 | 813 if (p[1] == 'd') { |
814 fop->op = ngx_http_script_file_dir; | |
815 return NGX_CONF_OK; | |
816 } | |
817 | |
818 if (p[1] == 'e') { | |
819 fop->op = ngx_http_script_file_exists; | |
820 return NGX_CONF_OK; | |
821 } | |
822 | |
823 if (p[1] == 'x') { | |
824 fop->op = ngx_http_script_file_exec; | |
825 return NGX_CONF_OK; | |
826 } | |
827 | |
631 | 828 if (p[0] == '!') { |
829 if (p[2] == 'f') { | |
830 fop->op = ngx_http_script_file_not_plain; | |
831 return NGX_CONF_OK; | |
832 } | |
669 | 833 |
834 if (p[2] == 'd') { | |
835 fop->op = ngx_http_script_file_not_dir; | |
836 return NGX_CONF_OK; | |
837 } | |
838 | |
839 if (p[2] == 'e') { | |
840 fop->op = ngx_http_script_file_not_exists; | |
841 return NGX_CONF_OK; | |
842 } | |
843 | |
844 if (p[2] == 'x') { | |
845 fop->op = ngx_http_script_file_not_exec; | |
846 return NGX_CONF_OK; | |
847 } | |
631 | 848 } |
849 | |
850 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
851 "invalid condition \"%V\"", &value[cur]); | |
852 return NGX_CONF_ERROR; | |
501 | 853 } |
854 | |
855 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
856 "invalid condition \"%V\"", &value[cur]); | |
857 | |
858 return NGX_CONF_ERROR; | |
859 } | |
860 | |
861 | |
862 static char * | |
863 ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | |
864 ngx_str_t *value) | |
865 { | |
509 | 866 ngx_int_t index; |
867 ngx_http_script_var_code_t *var_code; | |
501 | 868 |
869 value->len--; | |
870 value->data++; | |
871 | |
577 | 872 index = ngx_http_get_variable_index(cf, value); |
501 | 873 |
577 | 874 if (index == NGX_ERROR) { |
875 return NGX_CONF_ERROR; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
876 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
877 |
577 | 878 var_code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
879 sizeof(ngx_http_script_var_code_t)); | |
880 if (var_code == NULL) { | |
881 return NGX_CONF_ERROR; | |
485 | 882 } |
883 | |
577 | 884 var_code->code = ngx_http_script_var_code; |
885 var_code->index = index; | |
485 | 886 |
887 return NGX_CONF_OK; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
888 } |
485 | 889 |
890 | |
501 | 891 static char * |
892 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
893 { | |
577 | 894 ngx_http_rewrite_loc_conf_t *lcf = conf; |
501 | 895 |
637 | 896 ngx_int_t index; |
897 ngx_str_t *value; | |
898 ngx_http_variable_t *v; | |
899 ngx_http_script_var_code_t *vcode; | |
900 ngx_http_script_var_handler_code_t *vhcode; | |
501 | 901 |
902 value = cf->args->elts; | |
903 | |
904 if (value[1].data[0] != '$') { | |
905 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
906 "invalid variable name \"%V\"", &value[1]); | |
907 return NGX_CONF_ERROR; | |
908 } | |
909 | |
910 value[1].len--; | |
911 value[1].data++; | |
912 | |
1565 | 913 v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE); |
501 | 914 if (v == NULL) { |
915 return NGX_CONF_ERROR; | |
916 } | |
917 | |
509 | 918 index = ngx_http_get_variable_index(cf, &value[1]); |
919 if (index == NGX_ERROR) { | |
920 return NGX_CONF_ERROR; | |
921 } | |
501 | 922 |
1189
5e1a8fe79c4b
allow to "set" $http_, $sent_http_, and $upstream_http_ variables
Igor Sysoev <igor@sysoev.ru>
parents:
739
diff
changeset
|
923 if (v->get_handler == NULL |
1192 | 924 && ngx_strncasecmp(value[1].data, (u_char *) "http_", 5) != 0 |
925 && ngx_strncasecmp(value[1].data, (u_char *) "sent_http_", 10) != 0 | |
926 && ngx_strncasecmp(value[1].data, (u_char *) "upstream_http_", 14) != 0) | |
1189
5e1a8fe79c4b
allow to "set" $http_, $sent_http_, and $upstream_http_ variables
Igor Sysoev <igor@sysoev.ru>
parents:
739
diff
changeset
|
927 { |
637 | 928 v->get_handler = ngx_http_rewrite_var; |
555 | 929 v->data = index; |
930 } | |
509 | 931 |
577 | 932 if (ngx_http_rewrite_value(cf, lcf, &value[2]) != NGX_CONF_OK) { |
933 return NGX_CONF_ERROR; | |
515 | 934 } |
501 | 935 |
637 | 936 if (v->set_handler) { |
937 vhcode = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
938 sizeof(ngx_http_script_var_handler_code_t)); | |
939 if (vhcode == NULL) { | |
940 return NGX_CONF_ERROR; | |
941 } | |
942 | |
943 vhcode->code = ngx_http_script_var_set_handler_code; | |
944 vhcode->handler = v->set_handler; | |
945 vhcode->data = v->data; | |
946 | |
947 return NGX_CONF_OK; | |
948 } | |
949 | |
950 vcode = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
951 sizeof(ngx_http_script_var_code_t)); | |
952 if (vcode == NULL) { | |
501 | 953 return NGX_CONF_ERROR; |
954 } | |
955 | |
637 | 956 vcode->code = ngx_http_script_set_var_code; |
957 vcode->index = (uintptr_t) index; | |
501 | 958 |
959 return NGX_CONF_OK; | |
960 } | |
577 | 961 |
962 | |
963 static char * | |
964 ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | |
965 ngx_str_t *value) | |
966 { | |
967 ngx_int_t n; | |
968 ngx_http_script_compile_t sc; | |
969 ngx_http_script_value_code_t *val; | |
970 ngx_http_script_complex_value_code_t *complex; | |
971 | |
972 n = ngx_http_script_variables_count(value); | |
973 | |
974 if (n == 0) { | |
975 val = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
976 sizeof(ngx_http_script_value_code_t)); | |
977 if (val == NULL) { | |
978 return NGX_CONF_ERROR; | |
979 } | |
980 | |
981 n = ngx_atoi(value->data, value->len); | |
982 | |
983 if (n == NGX_ERROR) { | |
984 n = 0; | |
985 } | |
986 | |
987 val->code = ngx_http_script_value_code; | |
988 val->value = (uintptr_t) n; | |
989 val->text_len = (uintptr_t) value->len; | |
990 val->text_data = (uintptr_t) value->data; | |
991 | |
992 return NGX_CONF_OK; | |
993 } | |
994 | |
995 complex = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
996 sizeof(ngx_http_script_complex_value_code_t)); | |
997 if (complex == NULL) { | |
998 return NGX_CONF_ERROR; | |
999 } | |
1000 | |
1001 complex->code = ngx_http_script_complex_value_code; | |
1002 complex->lengths = NULL; | |
1003 | |
1004 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1005 | |
1006 sc.cf = cf; | |
1007 sc.source = value; | |
1008 sc.lengths = &complex->lengths; | |
1009 sc.values = &lcf->codes; | |
1010 sc.variables = n; | |
1011 sc.complete_lengths = 1; | |
1012 | |
1013 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1014 return NGX_CONF_ERROR; | |
1015 } | |
1016 | |
1017 return NGX_CONF_OK; | |
1018 } |