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