blob: bc88fc920da24ddd12394e96034ac697e8849b40 [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#include <ngx_http_config.h>
Igor Sysoev79a80482003-05-14 17:13:13 +00006#include <ngx_http_core_module.h>
Igor Sysoev73009772003-02-06 17:21:13 +00007#include <ngx_http_output_filter.h>
Igor Sysoev0c331d92002-08-15 17:20:26 +00008
Igor Sysoevdc479b42003-03-20 16:09:44 +00009
Igor Sysoev2b542382002-08-20 14:48:28 +000010
Igor Sysoev0c331d92002-08-15 17:20:26 +000011int ngx_http_static_handler(ngx_http_request_t *r)
12{
Igor Sysoev6253ca12003-05-27 12:18:54 +000013 int rc, key, i;
14 ngx_log_e level;
15 ngx_err_t err;
16 ngx_hunk_t *h;
17 ngx_http_type_t *type;
18 ngx_http_log_ctx_t *ctx;
19 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev0c331d92002-08-15 17:20:26 +000020
Igor Sysoev6ddfbf02003-05-15 15:42:53 +000021 rc = ngx_http_discard_body(r);
22
23 if (rc != NGX_OK) {
24 return rc;
25 }
26
Igor Sysoev6253ca12003-05-27 12:18:54 +000027 if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
28 return NGX_HTTP_NOT_ALLOWED;
29 }
30
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000031 ctx = r->connection->log->data;
32 ctx->action = "sending response";
33
Igor Sysoev79a80482003-05-14 17:13:13 +000034 if (r->file.fd == NGX_INVALID_FILE) {
Igor Sysoev42feecb2002-12-15 06:25:09 +000035 r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY);
Igor Sysoevb0869052002-12-10 18:05:12 +000036
Igor Sysoev79a80482003-05-14 17:13:13 +000037 if (r->file.fd == NGX_INVALID_FILE) {
38 err = ngx_errno;
Igor Sysoeve0268b92002-09-11 15:18:33 +000039
Igor Sysoev79a80482003-05-14 17:13:13 +000040 if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
41 level = NGX_LOG_ERR;
42 rc = NGX_HTTP_NOT_FOUND;
Igor Sysoevfd675862003-04-11 16:01:14 +000043
Igor Sysoev79a80482003-05-14 17:13:13 +000044 } else {
45 level = NGX_LOG_CRIT;
46 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
47 }
48
49 ngx_log_error(level, r->connection->log, ngx_errno,
50 ngx_open_file_n " %s failed", r->file.name.data);
51 return rc;
Igor Sysoevfd675862003-04-11 16:01:14 +000052 }
Igor Sysoev2b542382002-08-20 14:48:28 +000053 }
Igor Sysoev0c331d92002-08-15 17:20:26 +000054
Igor Sysoev42feecb2002-12-15 06:25:09 +000055 if (!r->file.info_valid) {
56 if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) {
Igor Sysoev79a80482003-05-14 17:13:13 +000057 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
Igor Sysoev42feecb2002-12-15 06:25:09 +000058 ngx_stat_fd_n " %s failed", r->file.name.data);
59
60 if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
Igor Sysoev79a80482003-05-14 17:13:13 +000061 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
Igor Sysoev42feecb2002-12-15 06:25:09 +000062 ngx_close_file_n " %s failed", r->file.name.data);
63
64 return NGX_HTTP_INTERNAL_SERVER_ERROR;
65 }
66
67 r->file.info_valid = 1;
68 }
69
Igor Sysoev6ddfbf02003-05-15 15:42:53 +000070#if !(WIN32) /* the not regular files are probably Unix specific */
Igor Sysoev42feecb2002-12-15 06:25:09 +000071
72 if (!ngx_is_file(r->file.info)) {
Igor Sysoev79a80482003-05-14 17:13:13 +000073 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
Igor Sysoev42feecb2002-12-15 06:25:09 +000074 "%s is not regular file", r->file.name.data);
Igor Sysoeve0268b92002-09-11 15:18:33 +000075
Igor Sysoev42feecb2002-12-15 06:25:09 +000076 if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
Igor Sysoev79a80482003-05-14 17:13:13 +000077 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
Igor Sysoev42feecb2002-12-15 06:25:09 +000078 ngx_close_file_n " %s failed", r->file.name.data);
79
80 return NGX_HTTP_NOT_FOUND;
Igor Sysoev2b542382002-08-20 14:48:28 +000081 }
Igor Sysoev0c331d92002-08-15 17:20:26 +000082
Igor Sysoev42feecb2002-12-15 06:25:09 +000083#endif
84
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000085 r->headers_out.status = NGX_HTTP_OK;
Igor Sysoev42feecb2002-12-15 06:25:09 +000086 r->headers_out.content_length = ngx_file_size(r->file.info);
87 r->headers_out.last_modified_time = ngx_file_mtime(r->file.info);
Igor Sysoev2b542382002-08-20 14:48:28 +000088
Igor Sysoevb0869052002-12-10 18:05:12 +000089 ngx_test_null(r->headers_out.content_type,
90 ngx_push_table(r->headers_out.headers),
91 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev42feecb2002-12-15 06:25:09 +000092
Igor Sysoev6253ca12003-05-27 12:18:54 +000093 r->headers_out.content_type->key.len = 0;
94 r->headers_out.content_type->key.data = NULL;
95 r->headers_out.content_type->value.len = 0;
96 r->headers_out.content_type->value.data = NULL;
97
98 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevb0869052002-12-10 18:05:12 +000099
Igor Sysoevb0869052002-12-10 18:05:12 +0000100 if (r->exten.len) {
Igor Sysoev79a80482003-05-14 17:13:13 +0000101 ngx_http_types_hash_key(key, r->exten);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000102
Igor Sysoev6253ca12003-05-27 12:18:54 +0000103 type = (ngx_http_type_t *) clcf->types[key].elts;
104 for (i = 0; i < clcf->types[key].nelts; i++) {
Igor Sysoev79a80482003-05-14 17:13:13 +0000105 if (r->exten.len != type[i].exten.len) {
106 continue;
107 }
108
109 if (ngx_strcasecmp(r->exten.data, type[i].exten.data) == 0) {
110 r->headers_out.content_type->value.len = type[i].type.len;
111 r->headers_out.content_type->value.data = type[i].type.data;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000112
113 break;
Igor Sysoev79a80482003-05-14 17:13:13 +0000114 }
115 }
116 }
117
118 if (r->headers_out.content_type->value.len == 0) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000119 r->headers_out.content_type->value.len = clcf->default_type.len;
120 r->headers_out.content_type->value.data = clcf->default_type.data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000121 }
Igor Sysoev2b542382002-08-20 14:48:28 +0000122
Igor Sysoev79a80482003-05-14 17:13:13 +0000123 /* we need to allocate all before the header would be sent */
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000124 ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)),
Igor Sysoev0c331d92002-08-15 17:20:26 +0000125 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000126
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000127 ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)),
128 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000129
Igor Sysoev6253ca12003-05-27 12:18:54 +0000130
131 rc = ngx_http_send_header(r);
132
133 if (r->header_only) {
134 if (rc == NGX_AGAIN) {
135 ngx_http_set_write_handler(r);
136
137 } else {
138 ngx_http_finalize_request(r, 0);
139 }
140
Igor Sysoevd581fd52003-05-13 16:02:32 +0000141 return NGX_OK;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000142 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000143
Igor Sysoev0a9d1452003-02-11 16:42:23 +0000144
Igor Sysoev42feecb2002-12-15 06:25:09 +0000145 h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
Igor Sysoevb7387572003-03-11 20:38:13 +0000146 h->file_pos = 0;
147 h->file_last = ngx_file_size(r->file.info);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000148
149 h->file->fd = r->file.fd;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000150 h->file->log = r->connection->log;
151
152 rc = ngx_http_output_filter(r, h);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000153
Igor Sysoevd581fd52003-05-13 16:02:32 +0000154 if (r->main == NULL) {
155 if (rc == NGX_AGAIN) {
156 ngx_http_set_write_handler(r);
Igor Sysoev42feecb2002-12-15 06:25:09 +0000157
Igor Sysoevd581fd52003-05-13 16:02:32 +0000158 } else {
159 ngx_http_finalize_request(r, 0);
Igor Sysoev0a9d1452003-02-11 16:42:23 +0000160 }
Igor Sysoev0a9d1452003-02-11 16:42:23 +0000161 }
162
Igor Sysoevd581fd52003-05-13 16:02:32 +0000163 return NGX_OK;
Igor Sysoev0c331d92002-08-15 17:20:26 +0000164}