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