Mercurial > hg > nginx
comparison src/http/modules/ngx_http_index_module.c @ 1454:f497ed7682a7
open_file_cache in HTTP
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 01 Sep 2007 12:12:48 +0000 |
parents | c4f666fc3a7e |
children | 223e92651ca5 |
comparison
equal
deleted
inserted
replaced
1453:f2feed5bffe1 | 1454:f497ed7682a7 |
---|---|
36 | 36 |
37 #define NGX_HTTP_DEFAULT_INDEX "index.html" | 37 #define NGX_HTTP_DEFAULT_INDEX "index.html" |
38 | 38 |
39 | 39 |
40 static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, | 40 static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, |
41 ngx_http_index_ctx_t *ctx); | 41 ngx_http_core_loc_conf_t *clcf, ngx_http_index_ctx_t *ctx); |
42 static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, | 42 static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, |
43 ngx_http_index_ctx_t *ctx, ngx_err_t err); | 43 ngx_http_index_ctx_t *ctx, ngx_err_t err); |
44 | 44 |
45 static ngx_int_t ngx_http_index_init(ngx_conf_t *cf); | 45 static ngx_int_t ngx_http_index_init(ngx_conf_t *cf); |
46 static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf); | 46 static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf); |
56 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | 56 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, |
57 ngx_http_index_set_index, | 57 ngx_http_index_set_index, |
58 NGX_HTTP_LOC_CONF_OFFSET, | 58 NGX_HTTP_LOC_CONF_OFFSET, |
59 0, | 59 0, |
60 NULL }, | 60 NULL }, |
61 | |
62 #if (NGX_HTTP_CACHE) | |
63 | |
64 { ngx_string("index_cache"), | |
65 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3, | |
66 ngx_http_set_cache_slot, | |
67 NGX_HTTP_LOC_CONF_OFFSET, | |
68 offsetof(ngx_http_index_loc_conf_t, index_cache), | |
69 NULL }, | |
70 | |
71 #endif | |
72 | 61 |
73 ngx_null_command | 62 ngx_null_command |
74 }; | 63 }; |
75 | 64 |
76 | 65 |
118 static ngx_int_t | 107 static ngx_int_t |
119 ngx_http_index_handler(ngx_http_request_t *r) | 108 ngx_http_index_handler(ngx_http_request_t *r) |
120 { | 109 { |
121 u_char *last; | 110 u_char *last; |
122 size_t len; | 111 size_t len; |
123 ngx_fd_t fd; | |
124 ngx_int_t rc; | 112 ngx_int_t rc; |
125 ngx_err_t err; | 113 ngx_str_t path, uri; |
126 ngx_str_t uri; | |
127 ngx_log_t *log; | 114 ngx_log_t *log; |
128 ngx_uint_t i; | 115 ngx_uint_t i; |
129 ngx_http_index_t *index; | 116 ngx_http_index_t *index; |
130 ngx_http_index_ctx_t *ctx; | 117 ngx_http_index_ctx_t *ctx; |
131 ngx_pool_cleanup_t *cln; | 118 ngx_open_file_info_t of; |
132 ngx_pool_cleanup_file_t *clnf; | |
133 ngx_http_script_code_pt code; | 119 ngx_http_script_code_pt code; |
134 ngx_http_script_engine_t e; | 120 ngx_http_script_engine_t e; |
135 ngx_http_core_loc_conf_t *clcf; | 121 ngx_http_core_loc_conf_t *clcf; |
136 ngx_http_index_loc_conf_t *ilcf; | 122 ngx_http_index_loc_conf_t *ilcf; |
137 ngx_http_script_len_code_pt lcode; | 123 ngx_http_script_len_code_pt lcode; |
149 return NGX_DECLINED; | 135 return NGX_DECLINED; |
150 } | 136 } |
151 | 137 |
152 log = r->connection->log; | 138 log = r->connection->log; |
153 | 139 |
140 ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); | |
141 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
142 | |
154 /* | 143 /* |
155 * we use context because the handler supports an async file opening, | 144 * we use context because the handler supports an async file opening, |
156 * and may be called several times | 145 * and may be called several times |
157 */ | 146 */ |
158 | 147 |
159 ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); | |
160 | |
161 ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); | 148 ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); |
162 if (ctx == NULL) { | 149 if (ctx == NULL) { |
163 | 150 |
164 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_index_ctx_t)); | 151 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_index_ctx_t)); |
165 if (ctx == NULL) { | 152 if (ctx == NULL) { |
212 } | 199 } |
213 | 200 |
214 ctx->index.data = last; | 201 ctx->index.data = last; |
215 } | 202 } |
216 | 203 |
204 path.data = ctx->path.data; | |
205 | |
217 if (index[i].values == NULL) { | 206 if (index[i].values == NULL) { |
218 | 207 |
219 /* index[i].name.len includes the terminating '\0' */ | 208 /* index[i].name.len includes the terminating '\0' */ |
220 | 209 |
221 ngx_memcpy(ctx->index.data, index[i].name.data, index[i].name.len); | 210 ngx_memcpy(ctx->index.data, index[i].name.data, index[i].name.len); |
211 | |
212 path.len = (ctx->index.data + index[i].name.len - 1) - path.data; | |
222 | 213 |
223 } else { | 214 } else { |
224 e.ip = index[i].values->elts; | 215 e.ip = index[i].values->elts; |
225 e.pos = ctx->index.data; | 216 e.pos = ctx->index.data; |
226 | 217 |
232 if (*ctx->index.data == '/') { | 223 if (*ctx->index.data == '/') { |
233 ctx->index.len--; | 224 ctx->index.len--; |
234 return ngx_http_internal_redirect(r, &ctx->index, &r->args); | 225 return ngx_http_internal_redirect(r, &ctx->index, &r->args); |
235 } | 226 } |
236 | 227 |
228 path.len = e.pos - path.data; | |
229 | |
237 *e.pos++ = '\0'; | 230 *e.pos++ = '\0'; |
238 } | 231 } |
239 | 232 |
240 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, | 233 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, |
241 "open index \"%s\"", ctx->path.data); | 234 "open index \"%V\"", &path); |
242 | 235 |
243 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); | 236 of.test_dir = 0; |
244 if (cln == NULL) { | 237 of.retest = clcf->open_file_cache_retest; |
245 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 238 of.errors = clcf->open_file_cache_errors; |
246 } | 239 |
247 | 240 rc = ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool); |
248 fd = ngx_open_file(ctx->path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); | 241 |
249 | 242 #if 0 |
250 if (fd == (ngx_fd_t) NGX_AGAIN) { | 243 if (rc == NGX_AGAIN) { |
251 ctx->current = i; | 244 ctx->current = i; |
252 return NGX_AGAIN; | 245 return NGX_AGAIN; |
253 } | 246 } |
254 | 247 #endif |
255 if (fd == NGX_INVALID_FILE) { | 248 |
256 err = ngx_errno; | 249 if (rc == NGX_ERROR) { |
257 | 250 |
258 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, err, | 251 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, of.err, |
259 ngx_open_file_n " \"%s\" failed", ctx->path.data); | 252 ngx_open_file_n " \"%s\" failed", ctx->path.data); |
260 | 253 |
261 if (err == NGX_ENOTDIR) { | 254 if (of.err == 0) { |
262 return ngx_http_index_error(r, ctx, err); | 255 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
263 | 256 } |
264 } else if (err == NGX_EACCES) { | 257 |
265 return ngx_http_index_error(r, ctx, err); | 258 if (of.err == NGX_ENOTDIR) { |
259 return ngx_http_index_error(r, ctx, of.err); | |
260 | |
261 } else if (of.err == NGX_EACCES) { | |
262 return ngx_http_index_error(r, ctx, of.err); | |
266 } | 263 } |
267 | 264 |
268 if (!ctx->tested) { | 265 if (!ctx->tested) { |
269 rc = ngx_http_index_test_dir(r, ctx); | 266 rc = ngx_http_index_test_dir(r, clcf, ctx); |
270 | 267 |
271 if (rc != NGX_OK) { | 268 if (rc != NGX_OK) { |
272 return rc; | 269 return rc; |
273 } | 270 } |
274 | 271 |
275 ctx->tested = 1; | 272 ctx->tested = 1; |
276 } | 273 } |
277 | 274 |
278 if (err == NGX_ENOENT) { | 275 if (of.err == NGX_ENOENT) { |
279 continue; | 276 continue; |
280 } | 277 } |
281 | 278 |
282 ngx_log_error(NGX_LOG_ERR, log, err, | 279 ngx_log_error(NGX_LOG_ERR, log, of.err, |
283 ngx_open_file_n " \"%s\" failed", ctx->path.data); | 280 ngx_open_file_n " \"%s\" failed", ctx->path.data); |
284 | 281 |
285 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 282 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
286 } | 283 } |
287 | |
288 cln->handler = ngx_pool_cleanup_file; | |
289 clnf = cln->data; | |
290 | |
291 clnf->fd = fd; | |
292 clnf->name = ctx->path.data; | |
293 clnf->log = r->pool->log; | |
294 | |
295 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
296 | 284 |
297 uri.len = r->uri.len + ctx->index.len - 1; | 285 uri.len = r->uri.len + ctx->index.len - 1; |
298 | 286 |
299 if (!clcf->alias) { | 287 if (!clcf->alias) { |
300 uri.data = ctx->path.data + ctx->root; | 288 uri.data = ctx->path.data + ctx->root; |
315 return NGX_DECLINED; | 303 return NGX_DECLINED; |
316 } | 304 } |
317 | 305 |
318 | 306 |
319 static ngx_int_t | 307 static ngx_int_t |
320 ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_index_ctx_t *ctx) | 308 ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_core_loc_conf_t *clcf, |
321 { | 309 ngx_http_index_ctx_t *ctx) |
322 u_char c; | 310 { |
323 ngx_uint_t i; | 311 u_char c; |
324 ngx_err_t err; | 312 ngx_str_t path; |
325 ngx_file_info_t fi; | 313 ngx_uint_t i; |
314 ngx_open_file_info_t of; | |
326 | 315 |
327 c = *(ctx->index.data - 1); | 316 c = *(ctx->index.data - 1); |
328 i = (c == '/') ? 1 : 0; | 317 i = (c == '/') ? 1 : 0; |
329 *(ctx->index.data - i) = '\0'; | 318 *(ctx->index.data - i) = '\0'; |
330 | 319 |
320 path.len = (ctx->index.data - i) - ctx->path.data; | |
321 path.data = ctx->path.data; | |
322 | |
331 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 323 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
332 "http index check dir: \"%s\"", ctx->path.data); | 324 "http index check dir: \"%V\"", &path); |
333 | 325 |
334 if (ngx_file_info(ctx->path.data, &fi) == -1) { | 326 of.test_dir = 1; |
335 | 327 of.retest = clcf->open_file_cache_retest; |
336 err = ngx_errno; | 328 of.errors = clcf->open_file_cache_errors; |
337 | 329 |
338 if (err == NGX_ENOENT) { | 330 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) |
339 *(ctx->index.data - i) = c; | 331 != NGX_OK) |
340 return ngx_http_index_error(r, ctx, err); | 332 { |
341 } | 333 if (of.err) { |
342 | 334 |
343 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, | 335 if (of.err == NGX_ENOENT) { |
344 ngx_file_info_n " \"%s\" failed", ctx->path.data); | 336 *(ctx->index.data - i) = c; |
337 return ngx_http_index_error(r, ctx, of.err); | |
338 } | |
339 | |
340 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, | |
341 ngx_open_file_n " \"%s\" failed", path.data); | |
342 } | |
345 | 343 |
346 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 344 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
347 } | 345 } |
348 | 346 |
349 *(ctx->index.data - i) = c; | 347 *(ctx->index.data - i) = c; |
350 | 348 |
351 if (ngx_is_dir(&fi)) { | 349 if (of.is_dir) { |
352 return NGX_OK; | 350 return NGX_OK; |
353 } | 351 } |
354 | 352 |
355 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | 353 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
356 "\"%s\" is not a directory", ctx->path.data); | 354 "\"%s\" is not a directory", path.data); |
357 | 355 |
358 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 356 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
359 } | 357 } |
360 | 358 |
361 | 359 |