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