comparison src/http/modules/ngx_http_index_module.c @ 509:9b8c906f6e63 release-0.1.29

nginx-0.1.29-RELEASE import *) Feature: the ngx_http_ssi_module supports "include virtual" command. *) Feature: the ngx_http_ssi_module supports the condition command like 'if expr="$NAME"' and "else" and "endif" commands. Only one nested level is supported. *) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and DATE_GMT variables and "config timefmt" command. *) Feature: the "ssi_ignore_recycled_buffers" directive. *) Bugfix: the "echo" command did not show the default value for the empty QUERY_STRING variable. *) Change: the ngx_http_proxy_module was rewritten. *) Feature: the "proxy_redirect", "proxy_pass_request_headers", "proxy_pass_request_body", and "proxy_method" directives. *) Feature: the "proxy_set_header" directive. The "proxy_x_var" was canceled and must be replaced with the proxy_set_header directive. *) Change: the "proxy_preserve_host" is canceled and must be replaced with the "proxy_set_header Host $host" and the "proxy_redirect off" directives, the "proxy_set_header Host $host:$proxy_port" directive and the appropriate proxy_redirect directives. *) Change: the "proxy_set_x_real_ip" is canceled and must be replaced with the "proxy_set_header X-Real-IP $remote_addr" directive. *) Change: the "proxy_add_x_forwarded_for" is canceled and must be replaced with the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for" directive. *) Change: the "proxy_set_x_url" is canceled and must be replaced with the "proxy_set_header X-URL http://$host:$server_port$request_uri" directive. *) Feature: the "fastcgi_param" directive. *) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params" directive are canceled and must be replaced with the fastcgi_param directives. *) Feature: the "index" directive can use the variables. *) Feature: the "index" directive can be used at http and server levels. *) Change: the last index only in the "index" directive can be absolute. *) Feature: the "rewrite" directive can use the variables. *) Feature: the "internal" directive. *) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME, REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables. *) Change: nginx now passes the invalid lines in a client request headers or a backend response header. *) Bugfix: if the backend did not transfer response for a long time and the "send_timeout" was less than "proxy_read_timeout", then nginx returned the 408 response. *) Bugfix: the segmentation fault was occurred if the backend sent an invalid line in response header; the bug had appeared in 0.1.26. *) Bugfix: the segmentation fault may occurred in FastCGI fault tolerance configuration. *) Bugfix: the "expires" directive did not remove the previous "Expires" and "Cache-Control" headers. *) Bugfix: nginx did not take into account trailing dot in "Host" header line. *) Bugfix: the ngx_http_auth_module did not work under Linux. *) Bugfix: the rewrite directive worked incorrectly, if the arguments were in a request. *) Bugfix: nginx could not be built on MacOS X.
author Igor Sysoev <igor@sysoev.ru>
date Thu, 12 May 2005 14:58:06 +0000
parents d4ea69372b94
children b09ee85d0ac8
comparison
equal deleted inserted replaced
508:ca1020ce99ba 509:9b8c906f6e63
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_http.h> 9 #include <ngx_http.h>
10 10
11 11
12 typedef struct { 12 typedef struct {
13 ngx_array_t indices; 13 ngx_str_t name;
14 ngx_array_t *lengths;
15 ngx_array_t *values;
16 } ngx_http_index_t;
17
18
19 typedef struct {
20 ngx_array_t *indices; /* array of ngx_http_index_t */
14 size_t max_index_len; 21 size_t max_index_len;
15 ngx_http_cache_hash_t *index_cache;
16 } ngx_http_index_loc_conf_t; 22 } ngx_http_index_loc_conf_t;
17 23
18 24
19 typedef struct { 25 typedef struct {
20 ngx_uint_t index; 26 ngx_uint_t current;
21 u_char *last; 27 size_t allocated;
22 ngx_str_t path; 28
23 ngx_str_t redirect; 29 u_char *path;
24 ngx_http_cache_entry_t *cache; 30 ngx_str_t uri;
25 ngx_uint_t tested; /* unsigned tested:1 */ 31 ngx_str_t index;
32
33 ngx_uint_t tested; /* unsigned tested:1 */
26 } ngx_http_index_ctx_t; 34 } ngx_http_index_ctx_t;
27 35
28 36
29 #define NGX_HTTP_DEFAULT_INDEX "index.html" 37 #define NGX_HTTP_DEFAULT_INDEX "index.html"
30 38
31 39
40 static ngx_int_t ngx_http_index_alloc(ngx_http_request_t *r, size_t size,
41 ngx_http_index_ctx_t *ctx, ngx_http_core_loc_conf_t *clcf);
32 static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, 42 static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
33 ngx_http_index_ctx_t *ctx); 43 ngx_http_index_ctx_t *ctx);
34 static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, 44 static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
35 ngx_http_index_ctx_t *ctx, ngx_err_t err); 45 ngx_http_index_ctx_t *ctx, ngx_err_t err);
36 46
37 static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle); 47 static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle);
38 static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf); 48 static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf);
39 static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf, 49 static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
40 void *parent, void *child); 50 void *parent, void *child);
41 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, 51 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
42 void *conf); 52 void *conf);
43 53
44 54
45 static ngx_command_t ngx_http_index_commands[] = { 55 static ngx_command_t ngx_http_index_commands[] = {
46 56
47 { ngx_string("index"), 57 { ngx_string("index"),
48 NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, 58 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
49 ngx_http_index_set_index, 59 ngx_http_index_set_index,
50 NGX_HTTP_LOC_CONF_OFFSET, 60 NGX_HTTP_LOC_CONF_OFFSET,
51 0, 61 0,
52 NULL }, 62 NULL },
53 63
65 ngx_null_command 75 ngx_null_command
66 }; 76 };
67 77
68 78
69 ngx_http_module_t ngx_http_index_module_ctx = { 79 ngx_http_module_t ngx_http_index_module_ctx = {
70 NULL, /* pre conf */ 80 NULL, /* preconfiguration */
81 NULL, /* postconfiguration */
71 82
72 NULL, /* create main configuration */ 83 NULL, /* create main configuration */
73 NULL, /* init main configuration */ 84 NULL, /* init main configuration */
74 85
75 NULL, /* create server configuration */ 86 NULL, /* create server configuration */
79 ngx_http_index_merge_loc_conf /* merge location configration */ 90 ngx_http_index_merge_loc_conf /* merge location configration */
80 }; 91 };
81 92
82 93
83 ngx_module_t ngx_http_index_module = { 94 ngx_module_t ngx_http_index_module = {
84 NGX_MODULE, 95 NGX_MODULE_V1,
85 &ngx_http_index_module_ctx, /* module context */ 96 &ngx_http_index_module_ctx, /* module context */
86 ngx_http_index_commands, /* module directives */ 97 ngx_http_index_commands, /* module directives */
87 NGX_HTTP_MODULE, /* module type */ 98 NGX_HTTP_MODULE, /* module type */
88 ngx_http_index_init, /* init module */ 99 ngx_http_index_init, /* init module */
89 NULL /* init process */ 100 NULL /* init process */
98 * Besides, Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR). 109 * Besides, Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
99 * Unix has ENOTDIR error, although it less helpfull - it points only 110 * Unix has ENOTDIR error, although it less helpfull - it points only
100 * that path contains the usual file in place of the directory. 111 * that path contains the usual file in place of the directory.
101 */ 112 */
102 113
103 static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r) 114 static ngx_int_t
104 { 115 ngx_http_index_handler(ngx_http_request_t *r)
105 u_char *name; 116 {
106 ngx_fd_t fd; 117 u_char *name;
107 ngx_int_t rc; 118 size_t len;
108 ngx_str_t *index; 119 ngx_fd_t fd;
109 ngx_err_t err; 120 ngx_int_t rc;
110 ngx_log_t *log; 121 ngx_err_t err;
111 ngx_http_index_ctx_t *ctx; 122 ngx_log_t *log;
112 ngx_http_core_loc_conf_t *clcf; 123 ngx_uint_t i;
113 ngx_http_index_loc_conf_t *ilcf; 124 ngx_http_index_t *index;
114 #if (NGX_HTTP_CACHE0) 125 ngx_http_index_ctx_t *ctx;
115 /* crc must be in ctx !! */ 126 ngx_pool_cleanup_file_t *cln;
116 uint32_t crc; 127 ngx_http_script_code_pt code;
117 #endif 128 ngx_http_script_engine_t e;
129 ngx_http_core_loc_conf_t *clcf;
130 ngx_http_index_loc_conf_t *ilcf;
131 ngx_http_script_len_code_pt lcode;
118 132
119 if (r->uri.data[r->uri.len - 1] != '/') { 133 if (r->uri.data[r->uri.len - 1] != '/') {
120 return NGX_DECLINED; 134 return NGX_DECLINED;
121 } 135 }
122 136
126 } 140 }
127 141
128 log = r->connection->log; 142 log = r->connection->log;
129 143
130 /* 144 /*
131 * we use context because the handler supports an async file opening 145 * we use context because the handler supports an async file opening,
132 * and thus can be called several times 146 * and may be called several times
133 */ 147 */
134 148
135 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 149 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
136 ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); 150 ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
137 151
142 if (ctx == NULL) { 156 if (ctx == NULL) {
143 return NGX_HTTP_INTERNAL_SERVER_ERROR; 157 return NGX_HTTP_INTERNAL_SERVER_ERROR;
144 } 158 }
145 159
146 ngx_http_set_ctx(r, ctx, ngx_http_index_module); 160 ngx_http_set_ctx(r, ctx, ngx_http_index_module);
147 161 }
148 #if (NGX_HTTP_CACHE) 162
149 163 index = ilcf->indices->elts;
150 if (ilcf->index_cache) { 164 for (i = ctx->current; i < ilcf->indices->nelts; i++) {
151 ctx->cache = ngx_http_cache_get(ilcf->index_cache, NULL, 165
152 &r->uri, &crc); 166 if (index[i].lengths == NULL) {
153 167
154 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, 168 if (index[i].name.data[0] == '/') {
155 "http index cache get: %p", ctx->cache); 169 return ngx_http_internal_redirect(r, &index[i].name, &r->args);
156 170 }
157 if (ctx->cache && !ctx->cache->expired) { 171
158 172 len = ilcf->max_index_len;
159 ctx->cache->accessed = ngx_cached_time; 173 ctx->index.len = index[i].name.len;
160 174
161 ctx->redirect.len = ctx->cache->data.value.len; 175 } else {
162 ctx->redirect.data = ngx_palloc(r->pool, ctx->redirect.len + 1); 176 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
163 if (ctx->redirect.data == NULL) { 177
164 ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log); 178 e.ip = index[i].lengths->elts;
165 return NGX_HTTP_INTERNAL_SERVER_ERROR; 179 e.request = r;
166 } 180
167 181 len = 1;
168 ngx_memcpy(ctx->redirect.data, ctx->cache->data.value.data, 182
169 ctx->redirect.len + 1); 183 while (*(uintptr_t *) e.ip) {
170 ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log); 184 lcode = *(ngx_http_script_len_code_pt *) e.ip;
171 185 len += lcode(&e);
172 return ngx_http_internal_redirect(r, &ctx->redirect, NULL); 186 }
173 } 187
174 } 188 ctx->index.len = len;
175 189 }
176 #endif 190
177 191 if (len > ctx->allocated) {
178 #if 0 192 if (ngx_http_index_alloc(r, len, ctx, clcf) != NGX_OK) {
179 ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len
180 + ilcf->max_index_len
181 - clcf->alias * clcf->name.len);
182 if (ctx->path.data == NULL) {
183 return NGX_HTTP_INTERNAL_SERVER_ERROR;
184 }
185
186 ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data,
187 clcf->root.len);
188 #endif
189
190 if (clcf->alias) {
191 ctx->path.data = ngx_palloc(r->pool, clcf->root.len
192 + r->uri.len + 1 - clcf->name.len
193 + ilcf->max_index_len);
194 if (ctx->path.data == NULL) {
195 return NGX_HTTP_INTERNAL_SERVER_ERROR; 193 return NGX_HTTP_INTERNAL_SERVER_ERROR;
196 } 194 }
197 195 }
198 ctx->redirect.data = ngx_palloc(r->pool, r->uri.len 196
199 + ilcf->max_index_len); 197 if (index[i].values == NULL) {
200 if (ctx->redirect.data == NULL) { 198 ngx_memcpy(ctx->index.data, index[i].name.data, ctx->index.len);
201 return NGX_HTTP_INTERNAL_SERVER_ERROR;
202 }
203
204 ngx_memcpy(ctx->path.data, clcf->root.data, clcf->root.len);
205
206 ctx->last = ngx_cpystrn(ctx->path.data + clcf->root.len,
207 r->uri.data + clcf->name.len,
208 r->uri.len + 1 - clcf->name.len);
209
210 #if 0
211 /*
212 * aliases usually have trailling "/",
213 * set it in the start of the possible redirect
214 */
215
216 if (*ctx->redirect.data != '/') {
217 ctx->redirect.data--;
218 }
219 #endif
220 199
221 } else { 200 } else {
222 ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len 201 e.ip = index[i].values->elts;
223 + ilcf->max_index_len); 202 e.pos = ctx->index.data;
224 if (ctx->path.data == NULL) { 203
225 return NGX_HTTP_INTERNAL_SERVER_ERROR; 204 while (*(uintptr_t *) e.ip) {
226 } 205 code = *(ngx_http_script_code_pt *) e.ip;
227 206 code((ngx_http_script_engine_t *) &e);
228 ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data, 207 }
229 clcf->root.len); 208
230 209 if (*ctx->index.data == '/') {
231 ctx->last = ngx_cpystrn(ctx->redirect.data, r->uri.data, 210 ctx->index.len--;
232 r->uri.len + 1); 211 return ngx_http_internal_redirect(r, &ctx->index, &r->args);
233 } 212 }
234 } 213
235 214 *e.pos++ = '\0';
236 ctx->path.len = ctx->last - ctx->path.data; 215 }
237 216
238 index = ilcf->indices.elts; 217 name = ctx->path;
239 for (/* void */; ctx->index < ilcf->indices.nelts; ctx->index++) {
240
241 if (index[ctx->index].data[0] == '/') {
242 name = index[ctx->index].data;
243
244 } else {
245 ngx_memcpy(ctx->last, index[ctx->index].data,
246 index[ctx->index].len + 1);
247 name = ctx->path.data;
248 }
249 218
250 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, 219 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
251 "open index \"%s\"", name); 220 "open index \"%s\"", name);
252 221
253 fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN); 222 fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
254 223
255 if (fd == (ngx_fd_t) NGX_AGAIN) { 224 if (fd == (ngx_fd_t) NGX_AGAIN) {
225 ctx->current = i;
256 return NGX_AGAIN; 226 return NGX_AGAIN;
257 } 227 }
258 228
259 if (fd == NGX_INVALID_FILE) { 229 if (fd == NGX_INVALID_FILE) {
260 err = ngx_errno; 230 err = ngx_errno;
288 258
289 return NGX_HTTP_INTERNAL_SERVER_ERROR; 259 return NGX_HTTP_INTERNAL_SERVER_ERROR;
290 } 260 }
291 261
292 262
293 /* STUB: open file cache */ 263 cln = ngx_palloc(r->pool, sizeof(ngx_pool_cleanup_file_t));
294 264 if (cln == NULL) {
295 r->file.name.data = name; 265 return NGX_HTTP_INTERNAL_SERVER_ERROR;
296 r->file.fd = fd; 266 }
297 267
298 if (index[ctx->index].data[0] == '/') { 268 cln->fd = fd;
299 r->file.name.len = index[ctx->index].len; 269 cln->name = name;
300 ctx->redirect.len = index[ctx->index].len; 270 cln->log = r->pool->log;
301 ctx->redirect.data = index[ctx->index].data; 271
302 272 if (ngx_pool_cleanup_add(r->pool, ngx_pool_cleanup_file, cln) == NULL) {
303 } else { 273 return NGX_HTTP_INTERNAL_SERVER_ERROR;
304 if (clcf->alias) { 274 }
305 name = ngx_cpymem(ctx->redirect.data, r->uri.data, r->uri.len); 275
306 ngx_memcpy(name, index[ctx->index].data, 276
307 index[ctx->index].len + 1); 277 if (clcf->alias) {
308 } 278 name = ngx_cpymem(ctx->uri.data, r->uri.data, r->uri.len);
309 279 ngx_memcpy(name, ctx->index.data, ctx->index.len - 1);
310 ctx->redirect.len = r->uri.len + index[ctx->index].len; 280 }
311 r->file.name.len = clcf->root.len + r->uri.len 281
312 - clcf->alias * clcf->name.len 282 ctx->uri.len = r->uri.len + ctx->index.len - 1;
313 + index[ctx->index].len; 283
314 } 284 return ngx_http_internal_redirect(r, &ctx->uri, &r->args);
315
316 /**/
317
318
319 #if (NGX_HTTP_CACHE)
320
321 if (ilcf->index_cache) {
322
323 if (ctx->cache) {
324 if (ctx->redirect.len == ctx->cache->data.value.len
325 && ngx_memcmp(ctx->cache->data.value.data,
326 ctx->redirect.data, ctx->redirect.len) == 0)
327 {
328 ctx->cache->accessed = ngx_cached_time;
329 ctx->cache->updated = ngx_cached_time;
330 ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
331
332 return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
333 }
334 }
335
336 ctx->redirect.len++;
337 ctx->cache = ngx_http_cache_alloc(ilcf->index_cache, ctx->cache,
338 NULL, &r->uri, crc,
339 &ctx->redirect, log);
340 ctx->redirect.len--;
341
342 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
343 "http index cache alloc: %p", ctx->cache);
344
345 if (ctx->cache) {
346 ctx->cache->fd = NGX_INVALID_FILE;
347 ctx->cache->accessed = ngx_cached_time;
348 ctx->cache->last_modified = 0;
349 ctx->cache->updated = ngx_cached_time;
350 ctx->cache->memory = 1;
351 ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
352 }
353 }
354
355 #endif
356
357 return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
358 } 285 }
359 286
360 return NGX_DECLINED; 287 return NGX_DECLINED;
361 } 288 }
362 289
363 290
364 static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, 291 static ngx_int_t
365 ngx_http_index_ctx_t *ctx) 292 ngx_http_index_alloc(ngx_http_request_t *r, size_t size,
366 { 293 ngx_http_index_ctx_t *ctx, ngx_http_core_loc_conf_t *clcf)
367 ngx_err_t err; 294 {
368 295 ctx->allocated = size;
369 ctx->path.data[ctx->path.len - 1] = '\0'; 296
370 ctx->path.data[ctx->path.len] = '\0'; 297 if (!clcf->alias) {
298 ctx->path = ngx_palloc(r->pool, clcf->root.len + r->uri.len + size);
299 if (ctx->path == NULL) {
300 return NGX_ERROR;
301 }
302
303 ctx->uri.data = ngx_cpymem(ctx->path, clcf->root.data, clcf->root.len);
304
305 ctx->index.data = ngx_cpymem(ctx->uri.data, r->uri.data, r->uri.len);
306
307 } else {
308 ctx->path = ngx_palloc(r->pool,
309 clcf->root.len + r->uri.len - clcf->name.len + size);
310 if (ctx->path == NULL) {
311 return NGX_ERROR;
312 }
313
314 ctx->uri.data = ngx_palloc(r->pool, r->uri.len + size);
315 if (ctx->uri.data == NULL) {
316 return NGX_ERROR;
317 }
318
319 ngx_memcpy(ctx->path, clcf->root.data, clcf->root.len);
320
321 ctx->index.data = ngx_cpymem(ctx->path + clcf->root.len,
322 r->uri.data + clcf->name.len,
323 r->uri.len - clcf->name.len);
324 }
325
326 return NGX_OK;
327 }
328
329
330 static ngx_int_t
331 ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_index_ctx_t *ctx)
332 {
333 ngx_err_t err;
334 ngx_file_info_t fi;
335
336 *(ctx->index.data - 1) = '\0';
371 337
372 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 338 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
373 "http check dir: \"%s\"", ctx->path.data); 339 "http index check dir: \"%s\"", ctx->path);
374 340
375 if (ngx_file_info(ctx->path.data, &r->file.info) == -1) { 341 if (ngx_file_info(ctx->path, &fi) == -1) {
376 342
377 err = ngx_errno; 343 err = ngx_errno;
378 344
379 if (err == NGX_ENOENT) { 345 if (err == NGX_ENOENT) {
380 ctx->path.data[ctx->path.len - 1] = '/'; 346 *(ctx->index.data - 1) = '/';
381 return ngx_http_index_error(r, ctx, err); 347 return ngx_http_index_error(r, ctx, err);
382 } 348 }
383 349
384 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, 350 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
385 ngx_file_info_n " \"%s\" failed", ctx->path.data); 351 ngx_file_info_n " \"%s\" failed", ctx->path);
386 352
387 return NGX_HTTP_INTERNAL_SERVER_ERROR; 353 return NGX_HTTP_INTERNAL_SERVER_ERROR;
388 } 354 }
389 355
390 ctx->path.data[ctx->path.len - 1] = '/'; 356 *(ctx->index.data - 1) = '/';
391 357
392 if (ngx_is_dir(&r->file.info)) { 358 if (ngx_is_dir(&fi)) {
393 return NGX_OK; 359 return NGX_OK;
394 } 360 }
395 361
396 /* THINK: not reached ??? */ 362 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
397 return ngx_http_index_error(r, ctx, 0); 363 "\"%s\" is not a directory", ctx->path);
398 } 364
399 365 return NGX_HTTP_INTERNAL_SERVER_ERROR;
400 366 }
401 static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, 367
402 ngx_http_index_ctx_t *ctx, ngx_err_t err) 368
369 static ngx_int_t
370 ngx_http_index_error(ngx_http_request_t *r, ngx_http_index_ctx_t *ctx,
371 ngx_err_t err)
403 { 372 {
404 if (err == NGX_EACCES) { 373 if (err == NGX_EACCES) {
405 ngx_log_error(NGX_LOG_ERR, r->connection->log, err, 374 ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
406 "\"%s\" is forbidden", ctx->path.data); 375 "\"%s\" is forbidden", ctx->path);
407 376
408 return NGX_HTTP_FORBIDDEN; 377 return NGX_HTTP_FORBIDDEN;
409 } 378 }
410 379
411 ngx_log_error(NGX_LOG_ERR, r->connection->log, err, 380 ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
412 "\"%s\" is not found", ctx->path.data); 381 "\"%s\" is not found", ctx->path);
382
413 return NGX_HTTP_NOT_FOUND; 383 return NGX_HTTP_NOT_FOUND;
414 } 384 }
415 385
416 386
417 static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle) 387 static void *
388 ngx_http_index_create_loc_conf(ngx_conf_t *cf)
389 {
390 ngx_http_index_loc_conf_t *conf;
391
392 conf = ngx_palloc(cf->pool, sizeof(ngx_http_index_loc_conf_t));
393 if (conf == NULL) {
394 return NGX_CONF_ERROR;
395 }
396
397 conf->indices = NULL;
398 conf->max_index_len = 1;
399
400 return conf;
401 }
402
403
404 static char *
405 ngx_http_index_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
406 {
407 ngx_http_index_loc_conf_t *prev = parent;
408 ngx_http_index_loc_conf_t *conf = child;
409
410 ngx_http_index_t *index;
411
412 if (conf->indices == NULL) {
413 conf->indices = prev->indices;
414 conf->max_index_len = prev->max_index_len;
415 }
416
417 if (conf->indices == NULL) {
418 conf->indices = ngx_array_create(cf->pool, 1, sizeof(ngx_http_index_t));
419 if (conf->indices == NULL) {
420 return NGX_CONF_ERROR;
421 }
422
423 index = ngx_array_push(conf->indices);
424 if (index == NULL) {
425 return NGX_CONF_ERROR;
426 }
427
428 index->name.len = sizeof(NGX_HTTP_DEFAULT_INDEX);
429 index->name.data = (u_char *) NGX_HTTP_DEFAULT_INDEX;
430 index->lengths = NULL;
431 index->values = NULL;
432
433 conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX);
434
435 return NGX_CONF_OK;
436 }
437
438 return NGX_CONF_OK;
439 }
440
441
442 /* TODO: warn about duplicate indices */
443
444 static char *
445 ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
446 {
447 ngx_http_index_loc_conf_t *ilcf = conf;
448
449 ngx_uint_t i, n;
450 ngx_str_t *value;
451 ngx_http_index_t *index;
452 ngx_http_script_compile_t sc;
453
454 if (ilcf->indices == NULL) {
455 ilcf->indices = ngx_array_create(cf->pool, 2, sizeof(ngx_http_index_t));
456 if (ilcf->indices == NULL) {
457 return NGX_CONF_ERROR;
458 }
459 }
460
461 value = cf->args->elts;
462
463 for (i = 1; i < cf->args->nelts; i++) {
464 if (value[i].data[0] == '/' && i != cf->args->nelts - 1) {
465 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
466 "only the last index in \"index\" directive "
467 "may be absolute");
468 return NGX_CONF_ERROR;
469 }
470
471 if (value[i].len == 0) {
472 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
473 "index \"%V\" in \"index\" directive is invalid",
474 &value[1]);
475 return NGX_CONF_ERROR;
476 }
477
478 index = ngx_array_push(ilcf->indices);
479 if (index == NULL) {
480 return NGX_CONF_ERROR;
481 }
482
483 index->name.len = value[i].len;
484 index->name.data = value[i].data;
485 index->lengths = NULL;
486 index->values = NULL;
487
488 n = ngx_http_script_variables_count(&value[i]);
489
490 if (n == 0) {
491 index->name.len++;
492
493 if (ilcf->max_index_len != 0
494 && ilcf->max_index_len < index->name.len)
495 {
496 ilcf->max_index_len = index->name.len;
497 }
498
499 continue;
500 }
501
502 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
503
504 sc.cf = cf;
505 sc.source = &value[i];
506 sc.lengths = &index->lengths;
507 sc.values = &index->values;
508 sc.variables = n;
509 sc.complete_lengths = 1;
510 sc.complete_values = 1;
511
512 if (ngx_http_script_compile(&sc) != NGX_OK) {
513 return NGX_CONF_ERROR;
514 }
515
516 ilcf->max_index_len = 0;
517 }
518
519 return NGX_CONF_OK;
520 }
521
522
523 static ngx_int_t
524 ngx_http_index_init(ngx_cycle_t *cycle)
418 { 525 {
419 ngx_http_handler_pt *h; 526 ngx_http_handler_pt *h;
420 ngx_http_core_main_conf_t *cmcf; 527 ngx_http_core_main_conf_t *cmcf;
421 528
422 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); 529 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
428 535
429 *h = ngx_http_index_handler; 536 *h = ngx_http_index_handler;
430 537
431 return NGX_OK; 538 return NGX_OK;
432 } 539 }
433
434
435 static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf)
436 {
437 ngx_http_index_loc_conf_t *conf;
438
439 conf = ngx_palloc(cf->pool, sizeof(ngx_http_index_loc_conf_t));
440 if (conf == NULL) {
441 return NGX_CONF_ERROR;
442 }
443
444 if (ngx_array_init(&conf->indices, cf->pool, 2, sizeof(ngx_str_t))
445 == NGX_ERROR)
446 {
447 return NGX_CONF_ERROR;
448 }
449
450 conf->max_index_len = 0;
451
452 conf->index_cache = NULL;
453
454 return conf;
455 }
456
457
458 /* TODO: remove duplicate indices */
459
460 static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
461 void *parent, void *child)
462 {
463 ngx_http_index_loc_conf_t *prev = parent;
464 ngx_http_index_loc_conf_t *conf = child;
465
466 ngx_str_t *index;
467
468 if (conf->max_index_len == 0) {
469 if (prev->max_index_len != 0) {
470 ngx_memcpy(conf, prev, sizeof(ngx_http_index_loc_conf_t));
471 return NGX_CONF_OK;
472 }
473
474 index = ngx_array_push(&conf->indices);
475 if (index == NULL) {
476 return NGX_CONF_ERROR;
477 }
478
479 index->len = sizeof(NGX_HTTP_DEFAULT_INDEX) - 1;
480 index->data = (u_char *) NGX_HTTP_DEFAULT_INDEX;
481 conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX);
482
483 return NGX_CONF_OK;
484 }
485
486 #if 0
487
488 if (prev->max_index_len != 0) {
489
490 prev_index = prev->indices.elts;
491 for (i = 0; i < prev->indices.nelts; i++) {
492 index = ngx_array_push(&conf->indices);
493 if (index == NULL) {
494 return NGX_CONF_ERROR;
495 }
496
497 index->len = prev_index[i].len;
498 index->data = prev_index[i].data;
499 }
500 }
501
502 if (conf->max_index_len < prev->max_index_len) {
503 conf->max_index_len = prev->max_index_len;
504 }
505
506 #endif
507
508 if (conf->index_cache == NULL) {
509 conf->index_cache = prev->index_cache;
510 }
511
512 return NGX_CONF_OK;
513 }
514
515
516 /* TODO: warn about duplicate indices */
517
518 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
519 void *conf)
520 {
521 ngx_http_index_loc_conf_t *ilcf = conf;
522
523 ngx_uint_t i;
524 ngx_str_t *index, *value;
525
526 value = cf->args->elts;
527
528 if (value[1].data[0] == '/' && ilcf->indices.nelts == 0) {
529 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
530 "first index \"%V\" in \"%V\" directive "
531 "must not be absolute",
532 &value[1], &cmd->name);
533 return NGX_CONF_ERROR;
534 }
535
536 for (i = 1; i < cf->args->nelts; i++) {
537 if (value[i].len == 0) {
538 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
539 "index \"%V\" in \"%V\" directive is invalid",
540 &value[1], &cmd->name);
541 return NGX_CONF_ERROR;
542 }
543
544 index = ngx_array_push(&ilcf->indices);
545 if (index == NULL) {
546 return NGX_CONF_ERROR;
547 }
548
549 index->len = value[i].len;
550 index->data = value[i].data;
551
552 if (ilcf->max_index_len < index->len + 1) {
553 ilcf->max_index_len = index->len + 1;
554 }
555 }
556
557 return NGX_CONF_OK;
558 }