Igor Sysoev | 0c331d9 | 2002-08-15 17:20:26 +0000 | [diff] [blame] | 1 | |
| 2 | #include <ngx_config.h> |
Igor Sysoev | d581fd5 | 2003-05-13 16:02:32 +0000 | [diff] [blame] | 3 | #include <ngx_core.h> |
Igor Sysoev | 0c331d9 | 2002-08-15 17:20:26 +0000 | [diff] [blame] | 4 | #include <ngx_http.h> |
Igor Sysoev | dc479b4 | 2003-03-20 16:09:44 +0000 | [diff] [blame] | 5 | |
Igor Sysoev | 2b54238 | 2002-08-20 14:48:28 +0000 | [diff] [blame] | 6 | |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 7 | static int ngx_http_static_handler(ngx_http_request_t *r); |
| 8 | static int ngx_http_static_init(ngx_cycle_t *cycle); |
| 9 | |
| 10 | |
| 11 | static ngx_command_t ngx_http_static_commands[] = { |
| 12 | |
| 13 | ngx_null_command |
| 14 | }; |
| 15 | |
| 16 | |
| 17 | |
| 18 | ngx_http_module_t ngx_http_static_module_ctx = { |
Igor Sysoev | 7832933 | 2003-11-10 17:17:31 +0000 | [diff] [blame] | 19 | NULL, /* pre conf */ |
| 20 | |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 21 | NULL, /* create main configuration */ |
| 22 | NULL, /* init main configuration */ |
| 23 | |
| 24 | NULL, /* create server configuration */ |
| 25 | NULL, /* merge server configuration */ |
| 26 | |
| 27 | NULL, /* create location configuration */ |
| 28 | NULL /* merge location configuration */ |
| 29 | }; |
| 30 | |
| 31 | |
| 32 | ngx_module_t ngx_http_static_module = { |
| 33 | NGX_MODULE, |
| 34 | &ngx_http_static_module_ctx, /* module context */ |
| 35 | ngx_http_static_commands, /* module directives */ |
| 36 | NGX_HTTP_MODULE, /* module type */ |
| 37 | ngx_http_static_init, /* init module */ |
| 38 | NULL /* init child */ |
| 39 | }; |
| 40 | |
| 41 | |
| 42 | int ngx_http_static_translate_handler(ngx_http_request_t *r) |
| 43 | { |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 44 | int rc, level; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 45 | char *location, *last; |
| 46 | ngx_err_t err; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 47 | ngx_http_core_loc_conf_t *clcf; |
| 48 | |
| 49 | if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { |
| 50 | return NGX_HTTP_NOT_ALLOWED; |
| 51 | } |
| 52 | |
| 53 | clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
| 54 | |
| 55 | if (r->uri.data[r->uri.len - 1] == '/') { |
| 56 | if (r->path.data == NULL) { |
| 57 | ngx_test_null(r->path.data, |
| 58 | ngx_palloc(r->pool, |
| 59 | clcf->doc_root.len + r->uri.len), |
| 60 | NGX_HTTP_INTERNAL_SERVER_ERROR); |
| 61 | |
| 62 | ngx_cpystrn(ngx_cpymem(r->path.data, clcf->doc_root.data, |
| 63 | clcf->doc_root.len), |
| 64 | r->uri.data, r->uri.len + 1); |
| 65 | |
| 66 | } else { |
| 67 | r->path.data[r->path.len] = '\0'; |
| 68 | } |
| 69 | |
| 70 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
| 71 | "directory index of \"%s\" is forbidden", r->path.data); |
| 72 | |
| 73 | return NGX_HTTP_FORBIDDEN; |
| 74 | } |
| 75 | |
| 76 | /* "+ 2" is for trailing '/' in redirect and '\0' */ |
| 77 | ngx_test_null(r->file.name.data, |
| 78 | ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2), |
| 79 | NGX_HTTP_INTERNAL_SERVER_ERROR); |
| 80 | |
| 81 | location = ngx_cpymem(r->file.name.data, clcf->doc_root.data, |
| 82 | clcf->doc_root.len), |
| 83 | |
| 84 | last = ngx_cpystrn(location, r->uri.data, r->uri.len + 1); |
| 85 | |
| 86 | ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data); |
| 87 | |
| 88 | #if (WIN9X) |
| 89 | |
Igor Sysoev | 45890ea | 2003-11-13 16:16:33 +0000 | [diff] [blame^] | 90 | if (ngx_win32_version < NGX_WIN_NT) { |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 91 | |
Igor Sysoev | 45890ea | 2003-11-13 16:16:33 +0000 | [diff] [blame^] | 92 | /* |
| 93 | * There is no way to open a file or a directory in Win9X with |
| 94 | * one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag. |
| 95 | * So we need to check its type before the opening. |
| 96 | */ |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 97 | |
Igor Sysoev | 45890ea | 2003-11-13 16:16:33 +0000 | [diff] [blame^] | 98 | r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data); |
| 99 | if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { |
| 100 | err = ngx_errno; |
| 101 | ngx_log_error(NGX_LOG_ERR, r->connection->log, err, |
| 102 | ngx_file_type_n " \"%s\" failed", r->file.name.data); |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 103 | |
Igor Sysoev | 45890ea | 2003-11-13 16:16:33 +0000 | [diff] [blame^] | 104 | if (err == NGX_ENOENT || err == NGX_ENOTDIR) { |
| 105 | return NGX_HTTP_NOT_FOUND; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 106 | |
Igor Sysoev | 45890ea | 2003-11-13 16:16:33 +0000 | [diff] [blame^] | 107 | } else if (err == NGX_EACCES) { |
| 108 | return NGX_HTTP_FORBIDDEN; |
| 109 | |
| 110 | } else { |
| 111 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | if (ngx_is_dir(r->file.info)) { |
| 116 | ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); |
| 117 | |
| 118 | if (!(r->headers_out.location = |
| 119 | ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) |
| 120 | { |
| 121 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 122 | } |
| 123 | |
| 124 | *last++ = '/'; |
| 125 | *last = '\0'; |
| 126 | r->headers_out.location->key.len = 8; |
| 127 | r->headers_out.location->key.data = "Location" ; |
| 128 | r->headers_out.location->value.len = last - location; |
| 129 | r->headers_out.location->value.data = location; |
| 130 | |
| 131 | return NGX_HTTP_MOVED_PERMANENTLY; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 132 | } |
| 133 | } |
| 134 | |
Igor Sysoev | 45890ea | 2003-11-13 16:16:33 +0000 | [diff] [blame^] | 135 | #endif |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 136 | |
| 137 | if (r->file.fd == NGX_INVALID_FILE) { |
| 138 | r->file.fd = ngx_open_file(r->file.name.data, |
| 139 | NGX_FILE_RDONLY, NGX_FILE_OPEN); |
| 140 | } |
| 141 | |
| 142 | if (r->file.fd == NGX_INVALID_FILE) { |
| 143 | err = ngx_errno; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 144 | |
| 145 | if (err == NGX_ENOENT || err == NGX_ENOTDIR) { |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 146 | level = NGX_LOG_ERR; |
| 147 | rc = NGX_HTTP_NOT_FOUND; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 148 | |
| 149 | } else if (err == NGX_EACCES) { |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 150 | level = NGX_LOG_ERR; |
| 151 | rc = NGX_HTTP_FORBIDDEN; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 152 | |
| 153 | } else { |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 154 | level = NGX_LOG_CRIT; |
| 155 | rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 156 | } |
Igor Sysoev | 6597749 | 2003-11-02 22:56:18 +0000 | [diff] [blame] | 157 | |
| 158 | ngx_log_error(level, r->connection->log, ngx_errno, |
| 159 | ngx_open_file_n " \"%s\" failed", r->file.name.data); |
| 160 | |
| 161 | return rc; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd); |
| 165 | |
| 166 | if (!r->file.info_valid) { |
| 167 | if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { |
| 168 | ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, |
| 169 | ngx_stat_fd_n " \"%s\" failed", r->file.name.data); |
| 170 | |
| 171 | if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { |
| 172 | ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, |
| 173 | ngx_close_file_n " \"%s\" failed", |
| 174 | r->file.name.data); |
| 175 | } |
| 176 | |
| 177 | r->file.fd = NGX_INVALID_FILE; |
| 178 | |
| 179 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 180 | } |
| 181 | |
| 182 | r->file.info_valid = 1; |
| 183 | } |
Igor Sysoev | 10fc9ef | 2003-10-27 08:53:49 +0000 | [diff] [blame] | 184 | |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 185 | if (ngx_is_dir(r->file.info)) { |
| 186 | ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); |
| 187 | |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 188 | if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { |
| 189 | ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, |
| 190 | ngx_close_file_n " \"%s\" failed", r->file.name.data); |
| 191 | } |
| 192 | |
| 193 | r->file.fd = NGX_INVALID_FILE; |
Igor Sysoev | 10fc9ef | 2003-10-27 08:53:49 +0000 | [diff] [blame] | 194 | r->file.info_valid = 0; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 195 | |
Igor Sysoev | 14be46e | 2003-10-29 17:39:05 +0000 | [diff] [blame] | 196 | if (!(r->headers_out.location = |
| 197 | ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) |
| 198 | { |
| 199 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 200 | } |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 201 | |
| 202 | *last++ = '/'; |
| 203 | *last = '\0'; |
Igor Sysoev | 14be46e | 2003-10-29 17:39:05 +0000 | [diff] [blame] | 204 | r->headers_out.location->key.len = 8; |
| 205 | r->headers_out.location->key.data = "Location" ; |
| 206 | r->headers_out.location->value.len = last - location; |
| 207 | r->headers_out.location->value.data = location; |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 208 | |
| 209 | return NGX_HTTP_MOVED_PERMANENTLY; |
| 210 | } |
| 211 | |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 212 | #if !(WIN32) /* the not regular files are probably Unix specific */ |
| 213 | |
| 214 | if (!ngx_is_file(r->file.info)) { |
| 215 | ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, |
| 216 | "%s is not a regular file", r->file.name.data); |
| 217 | |
| 218 | if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) |
| 219 | ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, |
| 220 | ngx_close_file_n " %s failed", r->file.name.data); |
| 221 | |
| 222 | return NGX_HTTP_NOT_FOUND; |
| 223 | } |
| 224 | |
| 225 | #endif |
Igor Sysoev | 74e95c2 | 2003-11-09 20:03:38 +0000 | [diff] [blame] | 226 | |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 227 | r->content_handler = ngx_http_static_handler; |
| 228 | |
| 229 | return NGX_OK; |
| 230 | } |
| 231 | |
| 232 | |
| 233 | static int ngx_http_static_handler(ngx_http_request_t *r) |
Igor Sysoev | 0c331d9 | 2002-08-15 17:20:26 +0000 | [diff] [blame] | 234 | { |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 235 | int rc, key, i; |
| 236 | ngx_log_e level; |
| 237 | ngx_err_t err; |
| 238 | ngx_hunk_t *h; |
Igor Sysoev | 419f9ac | 2003-10-21 16:49:56 +0000 | [diff] [blame] | 239 | ngx_chain_t out; |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 240 | ngx_http_type_t *type; |
| 241 | ngx_http_log_ctx_t *ctx; |
| 242 | ngx_http_core_loc_conf_t *clcf; |
Igor Sysoev | 0c331d9 | 2002-08-15 17:20:26 +0000 | [diff] [blame] | 243 | |
Igor Sysoev | 6ddfbf0 | 2003-05-15 15:42:53 +0000 | [diff] [blame] | 244 | rc = ngx_http_discard_body(r); |
| 245 | |
| 246 | if (rc != NGX_OK) { |
| 247 | return rc; |
| 248 | } |
| 249 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 250 | ctx = r->connection->log->data; |
Igor Sysoev | 10fc9ef | 2003-10-27 08:53:49 +0000 | [diff] [blame] | 251 | ctx->action = "sending response to client"; |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 252 | |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 253 | if (r->file.fd == NGX_INVALID_FILE) { |
Igor Sysoev | 7578ec9 | 2003-06-02 15:24:30 +0000 | [diff] [blame] | 254 | r->file.fd = ngx_open_file(r->file.name.data, |
| 255 | NGX_FILE_RDONLY, NGX_FILE_OPEN); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 256 | |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 257 | if (r->file.fd == NGX_INVALID_FILE) { |
| 258 | err = ngx_errno; |
Igor Sysoev | e0268b9 | 2002-09-11 15:18:33 +0000 | [diff] [blame] | 259 | |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 260 | if (err == NGX_ENOENT || err == NGX_ENOTDIR) { |
| 261 | level = NGX_LOG_ERR; |
| 262 | rc = NGX_HTTP_NOT_FOUND; |
Igor Sysoev | fd67586 | 2003-04-11 16:01:14 +0000 | [diff] [blame] | 263 | |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 264 | } else { |
| 265 | level = NGX_LOG_CRIT; |
| 266 | rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 267 | } |
| 268 | |
| 269 | ngx_log_error(level, r->connection->log, ngx_errno, |
| 270 | ngx_open_file_n " %s failed", r->file.name.data); |
| 271 | return rc; |
Igor Sysoev | fd67586 | 2003-04-11 16:01:14 +0000 | [diff] [blame] | 272 | } |
Igor Sysoev | 2b54238 | 2002-08-20 14:48:28 +0000 | [diff] [blame] | 273 | } |
Igor Sysoev | 0c331d9 | 2002-08-15 17:20:26 +0000 | [diff] [blame] | 274 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 275 | if (!r->file.info_valid) { |
| 276 | if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 277 | ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 278 | ngx_stat_fd_n " %s failed", r->file.name.data); |
| 279 | |
| 280 | if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 281 | ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 282 | ngx_close_file_n " %s failed", r->file.name.data); |
| 283 | |
| 284 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 285 | } |
| 286 | |
| 287 | r->file.info_valid = 1; |
| 288 | } |
| 289 | |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 290 | r->headers_out.status = NGX_HTTP_OK; |
Igor Sysoev | 419f9ac | 2003-10-21 16:49:56 +0000 | [diff] [blame] | 291 | r->headers_out.content_length_n = ngx_file_size(r->file.info); |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 292 | r->headers_out.last_modified_time = ngx_file_mtime(r->file.info); |
Igor Sysoev | 2b54238 | 2002-08-20 14:48:28 +0000 | [diff] [blame] | 293 | |
Igor Sysoev | 14be46e | 2003-10-29 17:39:05 +0000 | [diff] [blame] | 294 | if (!(r->headers_out.content_type = |
| 295 | ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) |
| 296 | { |
| 297 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
| 298 | } |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 299 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 300 | r->headers_out.content_type->key.len = 0; |
| 301 | r->headers_out.content_type->key.data = NULL; |
| 302 | r->headers_out.content_type->value.len = 0; |
| 303 | r->headers_out.content_type->value.data = NULL; |
| 304 | |
| 305 | clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 306 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 307 | if (r->exten.len) { |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 308 | ngx_http_types_hash_key(key, r->exten); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 309 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 310 | type = (ngx_http_type_t *) clcf->types[key].elts; |
| 311 | for (i = 0; i < clcf->types[key].nelts; i++) { |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 312 | if (r->exten.len != type[i].exten.len) { |
| 313 | continue; |
| 314 | } |
| 315 | |
| 316 | if (ngx_strcasecmp(r->exten.data, type[i].exten.data) == 0) { |
| 317 | r->headers_out.content_type->value.len = type[i].type.len; |
| 318 | r->headers_out.content_type->value.data = type[i].type.data; |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 319 | |
| 320 | break; |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 321 | } |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | if (r->headers_out.content_type->value.len == 0) { |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 326 | r->headers_out.content_type->value.len = clcf->default_type.len; |
| 327 | r->headers_out.content_type->value.data = clcf->default_type.data; |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 328 | } |
Igor Sysoev | 2b54238 | 2002-08-20 14:48:28 +0000 | [diff] [blame] | 329 | |
Igor Sysoev | 79a8048 | 2003-05-14 17:13:13 +0000 | [diff] [blame] | 330 | /* we need to allocate all before the header would be sent */ |
Igor Sysoev | 1342d9c | 2003-10-09 07:00:45 +0000 | [diff] [blame] | 331 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 332 | ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), |
Igor Sysoev | 0c331d9 | 2002-08-15 17:20:26 +0000 | [diff] [blame] | 333 | NGX_HTTP_INTERNAL_SERVER_ERROR); |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 334 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 335 | ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)), |
| 336 | NGX_HTTP_INTERNAL_SERVER_ERROR); |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 337 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 338 | |
| 339 | rc = ngx_http_send_header(r); |
Igor Sysoev | b3e73d8 | 2003-10-10 15:10:50 +0000 | [diff] [blame] | 340 | |
| 341 | if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { |
| 342 | return rc; |
Igor Sysoev | 7578ec9 | 2003-06-02 15:24:30 +0000 | [diff] [blame] | 343 | } |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 344 | |
Igor Sysoev | 1342d9c | 2003-10-09 07:00:45 +0000 | [diff] [blame] | 345 | h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST; |
Igor Sysoev | 1342d9c | 2003-10-09 07:00:45 +0000 | [diff] [blame] | 346 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame] | 347 | h->file_pos = 0; |
| 348 | h->file_last = ngx_file_size(r->file.info); |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 349 | |
| 350 | h->file->fd = r->file.fd; |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 351 | h->file->log = r->connection->log; |
| 352 | |
Igor Sysoev | 419f9ac | 2003-10-21 16:49:56 +0000 | [diff] [blame] | 353 | out.hunk = h; |
| 354 | out.next = NULL; |
| 355 | |
| 356 | return ngx_http_output_filter(r, &out); |
Igor Sysoev | 0c331d9 | 2002-08-15 17:20:26 +0000 | [diff] [blame] | 357 | } |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 358 | |
| 359 | |
| 360 | static int ngx_http_static_init(ngx_cycle_t *cycle) |
| 361 | { |
| 362 | ngx_http_handler_pt *h; |
| 363 | ngx_http_conf_ctx_t *ctx; |
| 364 | ngx_http_core_main_conf_t *cmcf; |
| 365 | |
| 366 | ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; |
| 367 | cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; |
| 368 | |
| 369 | ngx_test_null(h, ngx_push_array( |
| 370 | &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), |
| 371 | NGX_ERROR); |
| 372 | *h = ngx_http_static_translate_handler; |
| 373 | |
| 374 | return NGX_OK; |
| 375 | } |
| 376 | |