Mercurial > hg > nginx
annotate src/http/modules/ngx_http_rewrite_module.c @ 555:7bd37aef1e7e release-0.2.6
nginx-0.2.6-RELEASE import
*) Change: while using load-balancing the time before the failed
backend retry was decreased from 60 to 10 seconds.
*) Change: the "proxy_pass_unparsed_uri" was canceled, the original URI
now passed, if the URI part is omitted in "proxy_pass" directive.
*) Feature: the "error_page" directive supports redirects and allows
more flexible to change an error code.
*) Change: the charset in the "Content-Type" header line now is ignored
in proxied subrequests.
*) Bugfix: if the URI was changed in the "if" block and request did not
found new configuration, then the ngx_http_rewrite_module rules ran
again.
*) Bugfix: if the "set" directive set the ngx_http_geo_module variable
in some configuration part, the this variable was not available in
other configuration parts and the "using uninitialized variable"
error was occurred; the bug had appeared in 0.2.2.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 05 Oct 2005 14:46:21 +0000 |
parents | b09ee85d0ac8 |
children | 58475592100c |
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 { |
509 | 13 ngx_str_t name; |
14 ngx_uint_t wildcard; | |
485 | 15 } ngx_http_rewrite_referer_t; |
16 | |
17 | |
18 typedef struct { | |
509 | 19 ngx_array_t *codes; /* uintptr_t */ |
20 ngx_array_t *referers; /* ngx_http_rewrite_referer_t */ | |
485 | 21 |
515 | 22 ngx_uint_t captures; |
509 | 23 ngx_uint_t stack_size; |
485 | 24 |
509 | 25 ngx_flag_t log; |
485 | 26 |
509 | 27 ngx_flag_t no_referer; |
28 ngx_flag_t blocked_referer; | |
485 | 29 } 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
|
30 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
31 |
485 | 32 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); |
33 static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, | |
487 | 34 void *parent, void *child); |
509 | 35 static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle); |
485 | 36 static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
37 static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, | |
487 | 38 void *conf); |
527 | 39 static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, |
40 void *conf); | |
485 | 41 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, |
487 | 42 void *conf); |
501 | 43 static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, |
44 ngx_http_rewrite_loc_conf_t *lcf); | |
45 static char *ngx_http_rewrite_variable(ngx_conf_t *cf, | |
46 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | |
487 | 47 static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf, |
48 ngx_command_t *cmd, void *conf); | |
509 | 49 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, |
501 | 50 void *conf); |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
51 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
52 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
53 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
|
54 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
55 { ngx_string("rewrite"), |
485 | 56 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
57 |NGX_CONF_TAKE23, | |
58 ngx_http_rewrite, | |
59 NGX_HTTP_LOC_CONF_OFFSET, | |
60 0, | |
61 NULL }, | |
62 | |
63 { ngx_string("return"), | |
64 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
65 |NGX_CONF_TAKE1, | |
66 ngx_http_rewrite_return, | |
67 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
|
68 0, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
69 NULL }, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
70 |
527 | 71 { ngx_string("break"), |
72 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
73 |NGX_CONF_NOARGS, | |
74 ngx_http_rewrite_break, | |
75 NGX_HTTP_LOC_CONF_OFFSET, | |
76 0, | |
77 NULL }, | |
78 | |
485 | 79 { ngx_string("if"), |
80 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE, | |
81 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
|
82 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
|
83 0, |
485 | 84 NULL }, |
85 | |
86 { ngx_string("valid_referers"), | |
87 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
88 ngx_http_rewrite_valid_referers, | |
89 NGX_HTTP_LOC_CONF_OFFSET, | |
90 0, | |
91 NULL }, | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
92 |
501 | 93 { ngx_string("set"), |
94 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
95 |NGX_CONF_TAKE2, | |
96 ngx_http_rewrite_set, | |
97 NGX_HTTP_LOC_CONF_OFFSET, | |
98 0, | |
99 NULL }, | |
100 | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
101 { ngx_string("rewrite_log"), |
485 | 102 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
103 |NGX_CONF_TAKE1, | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
104 ngx_conf_set_flag_slot, |
485 | 105 NGX_HTTP_LOC_CONF_OFFSET, |
106 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
|
107 NULL }, |
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
108 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
109 ngx_null_command |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
110 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
111 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
112 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
113 ngx_http_module_t ngx_http_rewrite_module_ctx = { |
509 | 114 NULL, /* preconfiguration */ |
115 NULL, /* postconfiguration */ | |
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 NULL, /* create main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
118 NULL, /* init main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
119 |
485 | 120 NULL, /* create server configuration */ |
121 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
|
122 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
123 ngx_http_rewrite_create_loc_conf, /* create location configration */ |
485 | 124 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
|
125 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
126 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
127 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
128 ngx_module_t ngx_http_rewrite_module = { |
509 | 129 NGX_MODULE_V1, |
485 | 130 &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
|
131 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
|
132 NGX_HTTP_MODULE, /* module type */ |
541 | 133 NULL, /* init master */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
134 ngx_http_rewrite_init, /* init module */ |
541 | 135 NULL, /* init process */ |
136 NULL, /* init thread */ | |
137 NULL, /* exit thread */ | |
138 NULL, /* exit process */ | |
139 NULL, /* exit master */ | |
140 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
|
141 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
142 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
143 |
501 | 144 static ngx_http_variable_value_t ngx_http_rewrite_null_value = |
509 | 145 { 0, ngx_string("") }; |
501 | 146 |
485 | 147 |
487 | 148 static ngx_int_t |
149 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
|
150 { |
509 | 151 ngx_http_script_code_pt code; |
152 ngx_http_script_engine_t *e; | |
485 | 153 ngx_http_rewrite_loc_conf_t *cf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
154 |
485 | 155 cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
156 |
485 | 157 if (cf->codes == NULL) { |
158 return NGX_DECLINED; | |
159 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
160 |
509 | 161 e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)); |
501 | 162 if (e == NULL) { |
485 | 163 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
164 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
165 |
509 | 166 e->sp = ngx_pcalloc(r->pool, |
167 cf->stack_size * sizeof(ngx_http_variable_value_t)); | |
485 | 168 if (e->sp == NULL) { |
169 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
170 } | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
171 |
515 | 172 if (cf->captures) { |
173 e->captures = ngx_palloc(r->pool, cf->captures * sizeof(int)); | |
485 | 174 if (e->captures == NULL) { |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
175 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
176 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
177 |
485 | 178 } else { |
179 e->captures = NULL; | |
180 } | |
181 | |
182 e->ip = cf->codes->elts; | |
509 | 183 e->request = r; |
485 | 184 e->quote = 1; |
509 | 185 e->log = cf->log; |
485 | 186 e->status = NGX_DECLINED; |
187 | |
188 while (*(uintptr_t *) e->ip) { | |
509 | 189 code = *(ngx_http_script_code_pt *) e->ip; |
485 | 190 code(e); |
191 } | |
192 | |
193 return e->status; | |
194 } | |
195 | |
196 | |
487 | 197 static void |
509 | 198 ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
199 { |
485 | 200 u_char *ref; |
201 size_t len; | |
202 ngx_uint_t i, n; | |
203 ngx_http_request_t *r; | |
204 ngx_http_rewrite_referer_t *refs; | |
205 ngx_http_rewrite_loc_conf_t *cf; | |
206 | |
207 r = e->request; | |
208 | |
209 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
210 "http rewrite invalid referer"); | |
211 | |
212 cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); | |
213 | |
214 e->ip += sizeof(uintptr_t); | |
215 | |
216 if (cf->referers == NULL) { | |
501 | 217 e->sp->value = 0; |
218 e->sp->text.len = 0; | |
219 e->sp->text.data = (u_char *) ""; | |
220 e->sp++; | |
221 | |
485 | 222 return; |
223 } | |
224 | |
225 if (r->headers_in.referer == NULL) { | |
226 if (cf->no_referer) { | |
501 | 227 e->sp->value = 0; |
228 e->sp->text.len = 0; | |
229 e->sp->text.data = (u_char *) ""; | |
230 e->sp++; | |
231 | |
485 | 232 return; |
505 | 233 |
485 | 234 } else { |
501 | 235 e->sp->value = 1; |
236 e->sp->text.len = 1; | |
237 e->sp->text.data = (u_char *) "1"; | |
238 e->sp++; | |
239 | |
485 | 240 return; |
241 } | |
242 } | |
243 | |
244 len = r->headers_in.referer->value.len; | |
245 ref = r->headers_in.referer->value.data; | |
246 | |
247 if (len < sizeof("http://i.ru") - 1 | |
248 || (ngx_strncasecmp(ref, "http://", 7) != 0)) | |
249 { | |
505 | 250 if (cf->blocked_referer) { |
251 e->sp->value = 0; | |
252 e->sp->text.len = 0; | |
253 e->sp->text.data = (u_char *) "0"; | |
254 e->sp++; | |
255 | |
256 return; | |
501 | 257 |
505 | 258 } else { |
259 e->sp->value = 1; | |
260 e->sp->text.len = 1; | |
261 e->sp->text.data = (u_char *) "1"; | |
262 e->sp++; | |
263 | |
264 return; | |
265 } | |
485 | 266 } |
267 | |
268 len -= 7; | |
269 ref += 7; | |
270 | |
271 refs = cf->referers->elts; | |
272 for (i = 0; i < cf->referers->nelts; i++ ){ | |
273 | |
274 if (refs[i].name.len > len) { | |
275 continue; | |
276 } | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
277 |
485 | 278 if (refs[i].wildcard) { |
279 for (n = 0; n < len; n++) { | |
280 if (ref[n] == '/' || ref[n] == ':') { | |
281 break; | |
282 } | |
283 | |
284 if (ref[n] != '.') { | |
285 continue; | |
286 } | |
287 | |
288 if (ngx_strncmp(&ref[n], refs[i].name.data, | |
289 refs[i].name.len) == 0) | |
290 { | |
501 | 291 e->sp->value = 0; |
292 e->sp->text.len = 0; | |
293 e->sp->text.data = (u_char *) ""; | |
294 e->sp++; | |
295 | |
485 | 296 return; |
297 } | |
298 } | |
299 | |
300 } else { | |
301 if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0) | |
302 { | |
501 | 303 e->sp->value = 0; |
304 e->sp->text.len = 0; | |
305 e->sp->text.data = (u_char *) ""; | |
306 e->sp++; | |
307 | |
485 | 308 return; |
309 } | |
310 } | |
311 } | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
312 |
501 | 313 e->sp->value = 1; |
314 e->sp->text.len = 1; | |
315 e->sp->text.data = (u_char *) "1"; | |
316 e->sp++; | |
485 | 317 } |
318 | |
319 | |
501 | 320 static ngx_http_variable_value_t * |
321 ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data) | |
322 { | |
323 ngx_http_variable_t *var; | |
324 ngx_http_core_main_conf_t *cmcf; | |
325 | |
326 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
327 | |
328 var = cmcf->variables.elts; | |
329 | |
330 /* | |
331 * the ngx_http_rewrite_module sets variables directly in r->variables, | |
519 | 332 * and they should be handled by ngx_http_get_indexed_variable(), |
501 | 333 * so the handler is called only if the variable is not initialized |
334 */ | |
335 | |
336 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
337 "using uninitialized \"%V\" variable", &var[data].name); | |
338 | |
339 return &ngx_http_rewrite_null_value; | |
340 } | |
341 | |
342 | |
487 | 343 static void * |
344 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
|
345 { |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
346 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
|
347 |
501 | 348 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)); |
349 if (conf == NULL) { | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
350 return NGX_CONF_ERROR; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
351 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
352 |
485 | 353 conf->stack_size = NGX_CONF_UNSET_UINT; |
354 conf->log = NGX_CONF_UNSET; | |
355 conf->no_referer = NGX_CONF_UNSET; | |
505 | 356 conf->blocked_referer = NGX_CONF_UNSET; |
485 | 357 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
358 return conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
359 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
360 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
361 |
487 | 362 static char * |
363 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
|
364 { |
485 | 365 ngx_http_rewrite_loc_conf_t *prev = parent; |
366 ngx_http_rewrite_loc_conf_t *conf = child; | |
367 | |
509 | 368 uintptr_t *code; |
485 | 369 |
370 ngx_conf_merge_value(conf->log, prev->log, 0); | |
371 ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10); | |
372 | |
373 if (conf->referers == NULL) { | |
374 conf->referers = prev->referers; | |
375 ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); | |
505 | 376 ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); |
485 | 377 } |
378 | |
499 | 379 if (conf->no_referer == NGX_CONF_UNSET) { |
380 conf->no_referer = 0; | |
381 } | |
382 | |
505 | 383 if (conf->blocked_referer == NGX_CONF_UNSET) { |
384 conf->blocked_referer = 0; | |
385 } | |
386 | |
485 | 387 if (conf->codes == NULL) { |
388 return NGX_CONF_OK; | |
389 } | |
390 | |
391 if (conf->codes == prev->codes) { | |
392 return NGX_CONF_OK; | |
393 } | |
394 | |
501 | 395 code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)); |
396 if (code == NULL) { | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
397 return NGX_CONF_ERROR; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
398 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
399 |
485 | 400 *code = (uintptr_t) NULL; |
401 | |
402 return NGX_CONF_OK; | |
403 } | |
404 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
405 |
509 | 406 static ngx_int_t |
407 ngx_http_rewrite_init(ngx_cycle_t *cycle) | |
408 { | |
409 ngx_http_handler_pt *h; | |
410 ngx_http_core_main_conf_t *cmcf; | |
411 | |
412 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); | |
413 | |
414 h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); | |
415 if (h == NULL) { | |
416 return NGX_ERROR; | |
417 } | |
418 | |
419 *h = ngx_http_rewrite_handler; | |
420 | |
421 return NGX_OK; | |
422 } | |
423 | |
424 | |
487 | 425 static char * |
426 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 427 { |
428 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
429 | |
509 | 430 ngx_str_t *value, err; |
431 ngx_int_t n; | |
432 ngx_uint_t last; | |
433 ngx_http_script_code_pt *code; | |
434 ngx_http_script_compile_t sc; | |
435 ngx_http_script_regex_code_t *regex; | |
436 ngx_http_script_regex_end_code_t *regex_end; | |
437 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
485 | 438 |
509 | 439 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
440 sizeof(ngx_http_script_regex_code_t)); | |
485 | 441 if (regex == NULL) { |
442 return NGX_CONF_ERROR; | |
443 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
444 |
509 | 445 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
446 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
447 value = cf->args->elts; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
448 |
485 | 449 err.len = NGX_MAX_CONF_ERRSTR; |
450 err.data = errstr; | |
451 | |
452 /* TODO: NGX_REGEX_CASELESS */ | |
453 | |
454 regex->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err); | |
455 | |
456 if (regex->regex == NULL) { | |
457 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | |
458 return NGX_CONF_ERROR; | |
459 } | |
460 | |
509 | 461 regex->code = ngx_http_script_regex_start_code; |
485 | 462 regex->uri = 1; |
463 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
|
464 |
509 | 465 if (value[2].data[value[2].len - 1] == '?') { |
466 | |
467 /* the last "?" drops the original arguments */ | |
468 value[2].len--; | |
469 | |
470 } else { | |
471 regex->add_args = 1; | |
472 } | |
473 | |
485 | 474 last = 0; |
475 | |
476 if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0) { | |
477 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | |
478 regex->redirect = 1; | |
479 last = 1; | |
480 } | |
481 | |
482 if (cf->args->nelts == 4) { | |
483 if (ngx_strcmp(value[3].data, "last") == 0) { | |
484 last = 1; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
485 |
487 | 486 } else if (ngx_strcmp(value[3].data, "break") == 0) { |
487 regex->break_cycle = 1; | |
488 last = 1; | |
489 | |
485 | 490 } else if (ngx_strcmp(value[3].data, "redirect") == 0) { |
491 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | |
492 regex->redirect = 1; | |
493 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
494 |
485 | 495 } else if (ngx_strcmp(value[3].data, "permanent") == 0) { |
496 regex->status = NGX_HTTP_MOVED_PERMANENTLY; | |
497 regex->redirect = 1; | |
498 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
499 |
485 | 500 } else { |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
501 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
461 | 502 "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
|
503 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
|
504 } |
485 | 505 } |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
506 |
509 | 507 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
485 | 508 |
509 | 509 sc.cf = cf; |
510 sc.source = &value[2]; | |
511 sc.lengths = ®ex->lengths; | |
512 sc.values = &lcf->codes; | |
513 sc.variables = ngx_http_script_variables_count(&value[2]); | |
514 sc.main = regex; | |
515 sc.complete_lengths = 1; | |
516 sc.compile_args = !regex->redirect; | |
485 | 517 |
509 | 518 if (ngx_http_script_compile(&sc) != NGX_OK) { |
519 return NGX_CONF_ERROR; | |
520 } | |
485 | 521 |
509 | 522 regex = sc.main; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
523 |
509 | 524 regex->ncaptures = sc.ncaptures; |
525 regex->size = sc.size; | |
526 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
|
527 |
509 | 528 if (sc.variables == 0) { |
529 regex->lengths = NULL; | |
485 | 530 } |
531 | |
532 n = ngx_regex_capture_count(regex->regex); | |
533 | |
501 | 534 if (n < 0) { |
535 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
536 ngx_regex_capture_count_n " failed for " | |
537 "pattern \"%V\"", &value[1]); | |
538 return NGX_CONF_ERROR; | |
539 } | |
540 | |
541 if (regex->ncaptures > (ngx_uint_t) n) { | |
485 | 542 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
543 "pattern \"%V\" has less captures " | |
544 "than referrenced in substitution \"%V\"", | |
545 &value[1], &value[2]); | |
546 return NGX_CONF_ERROR; | |
547 } | |
548 | |
501 | 549 if (regex->ncaptures < (ngx_uint_t) n) { |
550 regex->ncaptures = (ngx_uint_t) n; | |
485 | 551 } |
481 | 552 |
485 | 553 if (regex->ncaptures) { |
554 regex->ncaptures = (regex->ncaptures + 1) * 3; | |
555 | |
515 | 556 if (lcf->captures < regex->ncaptures) { |
557 lcf->captures = regex->ncaptures; | |
558 } | |
509 | 559 } |
560 | |
561 regex_end = ngx_http_script_add_code(lcf->codes, | |
562 sizeof(ngx_http_script_regex_end_code_t), | |
563 ®ex); | |
485 | 564 if (regex_end == NULL) { |
565 return NGX_CONF_ERROR; | |
566 } | |
567 | |
509 | 568 regex_end->code = ngx_http_script_regex_end_code; |
485 | 569 regex_end->uri = regex->uri; |
570 regex_end->args = regex->args; | |
509 | 571 regex_end->add_args = regex->add_args; |
485 | 572 regex_end->redirect = regex->redirect; |
573 | |
574 if (last) { | |
517 | 575 code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ®ex); |
485 | 576 if (code == NULL) { |
577 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
|
578 } |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
579 |
485 | 580 *code = (uintptr_t) NULL; |
581 } | |
582 | |
583 regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
584 - (u_char *) regex; | |
585 | |
586 return NGX_CONF_OK; | |
587 } | |
588 | |
589 | |
487 | 590 static char * |
591 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 592 { |
593 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
|
594 |
509 | 595 ngx_str_t *value; |
596 ngx_http_script_return_code_t *ret; | |
485 | 597 |
509 | 598 ret = ngx_http_script_start_code(cf->pool, &lcf->codes, |
599 sizeof(ngx_http_script_return_code_t)); | |
485 | 600 if (ret == NULL) { |
601 return NGX_CONF_ERROR; | |
602 } | |
603 | |
604 value = cf->args->elts; | |
605 | |
509 | 606 ret->code = ngx_http_script_return_code; |
485 | 607 ret->null = (uintptr_t) NULL; |
608 | |
609 ret->status = ngx_atoi(value[1].data, value[1].len); | |
610 | |
611 if (ret->status == (uintptr_t) NGX_ERROR) { | |
612 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
|
613 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
614 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
615 return NGX_CONF_OK; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
616 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
617 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
618 |
487 | 619 static char * |
527 | 620 ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
621 { | |
622 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
623 | |
624 ngx_http_script_code_pt *code; | |
625 | |
626 code = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(uintptr_t)); | |
627 if (code == NULL) { | |
628 return NGX_CONF_ERROR; | |
629 } | |
630 | |
631 *code = ngx_http_script_break_code; | |
632 | |
633 return NGX_CONF_OK; | |
634 } | |
635 | |
636 | |
637 static char * | |
487 | 638 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
|
639 { |
485 | 640 ngx_http_rewrite_loc_conf_t *lcf = conf; |
641 | |
642 void *mconf; | |
643 char *rv; | |
644 u_char *elts; | |
645 ngx_uint_t i; | |
646 ngx_conf_t save; | |
647 ngx_http_module_t *module; | |
648 ngx_http_conf_ctx_t *ctx, *pctx; | |
649 ngx_http_core_loc_conf_t *clcf, *pclcf, **clcfp; | |
509 | 650 ngx_http_script_if_code_t *if_code; |
485 | 651 ngx_http_rewrite_loc_conf_t *nlcf; |
652 | |
501 | 653 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
654 if (ctx == NULL) { | |
485 | 655 return NGX_CONF_ERROR; |
656 } | |
657 | |
658 pctx = cf->ctx; | |
659 ctx->main_conf = pctx->main_conf; | |
660 ctx->srv_conf = pctx->srv_conf; | |
661 | |
662 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | |
663 if (ctx->loc_conf == NULL) { | |
664 return NGX_CONF_ERROR; | |
665 } | |
666 | |
667 for (i = 0; ngx_modules[i]; i++) { | |
668 if (ngx_modules[i]->type != NGX_HTTP_MODULE) { | |
669 continue; | |
670 } | |
671 | |
672 module = ngx_modules[i]->ctx; | |
673 | |
674 if (module->create_loc_conf) { | |
675 | |
501 | 676 mconf = module->create_loc_conf(cf); |
677 if (mconf == NULL) { | |
485 | 678 return NGX_CONF_ERROR; |
679 } | |
680 | |
681 ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; | |
682 } | |
683 } | |
684 | |
685 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; | |
686 | |
687 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
688 clcf->loc_conf = ctx->loc_conf; | |
689 clcf->name = pclcf->name; | |
690 clcf->noname = 1; | |
691 | |
692 if (pclcf->locations.elts == NULL) { | |
693 if (ngx_array_init(&pclcf->locations, cf->pool, 4, sizeof(void *)) | |
555 | 694 == NGX_ERROR) |
485 | 695 { |
696 return NGX_CONF_ERROR; | |
697 } | |
698 } | |
699 | |
501 | 700 clcfp = ngx_array_push(&pclcf->locations); |
701 if (clcfp == NULL) { | |
485 | 702 return NGX_CONF_ERROR; |
703 } | |
704 | |
705 *clcfp = clcf; | |
706 | |
707 | |
501 | 708 if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { |
485 | 709 return NGX_CONF_ERROR; |
710 } | |
711 | |
509 | 712 if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t)); |
485 | 713 if (if_code == NULL) { |
714 return NULL; | |
715 } | |
716 | |
509 | 717 if_code->code = ngx_http_script_if_code; |
485 | 718 |
719 elts = lcf->codes->elts; | |
720 | |
721 | |
722 /* the inside directives must compile to the same code array */ | |
723 | |
724 nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index]; | |
725 nlcf->codes = lcf->codes; | |
726 | |
727 | |
728 save = *cf; | |
729 cf->ctx = ctx; | |
730 | |
731 if (pclcf->name.len == 0) { | |
732 if_code->loc_conf = NULL; | |
733 cf->cmd_type = NGX_HTTP_SIF_CONF; | |
734 | |
735 } else { | |
736 if_code->loc_conf = ctx->loc_conf; | |
737 cf->cmd_type = NGX_HTTP_LIF_CONF; | |
738 } | |
739 | |
740 rv = ngx_conf_parse(cf, NULL); | |
741 | |
742 *cf = save; | |
743 | |
744 if (rv != NGX_CONF_OK) { | |
745 return rv; | |
746 } | |
747 | |
748 | |
517 | 749 if (lcf->captures < nlcf->captures) { |
750 lcf->captures = nlcf->captures; | |
751 } | |
752 | |
753 | |
485 | 754 if (elts != lcf->codes->elts) { |
509 | 755 if_code = (ngx_http_script_if_code_t *) |
485 | 756 ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); |
757 } | |
758 | |
759 if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
760 - (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
|
761 |
555 | 762 /* the code array belong to parent block */ |
763 | |
764 nlcf->codes = NULL; | |
765 | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
766 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
|
767 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
768 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
769 |
487 | 770 static char * |
501 | 771 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) |
772 { | |
509 | 773 ngx_str_t *value, err; |
515 | 774 ngx_uint_t cur, last, n; |
509 | 775 ngx_http_script_regex_code_t *regex; |
776 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
501 | 777 |
778 value = cf->args->elts; | |
779 last = cf->args->nelts - 1; | |
780 | |
781 if (value[1].len < 1 || value[1].data[0] != '(') { | |
782 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
783 "invalid condition \"%V\"", &value[1]); | |
784 return NGX_CONF_ERROR; | |
785 } | |
786 | |
787 if (value[1].len == 1) { | |
788 cur = 2; | |
789 | |
790 } else { | |
791 cur = 1; | |
792 value[1].len--; | |
793 value[1].data++; | |
794 } | |
795 | |
796 if (value[last].len < 1 || value[last].data[value[last].len - 1] != ')') { | |
797 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
798 "invalid condition \"%V\"", &value[last]); | |
799 return NGX_CONF_ERROR; | |
800 } | |
801 | |
802 if (value[last].len == 1) { | |
803 last--; | |
804 | |
805 } else { | |
806 value[last].len--; | |
807 value[last].data[value[last].len] = '\0'; | |
808 } | |
809 | |
810 if (value[cur].len > 1 && value[cur].data[0] == '$') { | |
811 | |
812 if (cur != last && cur + 2 != last) { | |
813 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
814 "invalid condition \"%V\"", &value[cur]); | |
815 return NGX_CONF_ERROR; | |
816 } | |
817 | |
818 if (ngx_http_rewrite_variable(cf, lcf, &value[cur])!= NGX_CONF_OK) { | |
819 return NGX_CONF_ERROR; | |
820 } | |
821 | |
822 if (cur == last) { | |
823 return NGX_CONF_OK; | |
824 } | |
825 | |
826 cur++; | |
827 | |
828 if ((value[cur].len == 1 && value[cur].data[0] != '~') | |
829 || (value[cur].len == 2 | |
830 && value[cur].data[0] != '~' && value[cur].data[1] != '*')) | |
831 { | |
832 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
833 "unexpected \"%V\" in condition", &value[cur]); | |
834 return NGX_CONF_ERROR; | |
835 } | |
836 | |
509 | 837 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
838 sizeof(ngx_http_script_regex_code_t)); | |
501 | 839 if (regex == NULL) { |
840 return NGX_CONF_ERROR; | |
841 } | |
842 | |
509 | 843 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
844 | |
501 | 845 err.len = NGX_MAX_CONF_ERRSTR; |
846 err.data = errstr; | |
847 | |
848 regex->regex = ngx_regex_compile(&value[last], | |
849 (value[cur].len == 2) ? NGX_REGEX_CASELESS : 0, | |
850 cf->pool, &err); | |
851 | |
852 if (regex->regex == NULL) { | |
853 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | |
854 return NGX_CONF_ERROR; | |
855 } | |
856 | |
509 | 857 regex->code = ngx_http_script_regex_start_code; |
858 regex->next = sizeof(ngx_http_script_regex_code_t); | |
501 | 859 regex->test = 1; |
860 regex->name = value[last]; | |
861 | |
515 | 862 n = ngx_regex_capture_count(regex->regex); |
863 | |
864 if (n) { | |
865 regex->ncaptures = (n + 1) * 3; | |
866 | |
867 if (lcf->captures < regex->ncaptures) { | |
868 lcf->captures = regex->ncaptures; | |
869 } | |
870 } | |
871 | |
501 | 872 return NGX_CONF_OK; |
873 } | |
874 | |
875 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
876 "invalid condition \"%V\"", &value[cur]); | |
877 | |
878 return NGX_CONF_ERROR; | |
879 } | |
880 | |
881 | |
882 static char * | |
883 ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | |
884 ngx_str_t *value) | |
885 { | |
509 | 886 ngx_int_t index; |
887 ngx_http_script_code_pt *code; | |
888 ngx_http_script_var_code_t *var_code; | |
501 | 889 |
890 value->len--; | |
891 value->data++; | |
892 | |
893 if (value->len == sizeof("invalid_referer") - 1 | |
894 && ngx_strncmp(value->data, "invalid_referer", | |
895 sizeof("invalid_referer") - 1) == 0) | |
896 { | |
509 | 897 code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
898 sizeof(ngx_http_script_code_pt)); | |
501 | 899 if (code == NULL) { |
900 return NGX_CONF_ERROR; | |
901 } | |
902 | |
903 *code = ngx_http_rewrite_invalid_referer_code; | |
904 | |
905 } else { | |
509 | 906 index = ngx_http_get_variable_index(cf, value); |
501 | 907 |
509 | 908 if (index == NGX_ERROR) { |
501 | 909 return NGX_CONF_ERROR; |
910 } | |
911 | |
509 | 912 var_code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
913 sizeof(ngx_http_script_var_code_t)); | |
501 | 914 if (var_code == NULL) { |
915 return NGX_CONF_ERROR; | |
916 } | |
917 | |
509 | 918 var_code->code = ngx_http_script_var_code; |
919 var_code->index = index; | |
501 | 920 } |
921 | |
922 return NGX_CONF_OK; | |
923 } | |
924 | |
925 | |
926 static char * | |
487 | 927 ngx_http_rewrite_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
928 { |
485 | 929 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
|
930 |
485 | 931 ngx_uint_t i, server_names; |
932 ngx_str_t *value; | |
933 ngx_http_server_name_t *sn; | |
934 ngx_http_core_srv_conf_t *cscf; | |
935 ngx_http_rewrite_referer_t *ref; | |
936 | |
937 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
938 |
485 | 939 if (lcf->referers == NULL) { |
940 lcf->referers = ngx_array_create(cf->pool, | |
941 cf->args->nelts + cscf->server_names.nelts, | |
942 sizeof(ngx_http_rewrite_referer_t)); | |
943 if (lcf->referers == NULL) { | |
944 return NGX_CONF_ERROR; | |
945 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
946 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
947 |
485 | 948 value = cf->args->elts; |
949 server_names = 0; | |
950 | |
951 for (i = 1; i < cf->args->nelts; i++) { | |
952 if (value[i].len == 0) { | |
953 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
954 "invalid referer \"%V\"", &value[i]); | |
955 return NGX_CONF_ERROR; | |
956 } | |
957 | |
958 if (ngx_strcmp(value[i].data, "none") == 0) { | |
959 lcf->no_referer = 1; | |
960 continue; | |
961 } | |
962 | |
505 | 963 if (ngx_strcmp(value[i].data, "blocked") == 0) { |
964 lcf->blocked_referer = 1; | |
965 continue; | |
966 } | |
967 | |
485 | 968 if (ngx_strcmp(value[i].data, "server_names") == 0) { |
969 server_names = 1; | |
970 continue; | |
971 } | |
972 | |
501 | 973 ref = ngx_array_push(lcf->referers); |
974 if (ref == NULL) { | |
485 | 975 return NGX_CONF_ERROR; |
976 } | |
977 | |
978 if (value[i].data[0] != '*') { | |
979 ref->name = value[i]; | |
980 ref->wildcard = 0; | |
981 continue; | |
982 } | |
983 | |
984 if (value[i].data[1] != '.') { | |
985 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
986 "invalid wildcard referer \"%V\"", &value[i]); | |
987 return NGX_CONF_ERROR; | |
988 } | |
989 | |
990 ref->name.len = value[i].len - 1; | |
991 ref->name.data = value[i].data + 1; | |
992 ref->wildcard = 1; | |
993 } | |
994 | |
995 if (!server_names) { | |
996 return NGX_CONF_OK; | |
997 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
998 |
485 | 999 sn = cscf->server_names.elts; |
1000 for (i = 0; i < cscf->server_names.nelts; i++) { | |
501 | 1001 ref = ngx_array_push(lcf->referers); |
1002 if (ref == NULL) { | |
485 | 1003 return NGX_CONF_ERROR; |
1004 } | |
1005 | |
1006 ref->name.len = sn[i].name.len + 1; | |
501 | 1007 ref->name.data = ngx_palloc(cf->pool, ref->name.len); |
1008 if (ref->name.data == NULL) { | |
485 | 1009 return NGX_CONF_ERROR; |
1010 } | |
1011 | |
1012 ngx_memcpy(ref->name.data, sn[i].name.data, sn[i].name.len); | |
1013 ref->name.data[sn[i].name.len] = '/'; | |
1014 ref->wildcard = sn[i].wildcard; | |
1015 } | |
1016 | |
1017 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
|
1018 } |
485 | 1019 |
1020 | |
501 | 1021 static char * |
1022 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1023 { | |
1024 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
1025 | |
515 | 1026 ngx_int_t n, index; |
1027 ngx_str_t *value; | |
1028 ngx_http_variable_t *v; | |
1029 ngx_http_script_compile_t sc; | |
1030 ngx_http_script_var_code_t *var; | |
1031 ngx_http_script_value_code_t *val; | |
1032 ngx_http_script_complex_value_code_t *complex; | |
501 | 1033 |
1034 value = cf->args->elts; | |
1035 | |
1036 if (value[1].data[0] != '$') { | |
1037 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1038 "invalid variable name \"%V\"", &value[1]); | |
1039 return NGX_CONF_ERROR; | |
1040 } | |
1041 | |
1042 value[1].len--; | |
1043 value[1].data++; | |
1044 | |
509 | 1045 v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE); |
501 | 1046 if (v == NULL) { |
1047 return NGX_CONF_ERROR; | |
1048 } | |
1049 | |
509 | 1050 index = ngx_http_get_variable_index(cf, &value[1]); |
1051 if (index == NGX_ERROR) { | |
1052 return NGX_CONF_ERROR; | |
1053 } | |
501 | 1054 |
555 | 1055 if (v->handler == NULL) { |
1056 v->handler = ngx_http_rewrite_var; | |
1057 v->data = index; | |
1058 } | |
509 | 1059 |
515 | 1060 n = ngx_http_script_variables_count(&value[2]); |
1061 | |
1062 if (n == 0) { | |
1063 val = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
1064 sizeof(ngx_http_script_value_code_t)); | |
1065 if (val == NULL) { | |
1066 return NGX_CONF_ERROR; | |
1067 } | |
501 | 1068 |
515 | 1069 n = ngx_atoi(value[2].data, value[2].len); |
1070 | |
1071 if (n == NGX_ERROR) { | |
1072 n = 0; | |
1073 } | |
1074 | |
1075 val->code = ngx_http_script_value_code; | |
1076 val->value = (uintptr_t) n; | |
1077 val->text_len = (uintptr_t) value[2].len; | |
1078 val->text_data = (uintptr_t) value[2].data; | |
501 | 1079 |
515 | 1080 } else { |
1081 complex = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
1082 sizeof(ngx_http_script_complex_value_code_t)); | |
1083 if (complex == NULL) { | |
1084 return NGX_CONF_ERROR; | |
1085 } | |
1086 | |
1087 complex->code = ngx_http_script_complex_value_code; | |
1088 complex->lengths = NULL; | |
1089 | |
1090 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
501 | 1091 |
515 | 1092 sc.cf = cf; |
1093 sc.source = &value[2]; | |
1094 sc.lengths = &complex->lengths; | |
1095 sc.values = &lcf->codes; | |
1096 sc.variables = n; | |
1097 sc.complete_lengths = 1; | |
1098 | |
1099 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1100 return NGX_CONF_ERROR; | |
1101 } | |
1102 } | |
501 | 1103 |
509 | 1104 var = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1105 sizeof(ngx_http_script_var_code_t)); | |
501 | 1106 if (var == NULL) { |
1107 return NGX_CONF_ERROR; | |
1108 } | |
1109 | |
509 | 1110 var->code = ngx_http_script_set_var_code; |
1111 var->index = (uintptr_t) index; | |
501 | 1112 |
1113 return NGX_CONF_OK; | |
1114 } |