changeset 216:f1d0e5f09c1e

nginx-0.0.1-2003-12-25-23:26:58 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 25 Dec 2003 20:26:58 +0000
parents 5adc2b75f8a5
children c5d1cdcb04ec
files auto/lib/md5/makefile.msvc auto/make auto/options auto/sources src/core/nginx.c src/core/ngx_conf_file.h src/core/ngx_connection.h src/core/ngx_regex.c src/core/ngx_regex.h src/event/ngx_event.c src/http/modules/ngx_http_rewrite_handler.c src/http/modules/ngx_http_status.c src/http/ngx_http.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_log_handler.c src/http/ngx_http_parse.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/os/unix/ngx_errno.h src/os/unix/ngx_freebsd_sendfile_chain.c
diffstat 21 files changed, 507 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/auto/lib/md5/makefile.msvc
+++ b/auto/lib/md5/makefile.msvc
@@ -1,4 +1,5 @@
 
 all:
-	cl -nologo -c -MT -O2 -D MD5_ASM -D L_ENDIAN md5_dgst.c md5_one.c
+	cl -nologo -c -MT -O2 -Ob1 -Oi -Gs -D MD5_ASM -D L_ENDIAN	\
+		md5_dgst.c md5_one.c
 	link -lib -out:md5.lib md5_dgst.obj md5_one.obj asm/m-win32.obj
--- a/auto/make
+++ b/auto/make
@@ -11,6 +11,11 @@ HTTP_FILTER_MODULES="$HTTP_FILTER_MODULE
 
 HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE $HTTP_INDEX_MODULE"
 
+if [ $HTTP_REWRITE = YES ]; then
+    HTTP_MODULES="$HTTP_MODULES $HTTP_REWRITE_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_REWRITE_SRCS"
+fi
+
 if [ $HTTP_GZIP = YES ]; then
     HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_GZIP_FILTER_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_GZIP_SRCS"
--- a/auto/options
+++ b/auto/options
@@ -6,6 +6,7 @@ OBJS=objs
 
 TEST_BUILD_DEVPOLL=NO
 
+HTTP_REWRITE=YES
 HTTP_GZIP=YES
 HTTP_PROXY=YES
 
@@ -34,6 +35,7 @@ do
 
         --builddir=*)                    OBJS="$value"              ;;
 
+        --without-http_rewrite_module)   HTTP_REWRITE=NO            ;;
         --without-http_gzip_module)      HTTP_GZIP=NO               ;;
         --without-http_proxy_module)     HTTP_PROXY=NO              ;;
 
--- a/auto/sources
+++ b/auto/sources
@@ -193,6 +193,10 @@ HTTP_SRCS="src/http/ngx_http.c \
             src/http/modules/ngx_http_not_modified_filter.c"
 
 
+HTTP_REWRITE_MODULE=ngx_http_rewrite_module
+HTTP_REWRITE_SRCS=src/http/modules/ngx_http_rewrite_handler.c
+
+
 HTTP_GZIP_FILTER_MODULE=ngx_http_gzip_filter_module
 HTTP_GZIP_SRCS=src/http/modules/ngx_http_gzip_filter.c
 HTTP_GZIP_UNIX_LIBS=-lz
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -204,11 +204,13 @@ int main(int argc, char *const *argv)
                 ngx_process_events(cycle->log);
 
                 if (done) {
+#if !(WIN32)
                     if (ngx_delete_file(pidfile.name.data) == NGX_FILE_ERROR) {
                         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                                       ngx_delete_file_n " \"%s\" failed",
                                       pidfile.name.data);
                     }
+#endif
 
                     ngx_log_error(NGX_LOG_INFO,
                                   cycle->log, 0, "exiting");
@@ -291,11 +293,11 @@ ngx_log_debug(log, "REOPEN: %d:%d:%s" _ 
 static ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle, ngx_log_t *log)
 {
     int               i, n, failed;
-    ngx_fd_t          fd;
     ngx_str_t         conf_file;
     ngx_conf_t        conf;
     ngx_pool_t       *pool;
     ngx_cycle_t      *cycle, **old;
+    ngx_socket_t      fd;
     ngx_core_conf_t  *ccf;
     ngx_open_file_t  *file;
     ngx_listening_t  *ls, *nls;
@@ -457,7 +459,7 @@ ngx_log_debug(log, "OPEN: %d:%s" _ file[
 
                         fd /= 4;
 #endif
-                        if (fd >= cycle->connection_n) {
+                        if (fd >= (ngx_socket_t) cycle->connection_n) {
                             ngx_log_error(NGX_LOG_EMERG, log, 0,
                                         "%d connections is not enough to hold "
                                         "an open listening socket on %s, "
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -24,8 +24,9 @@
 #define NGX_CONF_TAKE9       0x00000200
 
 #define NGX_CONF_TAKE12      (NGX_CONF_TAKE1|NGX_CONF_TAKE2)
+#define NGX_CONF_TAKE13      (NGX_CONF_TAKE1|NGX_CONF_TAKE3)
 
-#define NGX_CONF_TAKE13      (NGX_CONF_TAKE1|NGX_CONF_TAKE3)
+#define NGX_CONF_TAKE23      (NGX_CONF_TAKE2|NGX_CONF_TAKE3)
 
 #define NGX_CONF_TAKE1234    (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3   \
                               |NGX_CONF_TAKE4)
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -81,7 +81,7 @@ struct ngx_connection_s {
 
     ngx_hunk_t       *buffer;
 
-    int               number;
+    ngx_int_t         number;
 
     unsigned          pipeline:1;
     unsigned          unexpected_eof:1;
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -45,11 +45,12 @@ ngx_regex_t *ngx_regex_compile(ngx_str_t
 }
 
 
-ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s)
+ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s,
+                         int *matches, ngx_int_t size)
 {
     int  rc;
 
-    rc = pcre_exec(re, NULL, s->data, s->len, 0, 0, NULL, 0);
+    rc = pcre_exec(re, NULL, s->data, s->len, 0, 0, matches, size);
 
     if (rc == -1) {
         return NGX_DECLINED;
--- a/src/core/ngx_regex.h
+++ b/src/core/ngx_regex.h
@@ -15,7 +15,8 @@ typedef pcre  ngx_regex_t;
 void ngx_regex_init();
 ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options,
                                ngx_pool_t *pool, ngx_str_t *err);
-ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s);
+ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s,
+                         int *matches, ngx_int_t size);
 
 #define ngx_regex_exec_n  "pcre_exec()"
 
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -8,6 +8,7 @@
 
 
 extern ngx_module_t ngx_select_module;
+extern ngx_event_module_t ngx_select_module_ctx;
 
 #if (HAVE_KQUEUE)
 #include <ngx_kqueue_module.h>
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_rewrite_handler.c
@@ -0,0 +1,340 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+#define NGX_HTTP_REWRITE_COPY_MATCH  0
+#define NGX_HTTP_REWRITE_COPY_SHORT  1
+#define NGX_HTTP_REWRITE_COPY_LONG   2
+
+
+typedef struct {
+    ngx_int_t    op;
+    size_t       len;
+    uintptr_t    data;
+} ngx_http_rewrite_op_t;
+
+
+typedef struct {
+    ngx_regex_t  *regex;
+    ngx_uint_t    msize;
+
+    ngx_array_t   ops;
+    ngx_uint_t    size;
+
+    ngx_str_t     re_name;
+    ngx_str_t     s_name;
+
+    unsigned      last:1;
+} ngx_http_rewrite_rule_t;
+
+
+typedef struct {
+    ngx_array_t   rules;
+    unsigned      log:1;
+} ngx_http_rewrite_srv_conf_t;
+
+
+static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_rewrite_rule(ngx_conf_t *cf, ngx_command_t *cmd,
+                                   void *conf);
+static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle);
+
+
+static ngx_command_t  ngx_http_rewrite_commands[] = {
+
+    { ngx_string("rewrite"),
+      NGX_HTTP_SRV_CONF|NGX_CONF_TAKE23,
+      ngx_http_rewrite_rule,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      0,
+      NULL },
+
+      ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_rewrite_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    ngx_http_rewrite_create_loc_conf,      /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configration */
+    NULL,                                  /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_rewrite_module = {
+    NGX_MODULE,
+    &ngx_http_rewrite_module_ctx,          /* module context */
+    ngx_http_rewrite_commands,             /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_rewrite_init,                 /* init module */
+    NULL                                   /* init child */
+};
+
+
+static ngx_int_t ngx_http_rewrite_handler(ngx_http_request_t *r)
+{
+    int                          *matches;
+    char                         *p;
+    size_t                        len;
+    uintptr_t                     data;
+    ngx_int_t                     rc, i, n, m;
+    ngx_str_t                     uri;
+    ngx_http_rewrite_op_t        *op;
+    ngx_http_rewrite_rule_t      *rule;
+    ngx_http_rewrite_srv_conf_t  *scf;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http rewrite handler");
+
+    scf = ngx_http_get_module_srv_conf(r, ngx_http_rewrite_module);
+
+    rule = scf->rules.elts;
+    for (i = 0; i < scf->rules.nelts; i++) {
+
+        if (rule[i].msize) {
+            if (!(matches = ngx_palloc(r->pool, rule[i].msize * sizeof(int)))) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+        } else {
+            matches = NULL;
+        }
+
+        rc = ngx_regex_exec(rule[i].regex, &r->uri, matches, rule[i].msize);
+
+        if (rc == NGX_DECLINED) {
+            if (scf->log) {
+                ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                              "\"%s\" is not matched", rule[i].re_name.data);
+            }
+
+            continue;
+        }
+
+        if (rc < 0) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                          ngx_regex_exec_n
+                          " failed: %d on \"%s\" using \"%s\"",
+                          rc, r->uri.data, rule[i].re_name.data);
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        if (scf->log) {
+            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                          "\"%s\" matched", rule[i].re_name.data);
+        }
+
+        uri.len = rule[i].size;
+
+        for (n = 1; n < rc; n++) {
+           uri.len += matches[2 * n + 1] - matches[2 * n];
+        }
+
+        if (!(uri.data = ngx_palloc(r->pool, uri.len + 1))) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        p = uri.data;
+
+        op = rule[i].ops.elts;
+        for (n = 0; n < rule[i].ops.nelts; n++) {
+            if (op[n].op == NGX_HTTP_REWRITE_COPY_SHORT) {
+                len = op[n].len;
+                data = op[n].data;
+                while (len--) {
+                    *p++ = data & 0xff;
+                    data >>= 8;
+                }
+
+            } else if (op[n].op == NGX_HTTP_REWRITE_COPY_LONG) {
+                p = ngx_cpymem(p, (void *) op[n].data, op[n].len);
+
+            } else { /* NGX_HTTP_REWRITE_COPY_MATCH */
+                m = 2 * op[n].data;
+                p = ngx_cpymem(p, &r->uri.data[matches[m]],
+                               matches[m + 1] - matches[m]);
+            }
+        }
+
+        *p = '\0';
+
+        if (scf->log) {
+            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                          "rewritten uri: \"%s\"", uri.data);
+        }
+
+        r->uri = uri;
+
+        if (ngx_http_set_exten(r) != NGX_OK) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        if (rule[i].last) {
+            return NGX_DECLINED;
+        }
+    }
+
+    return NGX_DECLINED;
+}
+
+
+static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_rewrite_srv_conf_t  *conf;
+
+    if (!(conf = ngx_palloc(cf->pool, sizeof(ngx_http_rewrite_srv_conf_t)))) {
+        return NGX_CONF_ERROR;
+    }
+
+    ngx_init_array(conf->rules, cf->pool, 5, sizeof(ngx_http_rewrite_rule_t),
+                   NGX_CONF_ERROR);
+
+    conf->log = 1;
+
+    return conf;
+}
+
+
+static char *ngx_http_rewrite_rule(ngx_conf_t *cf, ngx_command_t *cmd,
+                                   void *conf)
+{
+    ngx_http_rewrite_srv_conf_t *scf = conf;
+
+    char                     *data, *p;
+    size_t                    len;
+    ngx_str_t                *value, err;
+    ngx_uint_t                i;
+    ngx_http_rewrite_op_t    *op;
+    ngx_http_rewrite_rule_t  *rule;
+    char                      errstr[NGX_MAX_CONF_ERRSTR];
+
+    if (!(rule = ngx_push_array(&scf->rules))) {
+        return NGX_CONF_ERROR;
+    }
+
+    ngx_init_array(rule->ops, cf->pool, 5, sizeof(ngx_http_rewrite_op_t),
+                   NGX_CONF_ERROR);
+
+    rule->msize = 0;
+    rule->size = 0;
+
+    value = cf->args->elts;
+
+    /* STUB */ {
+        err.len = NGX_MAX_CONF_ERRSTR;
+        err.data = errstr;
+
+        rule->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
+    
+        if (rule->regex == NULL) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+            return NGX_CONF_ERROR;
+        }
+    
+        rule->re_name = value[1];
+        rule->s_name = value[2];
+
+        for (i = 0; i < value[2].len; /* void */) {
+
+            if (!(op = ngx_push_array(&rule->ops))) {
+                return NGX_CONF_ERROR;
+            }
+
+            data = &value[2].data[i];
+
+            if (value[2].data[i] == '$'
+                && i < value[2].len
+                && value[2].data[i + 1] >= '1'
+                && value[2].data[i + 1] <= '9')
+            {
+                op->op = NGX_HTTP_REWRITE_COPY_MATCH; 
+                op->data = value[2].data[++i] - '0';
+
+                if (rule->msize < op->data) {
+                    rule->msize = op->data;
+                }
+
+                i++;
+
+            } else {
+                i++;
+
+                while (i < value[2].len && value[2].data[i] != '$') {
+                    i++;
+                }
+
+                len = &value[2].data[i] - data;
+                rule->size += len;
+
+                if (len) {
+
+                    op->len = len;
+
+                    if (len <= sizeof(uintptr_t)) {
+                        op->op = NGX_HTTP_REWRITE_COPY_SHORT; 
+                        op->data = 0;
+
+                        while (len--) {
+                            op->data <<= 8;
+                            op->data |= data[len];
+                        }
+
+                    } else {
+                        op->op = NGX_HTTP_REWRITE_COPY_LONG;
+
+                        if (!(p = ngx_palloc(cf->pool, len))) {
+                            return NGX_CONF_ERROR;
+                        }
+
+                        ngx_memcpy(p, data, len);
+                        op->data = (uintptr_t) p;
+                    }
+                }
+            }
+        }
+
+        rule->msize++;
+        rule->msize *= 3;
+
+        if (cf->args->nelts > 3) {
+            if (ngx_strcmp(value[3].data, "last") == 0) {
+                rule->last = 1;
+
+            } else {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "invalid parameter \"%s\"", value[3].data);
+                return NGX_CONF_ERROR;
+            }
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_conf_ctx_t        *ctx;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
+    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
+
+    h = ngx_push_array(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+
+    *h = ngx_http_rewrite_handler;
+
+    return NGX_OK;
+}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_status.c
@@ -0,0 +1,61 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+static ngx_command_t  ngx_http_status_commands[] = {
+
+      ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_status_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_status_create_loc_conf,       /* create location configration */
+    ngx_http_status_merge_loc_conf         /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_status_module = {
+    NGX_MODULE,
+    &ngx_http_status_module_ctx,           /* module context */ 
+    ngx_http_status_commands,              /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_status_init,                  /* init module */
+    NULL                                   /* init child */
+};
+
+
+static char http_states = "IRPCUWLK";
+
+
+int ngx_http_status_handler(ngx_http_request_t *r)
+{
+    ngx_int_t            i, http;
+    ngx_connection_t    *c;
+    ngx_http_request_t  *sr;
+
+    c = ngx_cycle->connections;
+
+    for (i = 0; i < ngx_cycle->connection_n; i++) {
+        if (c[i].module != http || c[i].data == NULL) {
+            continue;
+        }
+
+        if (c[i].data == NULL && c[i].fd != -1) {
+            'A'
+        }
+
+        sr = c[i].data;
+    }
+
+    return NGX_OK;
+}
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -50,19 +50,19 @@ static char *ngx_http_block(ngx_conf_t *
     int                          port_found, addr_found, virtual_names;
     char                        *rv;
     struct sockaddr_in          *addr_in;
+    ngx_conf_t                   pcf;
     ngx_array_t                  in_ports;
     ngx_listening_t             *ls;
+    ngx_http_listen_t           *lscf;
     ngx_http_module_t           *module;
-    ngx_conf_t                   pcf;
     ngx_http_handler_pt         *h;
     ngx_http_conf_ctx_t         *ctx;
     ngx_http_in_port_t          *in_port, *inport;
     ngx_http_in_addr_t          *in_addr, *inaddr;
-    ngx_http_core_main_conf_t   *cmcf;
+    ngx_http_server_name_t      *s_name, *name;
     ngx_http_core_srv_conf_t   **cscfp, *cscf;
     ngx_http_core_loc_conf_t   **clcfp, *clcf;
-    ngx_http_listen_t           *lscf;
-    ngx_http_server_name_t      *s_name, *name;
+    ngx_http_core_main_conf_t   *cmcf;
 #if (WIN32)
     ngx_iocp_conf_t             *iocpcf;
 #endif
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -469,7 +469,7 @@ int ngx_http_find_location_config(ngx_ht
                                  clcfp[i]->regex ? "~ " : "",
                            clcfp[i]->name.data);
 
-            rc = ngx_regex_exec(clcfp[i]->regex, &r->uri);
+            rc = ngx_regex_exec(clcfp[i]->regex, &r->uri, NULL, 0);
 
             if (rc == NGX_DECLINED) {
                 continue;
@@ -613,11 +613,40 @@ int ngx_http_error(ngx_http_request_t *r
 }
 
 
+ngx_int_t ngx_http_set_exten(ngx_http_request_t *r)
+{
+    ngx_int_t  i;
+
+    r->exten.len = 0;
+    r->exten.data = NULL;
+
+    for (i = r->uri.len - 1; i > 1; i--) {
+        if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
+            r->exten.len = r->uri.len - i - 1;
+
+            if (r->exten.len > 0) {
+                if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) {
+                    return NGX_ERROR;
+                }
+
+                ngx_cpystrn(r->exten.data, &r->uri.data[i + 1],
+                            r->exten.len + 1);
+            }
+
+            break;
+
+        } else if (r->uri.data[i] == '/') {
+            break;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
 int ngx_http_internal_redirect(ngx_http_request_t *r,
                                ngx_str_t *uri, ngx_str_t *args)
 {
-    int  i;
-
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "internal redirect: \"%s\"", uri->data);
 
@@ -629,26 +658,8 @@ int ngx_http_internal_redirect(ngx_http_
         r->args.data = args->data;
     }
 
-    r->exten.len = 0;
-    r->exten.data = NULL;
-
-    for (i = uri->len - 1; i > 1; i--) {
-        if (uri->data[i] == '.' && uri->data[i - 1] != '/') {
-            r->exten.len = uri->len - i - 1;
-
-            if (r->exten.len > 0) {
-                ngx_test_null(r->exten.data,
-                              ngx_palloc(r->pool, r->exten.len + 1),
-                              NGX_HTTP_INTERNAL_SERVER_ERROR);
-
-                ngx_cpystrn(r->exten.data, &uri->data[i + 1], r->exten.len + 1);
-            }
-
-            break;
-
-        } else if (uri->data[i] == '/') {
-            break;
-        }
+    if (ngx_http_set_exten(r) != NGX_OK) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
     if (r->err_ctx) {
@@ -872,7 +883,7 @@ static char *ngx_location_block(ngx_conf
     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
     clcf->loc_conf = ctx->loc_conf;
 
-    value = (ngx_str_t *) cf->args->elts;
+    value = cf->args->elts;
 
     if (cf->args->nelts == 3) {
         if (value[1].len == 1 && value[1].data[0] == '=') {
@@ -898,8 +909,7 @@ static char *ngx_location_block(ngx_conf
                 return NGX_CONF_ERROR;
             }
 
-            clcf->name.len = value[2].len;
-            clcf->name.data = value[2].data;
+            clcf->name = value[2];
 #else
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "the using of the regex \"%s\" "
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -156,6 +156,7 @@ int ngx_http_find_location_config(ngx_ht
 int ngx_http_core_translate_handler(ngx_http_request_t *r);
 
 ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
+ngx_int_t ngx_http_set_exten(ngx_http_request_t *r);
 
 int ngx_http_internal_redirect(ngx_http_request_t *r,
                                ngx_str_t *uri, ngx_str_t *args);
--- a/src/http/ngx_http_log_handler.c
+++ b/src/http/ngx_http_log_handler.c
@@ -470,14 +470,14 @@ static char *ngx_http_log_header_out(ngx
         && ngx_strncasecmp(s->data, "Connection", s->len) == 0)
     {
         op->op = ngx_http_log_connection_header_out;
-        op->data = NULL;
+        op->data = (uintptr_t) NULL;
         return NULL;
     }
 
     if (s->len == sizeof("Transfer-Encoding") - 1
         && ngx_strncasecmp(s->data, "Transfer-Encoding", s->len) == 0) {
         op->op = ngx_http_log_transfer_encoding_header_out;
-        op->data = NULL;
+        op->data = (uintptr_t) NULL;
         return NULL;
     }
 
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -463,7 +463,7 @@ ngx_int_t ngx_http_parse_header_line(ngx
                     break;
                 }
 
-                if (ch == '-') {
+                if (ch == '-' || ch == '_' || ch == '~') {
                     break;
                 }
 
@@ -489,7 +489,7 @@ ngx_int_t ngx_http_parse_header_line(ngx
                 break;
             }
 
-            if (ch == '-') {
+            if (ch == '-' || ch == '_' || ch == '~') {
                 break;
             }
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -142,6 +142,8 @@ static void ngx_http_init_request(ngx_ev
         }
     }
 
+    r->http_state = NGX_HTTP_INITING_REQUEST_STATE;
+
     /* find the server configuration for the address:port */
 
     /* AF_INET only */
@@ -1519,6 +1521,7 @@ void ngx_http_close_connection(ngx_conne
     }
 
     c->fd = -1;
+    c->data = NULL;
 
     ngx_destroy_pool(c->pool);
 
@@ -1545,13 +1548,13 @@ static void ngx_http_client_error(ngx_ht
 
     if (ctx->url) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                     client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
-                     ctx->client, ctx->url);
+                    client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
+                    ctx->client, ctx->url);
 
     } else {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                     client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
-                     ctx->client);
+                    client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
+                    ctx->client);
     }
 
     r->connection->log->handler = ngx_http_log_error;
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -64,9 +64,19 @@
 #define NGX_HTTP_GATEWAY_TIME_OUT          504
 
 
+typedef enum {
+    NGX_HTTP_INITING_REQUEST_STATE = 0,
+    NGX_HTTP_READING_REQUEST_STATE,
+    NGX_HTTP_PROCESS_REQUEST_STATE,
 
-#define NGX_HTTP_STATIC_HANDLER     0
-#define NGX_HTTP_DIRECTORY_HANDLER  1
+    NGX_HTTP_CONNECT_UPSTREAM_STATE,
+    NGX_HTTP_WRITING_UPSTREAM_STATE,
+    NGX_HTTP_READING_UPSTREAM_STATE,
+
+    NGX_HTTP_WRITING_REQUEST_STATE,
+    NGX_HTTP_LINGERING_CLOSE_STATE,
+    NGX_HTTP_KEEPALIVE_STATE
+} ngx_http_state_e;
 
 
 typedef struct {
@@ -223,6 +233,8 @@ struct ngx_http_request_s {
     void               **err_ctx;
     int                  err_status;
 
+    unsigned             http_state:4;
+
     /* URI is not started with '/' - "GET http://" */
     unsigned             unusual_uri:1;
     /* URI with "/.", "%" and on Win32 with "//" */
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -10,16 +10,18 @@ typedef int               ngx_err_t;
 
 #define NGX_ENOENT        ENOENT
 #define NGX_EINTR         EINTR
+#define NGX_ECHILD        ECHILD
 #define NGX_EACCES        EACCES
+#define NGX_EBUSY         EBUSY
 #define NGX_EEXIST        EEXIST
 #define NGX_ENOTDIR       ENOTDIR
+#define NGX_EPIPE         EPIPE
 #define NGX_EAGAIN        EWOULDBLOCK
 #define NGX_EINPROGRESS   EINPROGRESS
 #define NGX_EADDRINUSE    EADDRINUSE
 #define NGX_ECONNRESET    ECONNRESET
 #define NGX_ETIMEDOUT     ETIMEDOUT
 #define NGX_ECANCELED     ECANCELED
-#define NGX_ECHILD        ECHILD
 #define NGX_ENOMOREFILES  0
 
 
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -26,7 +26,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
     char            *prev;
     off_t            sent, fprev;
     size_t           hsize, fsize, size;
-    ngx_int_t        eintr, eagain;
+    ngx_int_t        eintr, eagain, level;
     struct iovec    *iov;
     struct sf_hdtr   hdtr;
     ngx_err_t        err;
@@ -59,6 +59,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
         hsize = 0;
         eintr = 0;
         eagain = 0;
+        level = NGX_LOG_CRIT;
 
         ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
                        NGX_CHAIN_ERROR);
@@ -186,10 +187,12 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
 
                 if (err == NGX_EINTR) {
                     eintr = 1;
-                }
 
-                if (err == NGX_EAGAIN) {
+                } else if (err == NGX_EAGAIN) {
                     eagain = 1;
+
+                } else if (err == NGX_EPIPE) {
+                    level = NGX_LOG_INFO;
                 }
 
                 if (err == NGX_EAGAIN || err == NGX_EINTR) {
@@ -199,7 +202,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
 
                 } else {
                     wev->error = 1;
-                    ngx_log_error(NGX_LOG_CRIT, c->log, err,
+                    ngx_log_error(level, c->log, err,
                                   "sendfile() failed");
                     return NGX_CHAIN_ERROR;
                 }
@@ -217,6 +220,9 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
 
                 if (err == NGX_EINTR) {
                     eintr = 1;
+
+                } else if (err == NGX_EPIPE) {
+                    level = NGX_LOG_INFO;
                 }
 
                 if (err == NGX_EAGAIN || err == NGX_EINTR) {
@@ -225,7 +231,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
 
                 } else {
                     wev->error = 1;
-                    ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
+                    ngx_log_error(level, c->log, err, "writev() failed");
                     return NGX_CHAIN_ERROR;
                 }
             }