comparison src/http/modules/ngx_http_rewrite_handler.c @ 216:f1d0e5f09c1e

nginx-0.0.1-2003-12-25-23:26:58 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 25 Dec 2003 20:26:58 +0000
parents
children 05592fd7a436
comparison
equal deleted inserted replaced
215:5adc2b75f8a5 216:f1d0e5f09c1e
1
2 #include <ngx_config.h>
3 #include <ngx_core.h>
4 #include <ngx_http.h>
5
6
7 #define NGX_HTTP_REWRITE_COPY_MATCH 0
8 #define NGX_HTTP_REWRITE_COPY_SHORT 1
9 #define NGX_HTTP_REWRITE_COPY_LONG 2
10
11
12 typedef struct {
13 ngx_int_t op;
14 size_t len;
15 uintptr_t data;
16 } ngx_http_rewrite_op_t;
17
18
19 typedef struct {
20 ngx_regex_t *regex;
21 ngx_uint_t msize;
22
23 ngx_array_t ops;
24 ngx_uint_t size;
25
26 ngx_str_t re_name;
27 ngx_str_t s_name;
28
29 unsigned last:1;
30 } ngx_http_rewrite_rule_t;
31
32
33 typedef struct {
34 ngx_array_t rules;
35 unsigned log:1;
36 } ngx_http_rewrite_srv_conf_t;
37
38
39 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf);
40 static char *ngx_http_rewrite_rule(ngx_conf_t *cf, ngx_command_t *cmd,
41 void *conf);
42 static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle);
43
44
45 static ngx_command_t ngx_http_rewrite_commands[] = {
46
47 { ngx_string("rewrite"),
48 NGX_HTTP_SRV_CONF|NGX_CONF_TAKE23,
49 ngx_http_rewrite_rule,
50 NGX_HTTP_SRV_CONF_OFFSET,
51 0,
52 NULL },
53
54 ngx_null_command
55 };
56
57
58 ngx_http_module_t ngx_http_rewrite_module_ctx = {
59 NULL, /* pre conf */
60
61 NULL, /* create main configuration */
62 NULL, /* init main configuration */
63
64 ngx_http_rewrite_create_loc_conf, /* create server configuration */
65 NULL, /* merge server configuration */
66
67 NULL, /* create location configration */
68 NULL, /* merge location configration */
69 };
70
71
72 ngx_module_t ngx_http_rewrite_module = {
73 NGX_MODULE,
74 &ngx_http_rewrite_module_ctx, /* module context */
75 ngx_http_rewrite_commands, /* module directives */
76 NGX_HTTP_MODULE, /* module type */
77 ngx_http_rewrite_init, /* init module */
78 NULL /* init child */
79 };
80
81
82 static ngx_int_t ngx_http_rewrite_handler(ngx_http_request_t *r)
83 {
84 int *matches;
85 char *p;
86 size_t len;
87 uintptr_t data;
88 ngx_int_t rc, i, n, m;
89 ngx_str_t uri;
90 ngx_http_rewrite_op_t *op;
91 ngx_http_rewrite_rule_t *rule;
92 ngx_http_rewrite_srv_conf_t *scf;
93
94 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
95 "http rewrite handler");
96
97 scf = ngx_http_get_module_srv_conf(r, ngx_http_rewrite_module);
98
99 rule = scf->rules.elts;
100 for (i = 0; i < scf->rules.nelts; i++) {
101
102 if (rule[i].msize) {
103 if (!(matches = ngx_palloc(r->pool, rule[i].msize * sizeof(int)))) {
104 return NGX_HTTP_INTERNAL_SERVER_ERROR;
105 }
106
107 } else {
108 matches = NULL;
109 }
110
111 rc = ngx_regex_exec(rule[i].regex, &r->uri, matches, rule[i].msize);
112
113 if (rc == NGX_DECLINED) {
114 if (scf->log) {
115 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
116 "\"%s\" is not matched", rule[i].re_name.data);
117 }
118
119 continue;
120 }
121
122 if (rc < 0) {
123 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
124 ngx_regex_exec_n
125 " failed: %d on \"%s\" using \"%s\"",
126 rc, r->uri.data, rule[i].re_name.data);
127 return NGX_HTTP_INTERNAL_SERVER_ERROR;
128 }
129
130 if (scf->log) {
131 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
132 "\"%s\" matched", rule[i].re_name.data);
133 }
134
135 uri.len = rule[i].size;
136
137 for (n = 1; n < rc; n++) {
138 uri.len += matches[2 * n + 1] - matches[2 * n];
139 }
140
141 if (!(uri.data = ngx_palloc(r->pool, uri.len + 1))) {
142 return NGX_HTTP_INTERNAL_SERVER_ERROR;
143 }
144
145 p = uri.data;
146
147 op = rule[i].ops.elts;
148 for (n = 0; n < rule[i].ops.nelts; n++) {
149 if (op[n].op == NGX_HTTP_REWRITE_COPY_SHORT) {
150 len = op[n].len;
151 data = op[n].data;
152 while (len--) {
153 *p++ = data & 0xff;
154 data >>= 8;
155 }
156
157 } else if (op[n].op == NGX_HTTP_REWRITE_COPY_LONG) {
158 p = ngx_cpymem(p, (void *) op[n].data, op[n].len);
159
160 } else { /* NGX_HTTP_REWRITE_COPY_MATCH */
161 m = 2 * op[n].data;
162 p = ngx_cpymem(p, &r->uri.data[matches[m]],
163 matches[m + 1] - matches[m]);
164 }
165 }
166
167 *p = '\0';
168
169 if (scf->log) {
170 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
171 "rewritten uri: \"%s\"", uri.data);
172 }
173
174 r->uri = uri;
175
176 if (ngx_http_set_exten(r) != NGX_OK) {
177 return NGX_HTTP_INTERNAL_SERVER_ERROR;
178 }
179
180 if (rule[i].last) {
181 return NGX_DECLINED;
182 }
183 }
184
185 return NGX_DECLINED;
186 }
187
188
189 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf)
190 {
191 ngx_http_rewrite_srv_conf_t *conf;
192
193 if (!(conf = ngx_palloc(cf->pool, sizeof(ngx_http_rewrite_srv_conf_t)))) {
194 return NGX_CONF_ERROR;
195 }
196
197 ngx_init_array(conf->rules, cf->pool, 5, sizeof(ngx_http_rewrite_rule_t),
198 NGX_CONF_ERROR);
199
200 conf->log = 1;
201
202 return conf;
203 }
204
205
206 static char *ngx_http_rewrite_rule(ngx_conf_t *cf, ngx_command_t *cmd,
207 void *conf)
208 {
209 ngx_http_rewrite_srv_conf_t *scf = conf;
210
211 char *data, *p;
212 size_t len;
213 ngx_str_t *value, err;
214 ngx_uint_t i;
215 ngx_http_rewrite_op_t *op;
216 ngx_http_rewrite_rule_t *rule;
217 char errstr[NGX_MAX_CONF_ERRSTR];
218
219 if (!(rule = ngx_push_array(&scf->rules))) {
220 return NGX_CONF_ERROR;
221 }
222
223 ngx_init_array(rule->ops, cf->pool, 5, sizeof(ngx_http_rewrite_op_t),
224 NGX_CONF_ERROR);
225
226 rule->msize = 0;
227 rule->size = 0;
228
229 value = cf->args->elts;
230
231 /* STUB */ {
232 err.len = NGX_MAX_CONF_ERRSTR;
233 err.data = errstr;
234
235 rule->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
236
237 if (rule->regex == NULL) {
238 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
239 return NGX_CONF_ERROR;
240 }
241
242 rule->re_name = value[1];
243 rule->s_name = value[2];
244
245 for (i = 0; i < value[2].len; /* void */) {
246
247 if (!(op = ngx_push_array(&rule->ops))) {
248 return NGX_CONF_ERROR;
249 }
250
251 data = &value[2].data[i];
252
253 if (value[2].data[i] == '$'
254 && i < value[2].len
255 && value[2].data[i + 1] >= '1'
256 && value[2].data[i + 1] <= '9')
257 {
258 op->op = NGX_HTTP_REWRITE_COPY_MATCH;
259 op->data = value[2].data[++i] - '0';
260
261 if (rule->msize < op->data) {
262 rule->msize = op->data;
263 }
264
265 i++;
266
267 } else {
268 i++;
269
270 while (i < value[2].len && value[2].data[i] != '$') {
271 i++;
272 }
273
274 len = &value[2].data[i] - data;
275 rule->size += len;
276
277 if (len) {
278
279 op->len = len;
280
281 if (len <= sizeof(uintptr_t)) {
282 op->op = NGX_HTTP_REWRITE_COPY_SHORT;
283 op->data = 0;
284
285 while (len--) {
286 op->data <<= 8;
287 op->data |= data[len];
288 }
289
290 } else {
291 op->op = NGX_HTTP_REWRITE_COPY_LONG;
292
293 if (!(p = ngx_palloc(cf->pool, len))) {
294 return NGX_CONF_ERROR;
295 }
296
297 ngx_memcpy(p, data, len);
298 op->data = (uintptr_t) p;
299 }
300 }
301 }
302 }
303
304 rule->msize++;
305 rule->msize *= 3;
306
307 if (cf->args->nelts > 3) {
308 if (ngx_strcmp(value[3].data, "last") == 0) {
309 rule->last = 1;
310
311 } else {
312 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
313 "invalid parameter \"%s\"", value[3].data);
314 return NGX_CONF_ERROR;
315 }
316 }
317 }
318
319 return NGX_CONF_OK;
320 }
321
322
323 static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle)
324 {
325 ngx_http_handler_pt *h;
326 ngx_http_conf_ctx_t *ctx;
327 ngx_http_core_main_conf_t *cmcf;
328
329 ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
330 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
331
332 h = ngx_push_array(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
333 if (h == NULL) {
334 return NGX_ERROR;
335 }
336
337 *h = ngx_http_rewrite_handler;
338
339 return NGX_OK;
340 }