blob: ae1b8170dc8052fc246b8057f72de54351a566f7 [file] [log] [blame]
Igor Sysoev0c331d92002-08-15 17:20:26 +00001
2#include <ngx_config.h>
Igor Sysoevd581fd52003-05-13 16:02:32 +00003#include <ngx_core.h>
Igor Sysoev0c331d92002-08-15 17:20:26 +00004#include <ngx_http.h>
Igor Sysoevdc479b42003-03-20 16:09:44 +00005
Igor Sysoev2b542382002-08-20 14:48:28 +00006
Igor Sysoev865c1502003-11-30 20:03:18 +00007typedef struct {
8 ngx_http_cache_hash_t *redirect_cache;
9} ngx_http_static_loc_conf_t;
10
11
12static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
13static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf);
14static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
15 void *parent, void *child);
16static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle);
Igor Sysoevd404c972003-10-16 20:19:16 +000017
18
19static ngx_command_t ngx_http_static_commands[] = {
20
Igor Sysoev67f88e92004-03-12 16:57:08 +000021#if (NGX_HTTP_CACHE)
22
Igor Sysoev865c1502003-11-30 20:03:18 +000023 { ngx_string("redirect_cache"),
24 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
25 ngx_http_set_cache_slot,
26 NGX_HTTP_LOC_CONF_OFFSET,
27 offsetof(ngx_http_static_loc_conf_t, redirect_cache),
28 NULL },
29
Igor Sysoev67f88e92004-03-12 16:57:08 +000030#endif
31
Igor Sysoev865c1502003-11-30 20:03:18 +000032 ngx_null_command
Igor Sysoevd404c972003-10-16 20:19:16 +000033};
34
35
36
37ngx_http_module_t ngx_http_static_module_ctx = {
Igor Sysoev78329332003-11-10 17:17:31 +000038 NULL, /* pre conf */
39
Igor Sysoevd404c972003-10-16 20:19:16 +000040 NULL, /* create main configuration */
41 NULL, /* init main configuration */
42
43 NULL, /* create server configuration */
44 NULL, /* merge server configuration */
45
Igor Sysoev865c1502003-11-30 20:03:18 +000046 ngx_http_static_create_loc_conf, /* create location configuration */
47 ngx_http_static_merge_loc_conf /* merge location configuration */
Igor Sysoevd404c972003-10-16 20:19:16 +000048};
49
50
51ngx_module_t ngx_http_static_module = {
52 NGX_MODULE,
53 &ngx_http_static_module_ctx, /* module context */
54 ngx_http_static_commands, /* module directives */
55 NGX_HTTP_MODULE, /* module type */
56 ngx_http_static_init, /* init module */
57 NULL /* init child */
58};
59
60
Igor Sysoev865c1502003-11-30 20:03:18 +000061static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
Igor Sysoevd404c972003-10-16 20:19:16 +000062{
Igor Sysoev10a543a2004-03-16 07:10:12 +000063 u_char *last;
Igor Sysoev865c1502003-11-30 20:03:18 +000064 ngx_fd_t fd;
Igor Sysoev54498db2004-02-11 17:08:49 +000065 ngx_int_t rc;
66 ngx_uint_t level;
Igor Sysoev865c1502003-11-30 20:03:18 +000067 ngx_str_t name, location;
68 ngx_err_t err;
69 ngx_log_t *log;
70 ngx_hunk_t *h;
71 ngx_chain_t out;
72 ngx_file_info_t fi;
Igor Sysoev865c1502003-11-30 20:03:18 +000073 ngx_http_cleanup_t *file_cleanup, *redirect_cleanup;
74 ngx_http_log_ctx_t *ctx;
75 ngx_http_core_loc_conf_t *clcf;
76 ngx_http_static_loc_conf_t *slcf;
Igor Sysoev3646a162004-03-14 20:46:25 +000077#if (NGX_HTTP_CACHE)
78 uint32_t file_crc, redirect_crc;
79 ngx_http_cache_t *file, *redirect;
80#endif
Igor Sysoev865c1502003-11-30 20:03:18 +000081
82 if (r->uri.data[r->uri.len - 1] == '/') {
83 return NGX_DECLINED;
84 }
Igor Sysoevd404c972003-10-16 20:19:16 +000085
86 if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
87 return NGX_HTTP_NOT_ALLOWED;
88 }
89
Igor Sysoev865c1502003-11-30 20:03:18 +000090 rc = ngx_http_discard_body(r);
Igor Sysoevd404c972003-10-16 20:19:16 +000091
Igor Sysoev89690bf2004-03-23 06:01:52 +000092 if (rc != NGX_OK && rc != NGX_AGAIN) {
Igor Sysoev865c1502003-11-30 20:03:18 +000093 return rc;
Igor Sysoevd404c972003-10-16 20:19:16 +000094 }
95
Igor Sysoev67f88e92004-03-12 16:57:08 +000096#if (NGX_HTTP_CACHE)
97
Igor Sysoev865c1502003-11-30 20:03:18 +000098 /*
Igor Sysoev7af6b162004-02-09 07:46:43 +000099 * there is a valid cached open file, i.e by the index handler,
100 * and it should be already registered in r->cleanup
Igor Sysoev865c1502003-11-30 20:03:18 +0000101 */
Igor Sysoevc2bba092003-11-28 17:41:47 +0000102
Igor Sysoev4fc368f2003-12-01 16:28:14 +0000103 if (r->cache && !r->cache->expired) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000104 return ngx_http_send_cached(r);
105 }
106
Igor Sysoev67f88e92004-03-12 16:57:08 +0000107#endif
108
Igor Sysoev865c1502003-11-30 20:03:18 +0000109 log = r->connection->log;
110
111 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
112
113 /*
Igor Sysoev7af6b162004-02-09 07:46:43 +0000114 * make a file name, reserve 2 bytes for a trailing '/'
115 * in a possible redirect and for the last '\0'
Igor Sysoev865c1502003-11-30 20:03:18 +0000116 */
117
Igor Sysoev10a543a2004-03-16 07:10:12 +0000118 name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2
119 - clcf->alias * clcf->name.len);
Igor Sysoev7af6b162004-02-09 07:46:43 +0000120 if (name.data == NULL) {
121 return NGX_HTTP_INTERNAL_SERVER_ERROR;
122 }
Igor Sysoevd404c972003-10-16 20:19:16 +0000123
Igor Sysoev10a543a2004-03-16 07:10:12 +0000124 location.data = ngx_cpymem(name.data, clcf->root.data, clcf->root.len);
125
126 if (clcf->alias) {
127 last = ngx_cpystrn(location.data, r->uri.data + clcf->name.len,
128 r->uri.len + 1 - clcf->name.len);
129
130 /*
131 * aliases usually have trailling "/",
132 * set it in the start of the possible redirect
133 */
134
135 if (*location.data != '/') {
136 location.data--;
137 }
138
139 } else {
140 last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
141 }
142
Igor Sysoev865c1502003-11-30 20:03:18 +0000143 name.len = last - name.data;
144 location.len = last - location.data + 1;
Igor Sysoevd404c972003-10-16 20:19:16 +0000145
Igor Sysoev865c1502003-11-30 20:03:18 +0000146 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
147 "http filename: \"%s\"", name.data);
Igor Sysoevd404c972003-10-16 20:19:16 +0000148
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000149
Igor Sysoev865c1502003-11-30 20:03:18 +0000150 /* allocate cleanups */
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000151
Igor Sysoev865c1502003-11-30 20:03:18 +0000152 if (!(file_cleanup = ngx_push_array(&r->cleanup))) {
153 return NGX_HTTP_INTERNAL_SERVER_ERROR;
154 }
155 file_cleanup->valid = 0;
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000156
Igor Sysoev865c1502003-11-30 20:03:18 +0000157 slcf = ngx_http_get_module_loc_conf(r, ngx_http_static_module);
158 if (slcf->redirect_cache) {
159 if (!(redirect_cleanup = ngx_push_array(&r->cleanup))) {
160 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000161 }
Igor Sysoev865c1502003-11-30 20:03:18 +0000162 redirect_cleanup->valid = 0;
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000163
164 } else {
Igor Sysoev865c1502003-11-30 20:03:18 +0000165 redirect_cleanup = NULL;
Igor Sysoeva8fa0a62003-11-25 20:44:56 +0000166 }
167
Igor Sysoev67f88e92004-03-12 16:57:08 +0000168#if (NGX_HTTP_CACHE)
Igor Sysoevc2bba092003-11-28 17:41:47 +0000169
Igor Sysoev865c1502003-11-30 20:03:18 +0000170 /* look up an open files cache */
171
172 if (clcf->open_files) {
173 file = ngx_http_cache_get(clcf->open_files, file_cleanup,
174 &name, &file_crc);
175
176 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
177 "http open file cache get: " PTR_FMT, file);
178
Igor Sysoev4fc368f2003-12-01 16:28:14 +0000179 if (file && !file->expired) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000180 r->cache = file;
181 return ngx_http_send_cached(r);
182 }
183
184 } else {
185 file = NULL;
186 }
187
188
189 /* look up an redirect cache */
190
191 if (slcf->redirect_cache) {
192 redirect = ngx_http_cache_get(slcf->redirect_cache, redirect_cleanup,
193 &name, &redirect_crc);
194
195 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
196 "http redirect cache get: " PTR_FMT, redirect);
197
Igor Sysoev4fc368f2003-12-01 16:28:14 +0000198 if (redirect && !redirect->expired) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000199
200 /*
201 * We do not copy a cached value so the cache entry is locked
202 * until the end of the request. In a single threaded model
203 * the redirected request should complete before other event
204 * will be processed. In a multithreaded model this locking
205 * should keep more popular redirects in cache.
206 */
207
208 if (!(r->headers_out.location =
209 ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
210 {
211 return NGX_HTTP_INTERNAL_SERVER_ERROR;
212 }
213
214 r->headers_out.location->value = redirect->data.value;
215
216 return NGX_HTTP_MOVED_PERMANENTLY;
217 }
218
219 } else {
220 redirect = NULL;
221 }
222
Igor Sysoev67f88e92004-03-12 16:57:08 +0000223#endif
Igor Sysoev865c1502003-11-30 20:03:18 +0000224
225 /* open file */
226
Igor Sysoevd404c972003-10-16 20:19:16 +0000227#if (WIN9X)
228
Igor Sysoev865c1502003-11-30 20:03:18 +0000229 /* TODO: redirect cache */
230
Igor Sysoev45890ea2003-11-13 16:16:33 +0000231 if (ngx_win32_version < NGX_WIN_NT) {
Igor Sysoevd404c972003-10-16 20:19:16 +0000232
Igor Sysoev45890ea2003-11-13 16:16:33 +0000233 /*
Igor Sysoev297c0482003-11-14 16:52:04 +0000234 * there is no way to open a file or a directory in Win9X with
235 * one syscall because Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag
236 * so we need to check its type before the opening
Igor Sysoev45890ea2003-11-13 16:16:33 +0000237 */
Igor Sysoevd404c972003-10-16 20:19:16 +0000238
Igor Sysoev865c1502003-11-30 20:03:18 +0000239 if (ngx_file_info(name.data, &fi) == NGX_FILE_ERROR) {
Igor Sysoev45890ea2003-11-13 16:16:33 +0000240 err = ngx_errno;
Igor Sysoev865c1502003-11-30 20:03:18 +0000241 ngx_log_error(NGX_LOG_ERR, log, err,
Igor Sysoevc2bba092003-11-28 17:41:47 +0000242 ngx_file_info_n " \"%s\" failed", name.data);
Igor Sysoevd404c972003-10-16 20:19:16 +0000243
Igor Sysoev45890ea2003-11-13 16:16:33 +0000244 if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
245 return NGX_HTTP_NOT_FOUND;
Igor Sysoevd404c972003-10-16 20:19:16 +0000246
Igor Sysoev45890ea2003-11-13 16:16:33 +0000247 } else if (err == NGX_EACCES) {
248 return NGX_HTTP_FORBIDDEN;
249
250 } else {
251 return NGX_HTTP_INTERNAL_SERVER_ERROR;
252 }
253 }
254
Igor Sysoev865c1502003-11-30 20:03:18 +0000255 if (ngx_is_dir(&fi)) {
256 ngx_log_debug(log, "HTTP DIR: '%s'" _ name.data);
Igor Sysoev45890ea2003-11-13 16:16:33 +0000257
258 if (!(r->headers_out.location =
259 ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
260 {
261 return NGX_HTTP_INTERNAL_SERVER_ERROR;
262 }
263
264 *last++ = '/';
265 *last = '\0';
Igor Sysoev45890ea2003-11-13 16:16:33 +0000266 r->headers_out.location->value.len = last - location;
267 r->headers_out.location->value.data = location;
268
269 return NGX_HTTP_MOVED_PERMANENTLY;
Igor Sysoevd404c972003-10-16 20:19:16 +0000270 }
271 }
272
Igor Sysoev45890ea2003-11-13 16:16:33 +0000273#endif
Igor Sysoevd404c972003-10-16 20:19:16 +0000274
Igor Sysoevc2bba092003-11-28 17:41:47 +0000275
Igor Sysoev865c1502003-11-30 20:03:18 +0000276 fd = ngx_open_file(name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
Igor Sysoevd404c972003-10-16 20:19:16 +0000277
Igor Sysoev865c1502003-11-30 20:03:18 +0000278 if (fd == NGX_INVALID_FILE) {
Igor Sysoevd404c972003-10-16 20:19:16 +0000279 err = ngx_errno;
Igor Sysoevd404c972003-10-16 20:19:16 +0000280
281 if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
Igor Sysoev65977492003-11-02 22:56:18 +0000282 level = NGX_LOG_ERR;
283 rc = NGX_HTTP_NOT_FOUND;
Igor Sysoevd404c972003-10-16 20:19:16 +0000284
285 } else if (err == NGX_EACCES) {
Igor Sysoev65977492003-11-02 22:56:18 +0000286 level = NGX_LOG_ERR;
287 rc = NGX_HTTP_FORBIDDEN;
Igor Sysoevd404c972003-10-16 20:19:16 +0000288
289 } else {
Igor Sysoev65977492003-11-02 22:56:18 +0000290 level = NGX_LOG_CRIT;
291 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoevd404c972003-10-16 20:19:16 +0000292 }
Igor Sysoev65977492003-11-02 22:56:18 +0000293
Igor Sysoev865c1502003-11-30 20:03:18 +0000294 ngx_log_error(level, log, err,
295 ngx_open_file_n " \"%s\" failed", name.data);
Igor Sysoev65977492003-11-02 22:56:18 +0000296
297 return rc;
Igor Sysoevd404c972003-10-16 20:19:16 +0000298 }
299
Igor Sysoev865c1502003-11-30 20:03:18 +0000300 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", fd);
Igor Sysoevd404c972003-10-16 20:19:16 +0000301
Igor Sysoev865c1502003-11-30 20:03:18 +0000302 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
303 ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
304 ngx_fd_info_n " \"%s\" failed", name.data);
Igor Sysoevd404c972003-10-16 20:19:16 +0000305
Igor Sysoev865c1502003-11-30 20:03:18 +0000306 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
307 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
308 ngx_close_file_n " \"%s\" failed", name.data);
Igor Sysoevd404c972003-10-16 20:19:16 +0000309 }
310
Igor Sysoev865c1502003-11-30 20:03:18 +0000311 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoevd404c972003-10-16 20:19:16 +0000312 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000313
Igor Sysoev865c1502003-11-30 20:03:18 +0000314 if (ngx_is_dir(&fi)) {
315
316 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
317
318 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
319 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
320 ngx_close_file_n " \"%s\" failed", name.data);
Igor Sysoev0e499db2003-11-27 07:45:22 +0000321 }
322
Igor Sysoev865c1502003-11-30 20:03:18 +0000323 *last++ = '/';
324 *last = '\0';
Igor Sysoevd404c972003-10-16 20:19:16 +0000325
Igor Sysoev14be46e2003-10-29 17:39:05 +0000326 if (!(r->headers_out.location =
327 ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
328 {
329 return NGX_HTTP_INTERNAL_SERVER_ERROR;
330 }
Igor Sysoevd404c972003-10-16 20:19:16 +0000331
Igor Sysoev865c1502003-11-30 20:03:18 +0000332 r->headers_out.location->value = location;
333
Igor Sysoev67f88e92004-03-12 16:57:08 +0000334#if (NGX_HTTP_CACHE)
335
Igor Sysoev865c1502003-11-30 20:03:18 +0000336 if (slcf->redirect_cache) {
337 if (redirect) {
338 if (location.len == redirect->data.value.len
339 && ngx_memcmp(redirect->data.value.data, location.data,
340 location.len) == 0)
341 {
342 redirect->accessed = ngx_cached_time;
343 redirect->updated = ngx_cached_time;
344
345 /*
346 * we can unlock the cache entry because
347 * we have the local copy anyway
348 */
349
350 ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
351 redirect_cleanup->valid = 0;
352
353 return NGX_HTTP_MOVED_PERMANENTLY;
354 }
355 }
356
357 location.len++;
358 redirect = ngx_http_cache_alloc(slcf->redirect_cache, redirect,
359 redirect_cleanup,
360 &name, redirect_crc,
361 &location, log);
362 location.len--;
363
364 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
365 "http redirect cache alloc: " PTR_FMT, redirect);
366
367 if (redirect) {
368 redirect->fd = NGX_INVALID_FILE;
369 redirect->accessed = ngx_cached_time;
370 redirect->last_modified = 0;
371 redirect->updated = ngx_cached_time;
Igor Sysoev865c1502003-11-30 20:03:18 +0000372 redirect->memory = 1;
373 ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
374 redirect_cleanup->valid = 0;
375 }
376
377 }
Igor Sysoevd404c972003-10-16 20:19:16 +0000378
Igor Sysoev67f88e92004-03-12 16:57:08 +0000379#endif
380
Igor Sysoevd404c972003-10-16 20:19:16 +0000381 return NGX_HTTP_MOVED_PERMANENTLY;
382 }
383
Igor Sysoev74e95c22003-11-09 20:03:38 +0000384#if !(WIN32) /* the not regular files are probably Unix specific */
385
Igor Sysoev865c1502003-11-30 20:03:18 +0000386 if (!ngx_is_file(&fi)) {
387 ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
388 "%s is not a regular file", name.data);
Igor Sysoev74e95c22003-11-09 20:03:38 +0000389
Igor Sysoev865c1502003-11-30 20:03:18 +0000390 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
391 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
392 ngx_close_file_n " \"%s\" failed", name.data);
393 }
Igor Sysoev74e95c22003-11-09 20:03:38 +0000394
395 return NGX_HTTP_NOT_FOUND;
396 }
397
398#endif
Igor Sysoev74e95c22003-11-09 20:03:38 +0000399
Igor Sysoevd404c972003-10-16 20:19:16 +0000400
Igor Sysoev67f88e92004-03-12 16:57:08 +0000401#if (NGX_HTTP_CACHE)
402
Igor Sysoev865c1502003-11-30 20:03:18 +0000403 if (clcf->open_files) {
Igor Sysoevd404c972003-10-16 20:19:16 +0000404
Igor Sysoev865c1502003-11-30 20:03:18 +0000405#if (NGX_USE_HTTP_FILE_CACHE_UNIQ)
Igor Sysoevd404c972003-10-16 20:19:16 +0000406
Igor Sysoev865c1502003-11-30 20:03:18 +0000407 if (file && file->uniq == ngx_file_uniq(&fi)) {
408 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
409 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
410 ngx_close_file_n " \"%s\" failed", name.data);
411 }
412 file->accessed = ngx_cached_time;
413 file->updated = ngx_cached_time;
Igor Sysoev4fc368f2003-12-01 16:28:14 +0000414 file->expired = 0;
Igor Sysoev865c1502003-11-30 20:03:18 +0000415 r->cache = file;
Igor Sysoev0c331d92002-08-15 17:20:26 +0000416
Igor Sysoev865c1502003-11-30 20:03:18 +0000417 return ngx_http_send_cached(r);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000418
Igor Sysoev865c1502003-11-30 20:03:18 +0000419 } else {
420 if (file) {
421 ngx_http_cache_unlock(clcf->open_files, file, log);
422 file = NULL;
423 }
424
425 file = ngx_http_cache_alloc(clcf->open_files, file,
426 file_cleanup,
427 &name, file_crc, NULL, log);
428 if (file) {
429 file->uniq = ngx_file_uniq(&fi);
430 }
431 }
432
433#else
434 file = ngx_http_cache_alloc(clcf->open_files, file,
435 file_cleanup,
436 &name, file_crc, NULL, log);
437#endif
438
439 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
440 "http open file cache alloc: " PTR_FMT, file);
441
442 if (file) {
443 file->fd = fd;
444 file->data.size = ngx_file_size(&fi);
445 file->accessed = ngx_cached_time;
446 file->last_modified = ngx_file_mtime(&fi);
447 file->updated = ngx_cached_time;
Igor Sysoev865c1502003-11-30 20:03:18 +0000448 r->cache = file;
449 }
450
451 return ngx_http_send_cached(r);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000452 }
453
Igor Sysoev67f88e92004-03-12 16:57:08 +0000454#endif
Igor Sysoev865c1502003-11-30 20:03:18 +0000455
456 ctx = log->data;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000457 ctx->action = "sending response to client";
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000458
Igor Sysoev865c1502003-11-30 20:03:18 +0000459 file_cleanup->data.file.fd = fd;
460 file_cleanup->data.file.name = name.data;
461 file_cleanup->valid = 1;
462 file_cleanup->cache = 0;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000463
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000464 r->headers_out.status = NGX_HTTP_OK;
Igor Sysoev865c1502003-11-30 20:03:18 +0000465 r->headers_out.content_length_n = ngx_file_size(&fi);
466 r->headers_out.last_modified_time = ngx_file_mtime(&fi);
Igor Sysoev2b542382002-08-20 14:48:28 +0000467
Igor Sysoev865c1502003-11-30 20:03:18 +0000468 if (ngx_http_set_content_type(r) != NGX_OK) {
Igor Sysoev14be46e2003-10-29 17:39:05 +0000469 return NGX_HTTP_INTERNAL_SERVER_ERROR;
470 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000471
Igor Sysoev2b542382002-08-20 14:48:28 +0000472
Igor Sysoev79a80482003-05-14 17:13:13 +0000473 /* we need to allocate all before the header would be sent */
Igor Sysoev1342d9c2003-10-09 07:00:45 +0000474
Igor Sysoev865c1502003-11-30 20:03:18 +0000475 if (!(h = ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)))) {
476 return NGX_HTTP_INTERNAL_SERVER_ERROR;
477 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000478
Igor Sysoev865c1502003-11-30 20:03:18 +0000479 if (!(h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)))) {
480 return NGX_HTTP_INTERNAL_SERVER_ERROR;
481 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000482
Igor Sysoev6253ca12003-05-27 12:18:54 +0000483 rc = ngx_http_send_header(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000484
485 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
486 return rc;
Igor Sysoev7578ec92003-06-02 15:24:30 +0000487 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000488
Igor Sysoev1342d9c2003-10-09 07:00:45 +0000489 h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
Igor Sysoev1342d9c2003-10-09 07:00:45 +0000490
Igor Sysoevb7387572003-03-11 20:38:13 +0000491 h->file_pos = 0;
Igor Sysoev865c1502003-11-30 20:03:18 +0000492 h->file_last = ngx_file_size(&fi);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000493
Igor Sysoev865c1502003-11-30 20:03:18 +0000494 h->file->fd = fd;
495 h->file->log = log;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000496
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000497 out.hunk = h;
498 out.next = NULL;
499
500 return ngx_http_output_filter(r, &out);
Igor Sysoev0c331d92002-08-15 17:20:26 +0000501}
Igor Sysoevd404c972003-10-16 20:19:16 +0000502
503
Igor Sysoev865c1502003-11-30 20:03:18 +0000504static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf)
505{
506 ngx_http_static_loc_conf_t *conf;
507
508 if (!(conf = ngx_palloc(cf->pool, sizeof(ngx_http_static_loc_conf_t)))) {
509 return NGX_CONF_ERROR;
510 }
511
512 conf->redirect_cache = NULL;
513
514 return conf;
515}
516
517
518static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
519 void *parent, void *child)
520{
521 ngx_http_static_loc_conf_t *prev = parent;
522 ngx_http_static_loc_conf_t *conf = child;
523
524 if (conf->redirect_cache == NULL) {
525 conf->redirect_cache = prev->redirect_cache;
526 }
527
528 return NGX_CONF_OK;
529}
530
531
532static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle)
Igor Sysoevd404c972003-10-16 20:19:16 +0000533{
534 ngx_http_handler_pt *h;
535 ngx_http_conf_ctx_t *ctx;
536 ngx_http_core_main_conf_t *cmcf;
537
538 ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
539 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
540
Igor Sysoev865c1502003-11-30 20:03:18 +0000541 h = ngx_push_array(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
542 if (h == NULL) {
543 return NGX_ERROR;
544 }
545
546 *h = ngx_http_static_handler;
Igor Sysoevd404c972003-10-16 20:19:16 +0000547
548 return NGX_OK;
549}