Mercurial > hg > nginx
comparison src/http/modules/ngx_http_index_handler.c @ 144:ef8c87afcfc5
nginx-0.0.1-2003-10-12-20:49:16 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 12 Oct 2003 16:49:16 +0000 |
parents | cd54bcbaf3b5 |
children | 5afee0074707 |
comparison
equal
deleted
inserted
replaced
143:5526213be452 | 144:ef8c87afcfc5 |
---|---|
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_index_conf_t; | 10 } ngx_http_index_conf_t; |
11 | 11 |
12 | 12 |
13 typedef struct { | |
14 int index; | |
15 unsigned tested:1; | |
16 } ngx_http_index_ctx_t; | |
17 | |
18 | |
13 #define NGX_HTTP_DEFAULT_INDEX "index.html" | 19 #define NGX_HTTP_DEFAULT_INDEX "index.html" |
14 | 20 |
15 | 21 |
16 static int ngx_http_index_test_dir(ngx_http_request_t *r); | 22 static int ngx_http_index_test_dir(ngx_http_request_t *r, |
23 ngx_http_index_ctx_t *ctx); | |
24 static int ngx_http_index_error(ngx_http_request_t *r, | |
25 ngx_http_index_ctx_t *ctx, ngx_err_t err); | |
26 | |
17 static int ngx_http_index_init(ngx_cycle_t *cycle); | 27 static int ngx_http_index_init(ngx_cycle_t *cycle); |
18 static void *ngx_http_index_create_conf(ngx_conf_t *cf); | 28 static void *ngx_http_index_create_conf(ngx_conf_t *cf); |
19 static char *ngx_http_index_merge_conf(ngx_conf_t *cf, | 29 static char *ngx_http_index_merge_conf(ngx_conf_t *cf, |
20 void *parent, void *child); | 30 void *parent, void *child); |
21 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, | 31 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, |
56 NULL /* init child */ | 66 NULL /* init child */ |
57 }; | 67 }; |
58 | 68 |
59 | 69 |
60 /* | 70 /* |
61 Try to open the first index file before the directory existence test | 71 * Try to open the first index file before the test of the directory existence |
62 because the valid requests should be many more than invalid ones. | 72 * because the valid requests should be many more than invalid ones. |
63 If open() failed then stat() should be more quickly because some data | 73 * If open() failed then stat() should be more quickly because some data |
64 is already cached in the kernel. | 74 * is already cached in the kernel. |
65 Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR). | 75 * Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR). |
66 Unix has ENOTDIR error, although it less helpfull - it shows only | 76 * Unix has ENOTDIR error, although it less helpfull - it shows only |
67 that path contains the usual file in place of the directory. | 77 * that path contains the usual file in place of the directory. |
68 */ | 78 */ |
69 | 79 |
70 int ngx_http_index_handler(ngx_http_request_t *r) | 80 int ngx_http_index_handler(ngx_http_request_t *r) |
71 { | 81 { |
72 int i, rc, test_dir, path_not_found; | 82 int i, rc, test_dir, path_not_found; |
73 char *name, *file; | 83 char *name, *file; |
74 ngx_str_t redirect, *index; | 84 ngx_str_t redirect, *index; |
75 ngx_err_t err; | 85 ngx_err_t err; |
76 ngx_fd_t fd; | 86 ngx_fd_t fd; |
87 ngx_http_index_ctx_t *ctx; | |
77 ngx_http_index_conf_t *icf; | 88 ngx_http_index_conf_t *icf; |
78 ngx_http_core_loc_conf_t *clcf; | 89 ngx_http_core_loc_conf_t *clcf; |
79 | 90 |
91 if (r->uri.data[r->uri.len - 1] != '/') { | |
92 return NGX_DECLINED; | |
93 } | |
94 | |
95 ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); | |
96 if (ctx == NULL) { | |
97 ngx_http_create_ctx(r, ctx, ngx_http_index_module, | |
98 sizeof(ngx_http_index_ctx_t), | |
99 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
100 } | |
101 | |
80 icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); | 102 icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); |
81 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 103 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
82 | 104 |
83 ngx_test_null(r->path.data, | 105 if (r->path.data == NULL) { |
84 ngx_palloc(r->pool, | 106 r->path_allocated = clcf->doc_root.len + r->uri.len |
85 clcf->doc_root.len + r->uri.len | 107 + icf->max_index_len; |
86 + icf->max_index_len), | 108 ngx_test_null(r->path.data, |
87 NGX_HTTP_INTERNAL_SERVER_ERROR); | 109 ngx_palloc(r->pool, r->path_allocated), |
88 | 110 NGX_HTTP_INTERNAL_SERVER_ERROR); |
89 redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data, | 111 |
90 clcf->doc_root.len); | 112 redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data, |
91 file = ngx_cpystrn(redirect.data, r->uri.data, r->uri.len + 1); | 113 clcf->doc_root.len); |
92 r->path.len = file - r->path.data; | 114 file = ngx_cpystrn(redirect.data, r->uri.data, r->uri.len + 1); |
93 | 115 r->path.len = file - r->path.data; |
94 test_dir = 1; | 116 |
95 path_not_found = 1; | 117 } else{ |
118 redirect.data = r->path.data + r->path.len; | |
119 file = redirect.data + r->uri.len; | |
120 } | |
96 | 121 |
97 index = icf->indices.elts; | 122 index = icf->indices.elts; |
98 for (i = 0; i < icf->indices.nelts; i++) { | 123 for (/* void */; ctx->index < icf->indices.nelts; ctx->index++) { |
99 | 124 |
100 if (index[i].data[0] != '/') { | 125 if (index[ctx->index].data[0] == '/') { |
101 ngx_memcpy(file, index[i].data, index[i].len + 1); | 126 name = index[ctx->index].data; |
127 | |
128 } else { | |
129 ngx_memcpy(file, index[ctx->index].data, index[ctx->index].len + 1); | |
102 name = r->path.data; | 130 name = r->path.data; |
103 | |
104 } else { | |
105 name = index[i].data; | |
106 } | 131 } |
107 | 132 |
108 fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN); | 133 fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN); |
134 | |
135 if (fd == NGX_AGAIN) { | |
136 return NGX_AGAIN; | |
137 } | |
138 | |
109 if (fd == NGX_INVALID_FILE) { | 139 if (fd == NGX_INVALID_FILE) { |
110 err = ngx_errno; | 140 err = ngx_errno; |
111 | 141 |
112 ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err, | 142 ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err, |
113 "DEBUG: " ngx_open_file_n " %s failed", name); | 143 "DEBUG: " ngx_open_file_n " %s failed", name); |
114 | 144 |
115 if (err == NGX_ENOTDIR) { | 145 if (err == NGX_ENOTDIR) { |
116 path_not_found = 1; | 146 return ngx_http_index_error(r, ctx, err); |
117 | 147 |
118 } else if (err == NGX_EACCES) { | 148 } else if (err == NGX_EACCES) { |
119 r->path_err = err; | 149 return ngx_http_index_error(r, ctx, err); |
120 return NGX_HTTP_FORBIDDEN; | |
121 } | 150 } |
122 | 151 |
123 if (test_dir) { | 152 if (!ctx->tested) { |
124 if (path_not_found) { | 153 rc = ngx_http_index_test_dir(r, ctx); |
125 r->path_err = err; | 154 |
126 return NGX_HTTP_NOT_FOUND; | |
127 } | |
128 | |
129 rc = ngx_http_index_test_dir(r); | |
130 if (rc != NGX_OK) { | 155 if (rc != NGX_OK) { |
131 return rc; | 156 return rc; |
132 } | 157 } |
133 | 158 |
134 test_dir = 0; | 159 ctx->tested = 1; |
135 } | 160 } |
136 | 161 |
137 if (err == NGX_ENOENT) { | 162 if (err == NGX_ENOENT) { |
138 continue; | 163 continue; |
139 } | 164 } |
145 } | 170 } |
146 | 171 |
147 r->file.name.data = name; | 172 r->file.name.data = name; |
148 r->file.fd = fd; | 173 r->file.fd = fd; |
149 | 174 |
150 if (index[i].data[0] == '/') { | 175 if (index[ctx->index].data[0] == '/') { |
151 r->file.name.len = index[i].len; | 176 r->file.name.len = index[ctx->index].len; |
152 redirect.len = index[i].len; | 177 redirect.len = index[ctx->index].len; |
153 redirect.data = index[i].data; | 178 redirect.data = index[ctx->index].data; |
154 | 179 |
155 } else { | 180 } else { |
156 redirect.len = r->uri.len + index[i].len; | 181 redirect.len = r->uri.len + index[ctx->index].len; |
157 r->file.name.len = clcf->doc_root.len + r->uri.len + index[i].len; | 182 r->file.name.len = clcf->doc_root.len + r->uri.len |
183 + index[ctx->index].len; | |
158 } | 184 } |
159 | 185 |
160 return ngx_http_internal_redirect(r, &redirect, NULL); | 186 return ngx_http_internal_redirect(r, &redirect, NULL); |
161 } | 187 } |
162 | 188 |
163 return NGX_DECLINED; | 189 return NGX_DECLINED; |
164 } | 190 } |
165 | 191 |
166 | 192 |
167 static int ngx_http_index_test_dir(ngx_http_request_t *r) | 193 static int ngx_http_index_test_dir(ngx_http_request_t *r, |
168 { | 194 ngx_http_index_ctx_t *ctx) |
195 { | |
196 ngx_err_t err; | |
197 | |
169 r->path.data[r->path.len - 1] = '\0'; | 198 r->path.data[r->path.len - 1] = '\0'; |
170 r->path.data[r->path.len] = '\0'; | 199 r->path.data[r->path.len] = '\0'; |
171 | 200 |
172 ngx_log_debug(r->connection->log, "IS_DIR: %s" _ r->path.data); | 201 ngx_log_debug(r->connection->log, "IS_DIR: %s" _ r->path.data); |
173 | 202 |
174 #if 0 | |
175 if (r->path_err == NGX_EACCES) { | |
176 return NGX_HTTP_FORBIDDEN; | |
177 } | |
178 #endif | |
179 | |
180 if (ngx_file_type(r->path.data, &r->file.info) == -1) { | 203 if (ngx_file_type(r->path.data, &r->file.info) == -1) { |
181 | 204 |
182 r->path_err = ngx_errno; | 205 err = ngx_errno; |
183 | 206 |
184 if (r->path_err == NGX_ENOENT) { | 207 if (err == NGX_ENOENT) { |
185 r->path.data[r->path.len - 1] = '/'; | 208 r->path.data[r->path.len - 1] = '/'; |
186 return NGX_HTTP_NOT_FOUND; | 209 return ngx_http_index_error(r, ctx, err); |
187 } | 210 } |
188 | 211 |
189 ngx_log_error(NGX_LOG_CRIT, r->connection->log, r->path_err, | 212 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, |
190 ngx_file_type_n " %s failed", r->path.data); | 213 ngx_file_type_n " %s failed", r->path.data); |
191 | 214 |
192 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 215 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
193 } | 216 } |
194 | 217 |
195 r->path.data[r->path.len - 1] = '/'; | 218 r->path.data[r->path.len - 1] = '/'; |
196 | 219 |
197 if (ngx_is_dir(r->file.info)) { | 220 if (ngx_is_dir(r->file.info)) { |
198 return NGX_OK; | 221 return NGX_OK; |
199 | 222 } |
200 } else { | 223 |
201 return NGX_HTTP_NOT_FOUND; | 224 /* THINK: not reached ??? */ |
202 } | 225 return ngx_http_index_error(r, ctx, 0); |
226 } | |
227 | |
228 | |
229 static int ngx_http_index_error(ngx_http_request_t *r, | |
230 ngx_http_index_ctx_t *ctx, ngx_err_t err) | |
231 { | |
232 if (err == NGX_EACCES) { | |
233 ngx_log_error(NGX_LOG_ERR, r->connection->log, err, | |
234 "\"%s\" is forbidden", r->path.data); | |
235 | |
236 return NGX_HTTP_FORBIDDEN; | |
237 } | |
238 | |
239 ngx_log_error(NGX_LOG_ERR, r->connection->log, err, | |
240 "\"%s\" is not found", r->path.data); | |
241 return NGX_HTTP_NOT_FOUND; | |
203 } | 242 } |
204 | 243 |
205 | 244 |
206 static int ngx_http_index_init(ngx_cycle_t *cycle) | 245 static int ngx_http_index_init(ngx_cycle_t *cycle) |
207 { | 246 { |
210 ngx_http_core_main_conf_t *cmcf; | 249 ngx_http_core_main_conf_t *cmcf; |
211 | 250 |
212 ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; | 251 ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; |
213 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; | 252 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; |
214 | 253 |
215 ngx_test_null(h, ngx_push_array(&cmcf->index_handlers), NGX_ERROR); | 254 ngx_test_null(h, ngx_push_array( |
216 | 255 &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), |
256 NGX_ERROR); | |
217 *h = ngx_http_index_handler; | 257 *h = ngx_http_index_handler; |
218 | 258 |
219 return NGX_OK; | 259 return NGX_OK; |
220 } | 260 } |
221 | 261 |