Mercurial > hg > nginx
comparison src/http/modules/ngx_http_index_handler.c @ 199:a65b630b3a66
nginx-0.0.1-2003-11-28-11:40:40 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 28 Nov 2003 08:40:40 +0000 |
parents | c1f3a3c7c5db |
children | abeaebe0a33c |
comparison
equal
deleted
inserted
replaced
198:34995c5ec6c4 | 199:a65b630b3a66 |
---|---|
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 #include <ngx_http.h> | 4 #include <ngx_http.h> |
5 | 5 |
6 | 6 |
7 typedef struct { | 7 typedef struct { |
8 ngx_array_t indices; | 8 ngx_array_t indices; |
9 size_t max_index_len; | 9 size_t max_index_len; |
10 ngx_http_cache_hash_t *cache; | |
10 } ngx_http_index_conf_t; | 11 } ngx_http_index_conf_t; |
11 | 12 |
12 | 13 |
13 typedef struct { | 14 typedef struct { |
14 int index; | 15 int index; |
17 | 18 |
18 | 19 |
19 #define NGX_HTTP_DEFAULT_INDEX "index.html" | 20 #define NGX_HTTP_DEFAULT_INDEX "index.html" |
20 | 21 |
21 | 22 |
22 static int ngx_http_index_test_dir(ngx_http_request_t *r, | 23 static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, |
23 ngx_http_index_ctx_t *ctx); | 24 ngx_http_index_ctx_t *ctx); |
24 static int ngx_http_index_error(ngx_http_request_t *r, | 25 static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, |
25 ngx_http_index_ctx_t *ctx, ngx_err_t err); | 26 ngx_http_index_ctx_t *ctx, ngx_err_t err); |
26 | 27 |
27 static int ngx_http_index_init(ngx_cycle_t *cycle); | 28 static int ngx_http_index_init(ngx_cycle_t *cycle); |
28 static void *ngx_http_index_create_conf(ngx_conf_t *cf); | 29 static void *ngx_http_index_create_conf(ngx_conf_t *cf); |
29 static char *ngx_http_index_merge_conf(ngx_conf_t *cf, | 30 static char *ngx_http_index_merge_conf(ngx_conf_t *cf, |
30 void *parent, void *child); | 31 void *parent, void *child); |
31 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, | 32 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, |
32 void *conf); | 33 void *conf); |
33 | 34 |
34 | 35 |
35 static ngx_command_t ngx_http_index_commands[] = { | 36 static ngx_command_t ngx_http_index_commands[] = { |
36 | 37 |
37 {ngx_string("index"), | 38 { ngx_string("index"), |
38 NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | 39 NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
39 ngx_http_index_set_index, | 40 ngx_http_index_set_index, |
40 NGX_HTTP_LOC_CONF_OFFSET, | 41 NGX_HTTP_LOC_CONF_OFFSET, |
41 0, | 42 0, |
42 NULL}, | 43 NULL }, |
43 | 44 |
44 ngx_null_command | 45 { ngx_string("index_cache"), |
46 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, | |
47 ngx_http_set_cache_slot, | |
48 NGX_HTTP_LOC_CONF_OFFSET, | |
49 offsetof(ngx_http_index_conf_t, cache), | |
50 NULL }, | |
51 | |
52 ngx_null_command | |
45 }; | 53 }; |
46 | 54 |
47 | 55 |
48 ngx_http_module_t ngx_http_index_module_ctx = { | 56 ngx_http_module_t ngx_http_index_module_ctx = { |
49 NULL, /* pre conf */ | 57 NULL, /* pre conf */ |
79 * that path contains the usual file in place of the directory. | 87 * that path contains the usual file in place of the directory. |
80 */ | 88 */ |
81 | 89 |
82 int ngx_http_index_handler(ngx_http_request_t *r) | 90 int ngx_http_index_handler(ngx_http_request_t *r) |
83 { | 91 { |
84 int rc; | |
85 char *name, *file; | 92 char *name, *file; |
93 uint32_t crc; | |
94 ngx_int_t rc; | |
86 ngx_str_t redirect, *index; | 95 ngx_str_t redirect, *index; |
87 ngx_err_t err; | 96 ngx_err_t err; |
88 ngx_fd_t fd; | 97 ngx_fd_t fd; |
98 ngx_http_cache_t *cache; | |
89 ngx_http_index_ctx_t *ctx; | 99 ngx_http_index_ctx_t *ctx; |
90 ngx_http_index_conf_t *icf; | 100 ngx_http_index_conf_t *ilcf; |
91 ngx_http_core_loc_conf_t *clcf; | 101 ngx_http_core_loc_conf_t *clcf; |
92 | 102 |
93 if (r->uri.data[r->uri.len - 1] != '/') { | 103 if (r->uri.data[r->uri.len - 1] != '/') { |
94 return NGX_DECLINED; | 104 return NGX_DECLINED; |
105 } | |
106 | |
107 ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); | |
108 | |
109 if (ilcf->cache) { | |
110 cache = ngx_http_cache_get(ilcf->cache, &r->uri, &crc); | |
111 | |
112 ngx_log_debug(r->connection->log, "index cache get: %x" _ cache); | |
113 | |
114 if (cache && ilcf->cache->update >= ngx_cached_time - cache->updated) { | |
115 | |
116 cache->accessed = ngx_cached_time; | |
117 | |
118 redirect.len = cache->data.value.len; | |
119 if (!(redirect.data = ngx_palloc(r->pool, redirect.len + 1))) { | |
120 ngx_http_cache_unlock(ilcf->cache, cache); | |
121 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
122 } | |
123 | |
124 ngx_memcpy(redirect.data, cache->data.value.data, redirect.len + 1); | |
125 ngx_http_cache_unlock(ilcf->cache, cache); | |
126 | |
127 return ngx_http_internal_redirect(r, &redirect, NULL); | |
128 } | |
129 | |
130 } else { | |
131 cache = NULL; | |
95 } | 132 } |
96 | 133 |
97 ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); | 134 ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); |
98 if (ctx == NULL) { | 135 if (ctx == NULL) { |
99 ngx_http_create_ctx(r, ctx, ngx_http_index_module, | 136 ngx_http_create_ctx(r, ctx, ngx_http_index_module, |
100 sizeof(ngx_http_index_ctx_t), | 137 sizeof(ngx_http_index_ctx_t), |
101 NGX_HTTP_INTERNAL_SERVER_ERROR); | 138 NGX_HTTP_INTERNAL_SERVER_ERROR); |
102 } | 139 } |
103 | 140 |
104 icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); | |
105 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 141 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
106 | 142 |
107 if (r->path.data == NULL) { | 143 if (r->path.data == NULL) { |
108 r->path_allocated = clcf->doc_root.len + r->uri.len | 144 r->path_allocated = clcf->doc_root.len + r->uri.len |
109 + icf->max_index_len; | 145 + ilcf->max_index_len; |
110 ngx_test_null(r->path.data, | 146 ngx_test_null(r->path.data, |
111 ngx_palloc(r->pool, r->path_allocated), | 147 ngx_palloc(r->pool, r->path_allocated), |
112 NGX_HTTP_INTERNAL_SERVER_ERROR); | 148 NGX_HTTP_INTERNAL_SERVER_ERROR); |
113 | 149 |
114 redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data, | 150 redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data, |
119 } else{ | 155 } else{ |
120 redirect.data = r->path.data + r->path.len; | 156 redirect.data = r->path.data + r->path.len; |
121 file = redirect.data + r->uri.len; | 157 file = redirect.data + r->uri.len; |
122 } | 158 } |
123 | 159 |
124 index = icf->indices.elts; | 160 index = ilcf->indices.elts; |
125 for (/* void */; ctx->index < icf->indices.nelts; ctx->index++) { | 161 for (/* void */; ctx->index < ilcf->indices.nelts; ctx->index++) { |
126 | 162 |
127 if (index[ctx->index].data[0] == '/') { | 163 if (index[ctx->index].data[0] == '/') { |
128 name = index[ctx->index].data; | 164 name = index[ctx->index].data; |
129 | 165 |
130 } else { | 166 } else { |
183 redirect.len = r->uri.len + index[ctx->index].len; | 219 redirect.len = r->uri.len + index[ctx->index].len; |
184 r->file.name.len = clcf->doc_root.len + r->uri.len | 220 r->file.name.len = clcf->doc_root.len + r->uri.len |
185 + index[ctx->index].len; | 221 + index[ctx->index].len; |
186 } | 222 } |
187 | 223 |
224 if (ilcf->cache) { | |
225 | |
226 if (cache) { | |
227 if (redirect.len == cache->data.value.len | |
228 && ngx_memcmp(cache->data.value.data, redirect.data, | |
229 redirect.len) == 0) | |
230 { | |
231 cache->accessed = ngx_cached_time; | |
232 cache->updated = ngx_cached_time; | |
233 ngx_http_cache_unlock(ilcf->cache, cache); | |
234 | |
235 return ngx_http_internal_redirect(r, &redirect, NULL); | |
236 | |
237 } else { | |
238 if (redirect.len > cache->data.value.len) { | |
239 ngx_free(cache->data.value.data); | |
240 cache->data.value.data = NULL; | |
241 } | |
242 } | |
243 } | |
244 | |
245 if (cache == NULL) { | |
246 cache = ngx_http_cache_alloc(ilcf->cache, &r->uri, crc, | |
247 r->connection->log); | |
248 } | |
249 | |
250 ngx_log_debug(r->connection->log, "index cache alloc: %x" _ cache); | |
251 | |
252 if (cache) { | |
253 cache->fd = NGX_INVALID_FILE; | |
254 cache->accessed = ngx_cached_time; | |
255 cache->last_modified = 0; | |
256 cache->updated = ngx_cached_time; | |
257 | |
258 cache->data.value.len = redirect.len; | |
259 if (cache->data.value.data == NULL) { | |
260 cache->data.value.data = ngx_alloc(redirect.len + 1, | |
261 r->connection->log); | |
262 if (cache->data.value.data == NULL) { | |
263 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
264 } | |
265 } | |
266 | |
267 ngx_memcpy(cache->data.value.data, redirect.data, | |
268 redirect.len + 1); | |
269 } | |
270 } | |
271 | |
272 if (cache) { | |
273 ngx_http_cache_unlock(ilcf->cache, cache); | |
274 } | |
275 | |
188 return ngx_http_internal_redirect(r, &redirect, NULL); | 276 return ngx_http_internal_redirect(r, &redirect, NULL); |
189 } | 277 } |
190 | 278 |
191 return NGX_DECLINED; | 279 return NGX_DECLINED; |
192 } | 280 } |
193 | 281 |
194 | 282 |
195 static int ngx_http_index_test_dir(ngx_http_request_t *r, | 283 static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, |
196 ngx_http_index_ctx_t *ctx) | 284 ngx_http_index_ctx_t *ctx) |
197 { | 285 { |
198 ngx_err_t err; | 286 ngx_err_t err; |
199 | 287 |
200 r->path.data[r->path.len - 1] = '\0'; | 288 r->path.data[r->path.len - 1] = '\0'; |
201 r->path.data[r->path.len] = '\0'; | 289 r->path.data[r->path.len] = '\0'; |
226 /* THINK: not reached ??? */ | 314 /* THINK: not reached ??? */ |
227 return ngx_http_index_error(r, ctx, 0); | 315 return ngx_http_index_error(r, ctx, 0); |
228 } | 316 } |
229 | 317 |
230 | 318 |
231 static int ngx_http_index_error(ngx_http_request_t *r, | 319 static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, |
232 ngx_http_index_ctx_t *ctx, ngx_err_t err) | 320 ngx_http_index_ctx_t *ctx, ngx_err_t err) |
233 { | 321 { |
234 if (err == NGX_EACCES) { | 322 if (err == NGX_EACCES) { |
235 ngx_log_error(NGX_LOG_ERR, r->connection->log, err, | 323 ngx_log_error(NGX_LOG_ERR, r->connection->log, err, |
236 "\"%s\" is forbidden", r->path.data); | 324 "\"%s\" is forbidden", r->path.data); |
237 | 325 |
270 NGX_CONF_ERROR); | 358 NGX_CONF_ERROR); |
271 | 359 |
272 ngx_init_array(conf->indices, cf->pool, 3, sizeof(ngx_str_t), | 360 ngx_init_array(conf->indices, cf->pool, 3, sizeof(ngx_str_t), |
273 NGX_CONF_ERROR); | 361 NGX_CONF_ERROR); |
274 conf->max_index_len = 0; | 362 conf->max_index_len = 0; |
363 | |
364 conf->cache = NULL; | |
275 | 365 |
276 return conf; | 366 return conf; |
277 } | 367 } |
278 | 368 |
279 | 369 |
315 | 405 |
316 if (conf->max_index_len < prev->max_index_len) { | 406 if (conf->max_index_len < prev->max_index_len) { |
317 conf->max_index_len = prev->max_index_len; | 407 conf->max_index_len = prev->max_index_len; |
318 } | 408 } |
319 | 409 |
410 if (conf->cache == NULL) { | |
411 conf->cache = prev->cache; | |
412 } | |
413 | |
320 return NGX_CONF_OK; | 414 return NGX_CONF_OK; |
321 } | 415 } |
322 | 416 |
323 | 417 |
324 /* TODO: warn about duplicate indices */ | 418 /* TODO: warn about duplicate indices */ |
325 | 419 |
326 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, | 420 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, |
327 void *conf) | 421 void *conf) |
328 { | 422 { |
329 ngx_http_index_conf_t *icf = conf; | 423 ngx_http_index_conf_t *ilcf = conf; |
330 | 424 |
331 int i; | 425 int i; |
332 ngx_str_t *index, *value; | 426 ngx_str_t *index, *value; |
333 | 427 |
334 value = cf->args->elts; | 428 value = cf->args->elts; |
335 | 429 |
336 if (value[1].data[0] == '/' && icf->indices.nelts == 0) { | 430 if (value[1].data[0] == '/' && ilcf->indices.nelts == 0) { |
337 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 431 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
338 "first index \"%s\" in \"%s\" directive " | 432 "first index \"%s\" in \"%s\" directive " |
339 "must not be absolute", | 433 "must not be absolute", |
340 value[1].data, cmd->name.data); | 434 value[1].data, cmd->name.data); |
341 return NGX_CONF_ERROR; | 435 return NGX_CONF_ERROR; |
347 "index \"%s\" in \"%s\" directive is invalid", | 441 "index \"%s\" in \"%s\" directive is invalid", |
348 value[1].data, cmd->name.data); | 442 value[1].data, cmd->name.data); |
349 return NGX_CONF_ERROR; | 443 return NGX_CONF_ERROR; |
350 } | 444 } |
351 | 445 |
352 ngx_test_null(index, ngx_push_array(&icf->indices), NGX_CONF_ERROR); | 446 ngx_test_null(index, ngx_push_array(&ilcf->indices), NGX_CONF_ERROR); |
353 index->len = value[i].len; | 447 index->len = value[i].len; |
354 index->data = value[i].data; | 448 index->data = value[i].data; |
355 | 449 |
356 if (icf->max_index_len < index->len + 1) { | 450 if (ilcf->max_index_len < index->len + 1) { |
357 icf->max_index_len = index->len + 1; | 451 ilcf->max_index_len = index->len + 1; |
358 } | 452 } |
359 } | 453 } |
360 | 454 |
361 return NGX_CONF_OK; | 455 return NGX_CONF_OK; |
362 } | 456 } |