nginx-0.0.1-2003-05-14-21:13:13 import
diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c
index 38683f7..deefae3 100644
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -157,6 +157,8 @@
                                + index[i].len;
         }
 
+/* STUB */ r->exten.len = 4; r->exten.data = "html";
+
         return ngx_http_internal_redirect(r, loc);
     }
 
diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c
index 69c1d29..e2bbc93 100644
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -6,6 +6,7 @@
 #include <ngx_hunk.h>
 #include <ngx_http.h>
 #include <ngx_http_config.h>
+#include <ngx_http_core_module.h>
 #include <ngx_http_output_filter.h>
 
 
@@ -14,16 +15,22 @@
 
 int ngx_http_static_handler(ngx_http_request_t *r)
 {
-    int                  rc;
+    int                  rc, key, i;
+    ngx_log_e            level;
     ngx_err_t            err;
     ngx_hunk_t          *h;
+    ngx_http_type_t     *type;
     ngx_http_log_ctx_t  *ctx;
+    ngx_http_core_loc_conf_t  *core_lcf; 
+
+    core_lcf = (ngx_http_core_loc_conf_t *)
+                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
 
 #if 0
-    ngx_http_event_static_handler_loc_conf_t  *cf;
+    ngx_http_event_static_handler_loc_conf_t  *lcf;
 
-    cf = (ngx_http_event_static_handler_loc_conf_t *)
-             ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module);
+    lcf = (ngx_http_event_static_handler_loc_conf_t *)
+         ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module_ctx);
 
 #endif
 
@@ -31,32 +38,34 @@
     ctx = r->connection->log->data;
     ctx->action = "sending response";
 
-    if (r->file.fd == NGX_INVALID_FILE)
+    if (r->file.fd == NGX_INVALID_FILE) {
         r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY);
 
-    if (r->file.fd == NGX_INVALID_FILE) {
-        err = ngx_errno;
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
-                      "ngx_http_static_handler: "
-                      ngx_open_file_n " %s failed", r->file.name.data);
+        if (r->file.fd == NGX_INVALID_FILE) {
+            err = ngx_errno;
 
-        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
-            return NGX_HTTP_NOT_FOUND;
+            if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
+                level = NGX_LOG_ERR;
+                rc = NGX_HTTP_NOT_FOUND;
 
-        } else {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            } else {
+                level = NGX_LOG_CRIT;
+                rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            ngx_log_error(level, r->connection->log, ngx_errno,
+                          ngx_open_file_n " %s failed", r->file.name.data);
+            return rc;
         }
     }
 
     if (!r->file.info_valid) {
         if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
-                          "ngx_http_static_handler: "
+            ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                           ngx_stat_fd_n " %s failed", r->file.name.data);
 
             if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
-                              "ngx_http_static_handler: "
+                ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                               ngx_close_file_n " %s failed", r->file.name.data);
 
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -65,16 +74,14 @@
         r->file.info_valid = 1;
     }
 
-#if !(WIN32) /* it's probably Unix specific */
+#if !(WIN32) /* not regular files is probably Unix specific */
 
     if (!ngx_is_file(r->file.info)) {
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
-                      "ngx_http_static_handler: "
+        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                       "%s is not regular file", r->file.name.data);
 
         if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
-            ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
-                          "ngx_http_static_handler: "
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                           ngx_close_file_n " %s failed", r->file.name.data);
 
         return NGX_HTTP_NOT_FOUND;
@@ -93,30 +100,29 @@
     r->headers_out.content_type->key.len = 12;
     r->headers_out.content_type->key.data = "Content-Type";
 
-    /* STUB */
     if (r->exten.len) {
-        if (ngx_strcasecmp(r->exten.data, "html") == 0) {
-            r->headers_out.content_type->value.len = 25;
-            r->headers_out.content_type->value.data =
-                                                   "text/html; charset=koi8-r";
-        } else if (ngx_strcasecmp(r->exten.data, "gif") == 0) {
-            r->headers_out.content_type->value.len = 9;
-            r->headers_out.content_type->value.data = "image/gif";
-        } else if (ngx_strcasecmp(r->exten.data, "jpg") == 0) {
-            r->headers_out.content_type->value.len = 10;
-            r->headers_out.content_type->value.data = "image/jpeg";
-        } else if (ngx_strcasecmp(r->exten.data, "pdf") == 0) {
-            r->headers_out.content_type->value.len = 15;
-            r->headers_out.content_type->value.data = "application/pdf";
-        }
+        ngx_http_types_hash_key(key, r->exten);
 
-    } else {
+        type = (ngx_http_type_t *) core_lcf->types[key].elts;
+        for (i = 0; i < core_lcf->types[key].nelts; i++) {
+            if (r->exten.len != type[i].exten.len) {
+                continue;
+            }
+
+            if (ngx_strcasecmp(r->exten.data, type[i].exten.data) == 0) {
+                r->headers_out.content_type->value.len = type[i].type.len;
+                r->headers_out.content_type->value.data = type[i].type.data;
+            }
+        }
+    }
+
+    if (r->headers_out.content_type->value.len == 0) {
+        /* STUB: default type */
         r->headers_out.content_type->value.len = 25;
         r->headers_out.content_type->value.data = "text/html; charset=koi8-r";
     }
-    /**/
 
-    /* we need to allocate them before header would be sent */
+    /* we need to allocate all before the header would be sent */
     ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
 
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 7128e20..c52a803 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -42,7 +42,7 @@
 static ngx_command_t  ngx_http_commands[] = {
 
     {ngx_string("http"),
-     NGX_CONF_BLOCK|NGX_CONF_NOARGS,
+     NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_http_block,
      0,
      0},
@@ -69,7 +69,8 @@
     ngx_array_t                 in_ports;
     ngx_listen_t               *ls;
     ngx_http_module_t          *module;
-    ngx_http_conf_ctx_t        *ctx, *prev;
+    ngx_conf_t                  prev;
+    ngx_http_conf_ctx_t        *ctx;
     ngx_http_in_port_t         *in_port;
     ngx_http_in_addr_t         *in_addr, *inaddr;
     ngx_http_core_srv_conf_t  **cscf;
@@ -113,12 +114,12 @@
         }
     }
 
-    prev = cf->ctx;
+    prev = *cf;
     cf->ctx = ctx;
-    cf->type = NGX_HTTP_MODULE_TYPE;
-
+    cf->module_type = NGX_HTTP_MODULE_TYPE;
+    cf->cmd_type = NGX_HTTP_MAIN_CONF;
     rv = ngx_conf_parse(cf, NULL);
-    cf->ctx = prev;
+    *cf = prev;
 
     if (rv != NGX_CONF_OK)
         return rv;
@@ -147,7 +148,7 @@
     ngx_init_array(ngx_http_index_handlers,
                    cf->pool, 3, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR);
 
-    /* create lists of ports, addresses and server names */
+    /* create lists of the ports, the addresses and the server names */
 
     ngx_init_array(in_ports, cf->pool, 10, sizeof(ngx_http_in_port_t),
                    NGX_CONF_ERROR);
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index efaee66..5a4f524 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -234,7 +234,7 @@
 void ngx_http_init_connection(ngx_connection_t *c);
 int ngx_parse_http_request_line(ngx_http_request_t *r);
 int ngx_parse_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h);
-int ngx_http_handler(ngx_http_request_t *r);
+void ngx_http_handler(ngx_http_request_t *r);
 void ngx_http_finalize_request(ngx_http_request_t *r, int error);
 void ngx_http_set_write_handler(ngx_http_request_t *r);
 
diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h
index 1bd0120..34890f9 100644
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -33,9 +33,9 @@
 
 #define NGX_HTTP_MODULE           0
 
-#define NGX_HTTP_MAIN_CONF        0x1000000
-#define NGX_HTTP_SRV_CONF         0x2000000
-#define NGX_HTTP_LOC_CONF         0x6000000
+#define NGX_HTTP_MAIN_CONF        0x2000000
+#define NGX_HTTP_SRV_CONF         0x4000000
+#define NGX_HTTP_LOC_CONF         0x8000000
 
 
 #define NGX_HTTP_SRV_CONF_OFFSET  offsetof(ngx_http_conf_ctx_t, srv_conf)
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 6b9de32..4d7225b 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2,8 +2,8 @@
 #include <ngx_config.h>
 
 #include <ngx_listen.h>
-
 #include <ngx_core.h>
+#include <ngx_string.h>
 #include <ngx_conf_file.h>
 
 #include <ngx_http.h>
@@ -30,6 +30,7 @@
 static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
 static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd,
                                                                   char *dummy);
+static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
 static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
 
 
@@ -89,6 +90,12 @@
      NGX_HTTP_SRV_CONF_OFFSET,
      0},
 
+    {ngx_string("types"),
+     NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
+     ngx_types_block,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     0},
+
     {ngx_string("root"),
      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_str_slot,
@@ -143,7 +150,7 @@
 };
 
 
-int ngx_http_handler(ngx_http_request_t *r)
+void ngx_http_handler(ngx_http_request_t *r)
 {
     int                         rc, a, n, i;
     ngx_http_handler_pt        *h;
@@ -267,16 +274,23 @@
             continue;
         }
 
-        if (rc == NGX_OK) {
-            break;
+        if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+            ngx_http_finalize_request(r, rc);
+            return;
         }
 
-        if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
-            return rc;
+        if (rc == NGX_OK) {
+            rc = r->handler(r);
+            if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+                ngx_http_finalize_request(r, rc);
+            }
+            return;
         }
     }
 
-    return r->handler(r);
+    /* TODO: no handlers found ? */
+    ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+    return;
 }
 
 
@@ -372,10 +386,7 @@
                       "ngx_http_core_translate_handler: "
                       ngx_file_type_n " \"%s\" failed", r->file.name.data);
 
-        if (err == NGX_ENOENT) {
-            return NGX_HTTP_NOT_FOUND;
-
-        } else if (err == NGX_ENOTDIR) {
+        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
             return NGX_HTTP_NOT_FOUND;
 
         } else if (err == NGX_EACCES) {
@@ -398,10 +409,7 @@
                       "ngx_http_core_handler: "
                       ngx_open_file_n " \"%s\" failed", r->file.name.data);
 
-        if (err == NGX_ENOENT) {
-            return NGX_HTTP_NOT_FOUND;
-
-        } else if (err == NGX_ENOTDIR) {
+        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
             return NGX_HTTP_NOT_FOUND;
 
         } else if (err == NGX_EACCES) {
@@ -547,7 +555,8 @@
     r->uri_end = uri.data + uri.len;
     /**/
 
-    return ngx_http_handler(r);
+    ngx_http_handler(r);
+    return 0;
 }
 
 
@@ -568,7 +577,8 @@
     int                         i, j;
     char                       *rv;
     ngx_http_module_t          *module;
-    ngx_http_conf_ctx_t        *ctx, *prev;
+    ngx_conf_t                  pcf;
+    ngx_http_conf_ctx_t        *ctx, *pctx;
     ngx_http_core_srv_conf_t   *scf;
     ngx_http_core_loc_conf_t  **plcf;
 
@@ -606,10 +616,12 @@
         }
     }
 
-    prev = cf->ctx;
+    pcf = *cf;
+    pctx = cf->ctx;
     cf->ctx = ctx;
+    cf->cmd_type = NGX_HTTP_SRV_CONF;
     rv = ngx_conf_parse(cf, NULL);
-    cf->ctx = prev;
+    *cf = pcf;
 
     if (rv != NGX_CONF_OK)
         return rv;
@@ -636,19 +648,19 @@
         }
 
         if (module->merge_loc_conf) {
-            if (module->merge_loc_conf(cf->pool,
-                                       prev->loc_conf[module->index],
-                                       ctx->loc_conf[module->index])
-                                                           == NGX_CONF_ERROR) {
-                return NGX_CONF_ERROR;
+            rv = module->merge_loc_conf(cf->pool,
+                                        pctx->loc_conf[module->index],
+                                        ctx->loc_conf[module->index]);
+            if (rv != NGX_CONF_OK) {
+                return rv;
             }
 
             for (j = 0; j < scf->locations.nelts; j++) {
-                if (module->merge_loc_conf(cf->pool,
-                                      ctx->loc_conf[module->index],
-                                      plcf[j]->loc_conf[module->index])
-                                                           == NGX_CONF_ERROR) {
-                    return NGX_CONF_ERROR;
+                rv = module->merge_loc_conf(cf->pool,
+                                            ctx->loc_conf[module->index],
+                                            plcf[j]->loc_conf[module->index]);
+                if (rv != NGX_CONF_OK) {
+                    return rv;
                 }
             }
         }
@@ -664,7 +676,8 @@
     char                      *rv;
     ngx_str_t                 *location;
     ngx_http_module_t         *module;
-    ngx_http_conf_ctx_t       *ctx, *prev;
+    ngx_conf_t                 pcf;
+    ngx_http_conf_ctx_t       *ctx, *pctx;
     ngx_http_core_srv_conf_t  *scf;
     ngx_http_core_loc_conf_t  *lcf, **plcf;
 
@@ -672,8 +685,8 @@
                   ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
                   NGX_CONF_ERROR);
 
-    prev = (ngx_http_conf_ctx_t *) cf->ctx;
-    ctx->srv_conf = prev->srv_conf;
+    pctx = (ngx_http_conf_ctx_t *) cf->ctx;
+    ctx->srv_conf = pctx->srv_conf;
 
     ngx_test_null(ctx->loc_conf,
                   ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
@@ -705,9 +718,62 @@
     ngx_test_null(plcf, ngx_push_array(&scf->locations), NGX_CONF_ERROR);
     *plcf = lcf;
 
+    pcf = *cf;
     cf->ctx = ctx;
+    cf->cmd_type = NGX_HTTP_LOC_CONF;
     rv = ngx_conf_parse(cf, NULL);
-    cf->ctx = prev;
+    *cf = pcf;
+
+    return rv;
+}
+
+
+static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, char *conf)
+{
+    ngx_http_core_loc_conf_t *lcf = (ngx_http_core_loc_conf_t *) conf;
+
+    int               i, key;
+    ngx_str_t        *args;
+    ngx_http_type_t  *t;
+
+    if (lcf->types == NULL) {
+        ngx_test_null(lcf->types,
+                      ngx_palloc(cf->pool, NGX_HTTP_TYPES_HASH_PRIME
+                                                        * sizeof(ngx_array_t)),
+                      NGX_CONF_ERROR);
+
+        for (i = 0; i < NGX_HTTP_TYPES_HASH_PRIME; i++) {
+            ngx_init_array(lcf->types[i], cf->pool, 5, sizeof(ngx_http_type_t),
+                           NGX_CONF_ERROR);
+        }
+    }
+
+    args = (ngx_str_t *) cf->args->elts;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+        ngx_http_types_hash_key(key, args[i]);
+
+        ngx_test_null(t, ngx_push_array(&lcf->types[key]), NGX_CONF_ERROR);
+        t->exten.len = args[i].len;
+        t->exten.data = args[i].data;
+        t->type.len = args[0].len;
+        t->type.data = args[0].data;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+{
+    char        *rv;
+    ngx_conf_t   pcf;
+
+    pcf = *cf;
+    cf->handler = ngx_set_type;
+    cf->handler_conf = conf;
+    rv = ngx_conf_parse(cf, NULL);
+    *cf = pcf;
 
     return rv;
 }
@@ -776,29 +842,95 @@
                   ngx_pcalloc(pool, sizeof(ngx_http_core_loc_conf_t)), 
                   NGX_CONF_ERROR);
 
-    lcf->doc_root.len = 4;
-    lcf->doc_root.data = "html";
-
-    lcf->sendfile = 0;
-
-    lcf->send_timeout = 10000;
-    lcf->discarded_buffer_size = 1500;
-    lcf->lingering_time = 30000;
-    lcf->lingering_timeout = 5000;
-
 /*
-    lcf->send_timeout = NGX_CONF_UNSET;
+    ngx_pcalloc():
+
+    lcf->doc_root.len = 0;
+    lcf->doc_root.data = NULL;
+    lcf->types = NULL;
 */
 
+    lcf->sendfile = NGX_CONF_UNSET;
+
+    lcf->send_timeout = NGX_CONF_UNSET;
+    lcf->discarded_buffer_size = NGX_CONF_UNSET;
+    lcf->lingering_time = NGX_CONF_UNSET;
+    lcf->lingering_timeout = NGX_CONF_UNSET;
+
     return lcf;
 }
 
+
+static ngx_http_type_t default_types[] = {
+    { ngx_string("html"), ngx_string("text/html") },
+    { ngx_string("gif"), ngx_string("image/gif") },
+    { ngx_string("jpg"), ngx_string("image/jpeg") },
+    { ngx_null_string, ngx_null_string }
+};
+
+
 static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool,
                                           void *parent, void *child)
 {
+    ngx_http_core_loc_conf_t *prev = (ngx_http_core_loc_conf_t *) parent;
+    ngx_http_core_loc_conf_t *conf = (ngx_http_core_loc_conf_t *) child;
+
+    int               i, key;
+    ngx_http_type_t  *t;
+
+    if (conf->doc_root.len == 0) {
+        if (prev->doc_root.len) {
+           conf->doc_root.len = prev->doc_root.len;
+           conf->doc_root.data = prev->doc_root.data;
+
+        } else {
+           conf->doc_root.len = 4;
+           conf->doc_root.data = "html";
+        }
+    }
+
+    if (conf->types == NULL) {
+        if (prev->types) {
+            conf->types = prev->types;
+
+        } else {
+            ngx_test_null(conf->types,
+                          ngx_palloc(pool, NGX_HTTP_TYPES_HASH_PRIME
+                                                        * sizeof(ngx_array_t)),
+                          NGX_CONF_ERROR);
+
+            for (i = 0; i < NGX_HTTP_TYPES_HASH_PRIME; i++) {
+                ngx_init_array(conf->types[i], pool, 5, sizeof(ngx_http_type_t),
+                               NGX_CONF_ERROR);
+            }
+
+            for (i = 0; default_types[i].exten.len; i++) {
+                ngx_http_types_hash_key(key, default_types[i].exten);
+
+                ngx_test_null(t, ngx_push_array(&conf->types[key]),
+                              NGX_CONF_ERROR);
+                t->exten.len = default_types[i].exten.len;
+                t->exten.data = default_types[i].exten.data;
+                t->type.len = default_types[i].type.len;
+                t->type.data = default_types[i].type.data;
+            }
+        }
+    }
+
+    ngx_conf_merge(conf->sendfile, prev->sendfile, 0);
+
+    ngx_conf_msec_merge(conf->send_timeout, prev->send_timeout, 10000);
+
+    ngx_conf_size_merge(conf->discarded_buffer_size,
+                        prev->discarded_buffer_size, 1500);
+
+    ngx_conf_msec_merge(conf->lingering_time, prev->lingering_time, 30000);
+    ngx_conf_msec_merge(conf->lingering_timeout, prev->lingering_timeout, 5000);
+
     return NGX_CONF_OK;
 }
 
+
 static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
 {
     ngx_str_t          *args;
@@ -817,7 +949,7 @@
 
     args = (ngx_str_t *) cf->args->elts;
 
-    ls->port = atoi(args[1].data);
+    ls->port = ngx_atoi(args[1].data, args[1].len);
     if (ls->port < 1 || ls->port > 65536) {
         return "port must be between 1 and 65535";
     }
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 6284aac..3208d0d 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -50,6 +50,21 @@
 } ngx_http_server_name_t;
 
 
+#define NGX_HTTP_TYPES_HASH_PRIME  13
+
+#define ngx_http_types_hash_key(key, ext)                                   \
+        {                                                                   \
+            int n;                                                          \
+            for (key = 0, n = 0; n < ext.len; n++) {                        \
+                key += ext.data[n];                                         \
+            }                                                               \
+            key %= NGX_HTTP_TYPES_HASH_PRIME;                               \
+        }
+
+typedef struct {
+    ngx_str_t  exten;
+    ngx_str_t  type;
+} ngx_http_type_t;
 
 
 typedef struct {
@@ -61,6 +76,8 @@
 
     ngx_str_t   doc_root;                /* root */
 
+    ngx_array_t  *types;
+
     int         sendfile;                /* sendfile */
     time_t      send_timeout;            /* send_timeout */
     size_t      send_lowat;              /* send_lowa */
diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c
index 06b8544..1b83fc4 100644
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -65,7 +65,7 @@
     ngx_null_string,  /* 412 */
     ngx_string("413 Request Entity Too Large"),
     ngx_null_string,  /* "414 Request-URI Too Large" but we never send it
-                         because we treat such requests as HTTP/0.9 requests
+                         because we treat such requests as the HTTP/0.9 requests
                          and send only the body without the header */
     ngx_null_string,  /* 415 */
     ngx_string("416 Requested Range Not Satisfiable"),
@@ -124,16 +124,20 @@
 
     } else {
         if (r->headers_out.status < NGX_HTTP_MOVED_PERMANENTLY) {
+            /* 2XX */
             status = r->headers_out.status - NGX_HTTP_OK;
 
         } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) {
+            /* 3XX */
             status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 1;
             r->header_only = 1;
 
         } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) {
+            /* 4XX */
             status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 1 + 4;
 
         } else {
+            /* 5XX */
             status = r->headers_out.status
                                  - NGX_HTTP_INTERNAL_SERVER_ERROR + 1 + 4 + 17;
         }
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 6213c4f..8c86b24 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -120,6 +120,7 @@
     r->headers_out.status = error;
 
     if (error < NGX_HTTP_BAD_REQUEST) {
+        /* 3XX */
         err = error - NGX_HTTP_MOVED_PERMANENTLY;
 
     } else {
@@ -133,9 +134,11 @@
         r->headers_out.content_type->value.data = "text/html";
 
         if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
+            /* 4XX */
             err = error - NGX_HTTP_BAD_REQUEST + 3;
 
         } else {
+            /* 5XX */
             err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17;
         }
     }
@@ -149,6 +152,15 @@
         }
     }
 
+    if (r->lingering_close == 1) {
+        switch (error) {
+            case NGX_HTTP_BAD_REQUEST:
+            case NGX_HTTP_REQUEST_URI_TOO_LARGE:
+            case NGX_HTTP_INTERNAL_SERVER_ERROR:
+                r->lingering_close = 0;
+        }
+    }
+
     if (error_pages[err].len == 0) {
         r->headers_out.content_length = -1;
     } else {