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