changeset 56:3050baa54a26 NGINX_0_1_28

nginx 0.1.28 *) Bugfix: nginx hogs CPU while proxying the huge files. *) Bugfix: nginx could not be built by gcc 4.0 on Linux.
author Igor Sysoev <http://sysoev.ru>
date Fri, 08 Apr 2005 00:00:00 +0400
parents 729de7d75018
children 5df375c55338
files CHANGES CHANGES.ru auto/sources conf/mime.types src/core/nginx.h src/core/ngx_buf.c src/core/ngx_buf.h src/core/ngx_conf_file.c src/core/ngx_conf_file.h src/core/ngx_core.h src/core/ngx_cycle.c src/core/ngx_cycle.h src/core/ngx_hash.c src/core/ngx_hash.h src/core/ngx_output_chain.c src/core/ngx_palloc.c src/core/ngx_palloc.h src/core/ngx_table.h src/event/ngx_event_pipe.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_rewrite_module.c src/http/modules/ngx_http_ssl_module.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/ngx_http.c src/http/ngx_http.h src/http/ngx_http_core_module.h src/http/ngx_http_parse.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_script.c src/http/ngx_http_script.h src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/http/ngx_http_write_filter_module.c src/os/unix/ngx_setproctitle.c
diffstat 35 files changed, 740 insertions(+), 163 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,7 +1,14 @@
+
+Changes with nginx 0.1.28                                        08 Apr 2005
+
+    *) Bugfix: nginx hogs CPU while proxing the huge files.
+
+    *) Bugfix: nginx could not be built by gcc 4.0 on Linux.
+
 
 Changes with nginx 0.1.27                                        28 Mar 2005
 
-    *) Feature: the "blocked" parameter of the "invalid_referers" directive.
+    *) Feature: the "blocked" parameter of the "valid_referers" directive.
 
     *) Change: the errors while handling the request header now logged at 
        "info" level. The server name and the "Host" and "Referer" header 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,7 +1,15 @@
+
+Изменения в nginx 0.1.28                                          08.04.2005
+
+    *) Исправление: при проксировании больших файлов nginx сильно нагружал 
+       процессор.
+
+    *) Исправление: nginx не собирался gcc 4.0 на Linux.
+
 
 Изменения в nginx 0.1.27                                          28.03.2005
 
-    *) Добавление: параметр blocked в директиве invalid_referers.
+    *) Добавление: параметр blocked в директиве valid_referers.
 
     *) Изменение: ошибки обработки заголовка запроса теперь записываются на 
        уровне info, в лог также записывается имя сервера и строки заголовка 
--- a/auto/sources
+++ b/auto/sources
@@ -13,7 +13,7 @@ CORE_DEPS="src/core/nginx.h \
            src/core/ngx_palloc.h \
            src/core/ngx_array.h \
            src/core/ngx_list.h \
-           src/core/ngx_table.h \
+           src/core/ngx_hash.h \
            src/core/ngx_buf.h \
            src/core/ngx_string.h \
            src/core/ngx_parse.h \
@@ -34,6 +34,7 @@ CORE_SRCS="src/core/nginx.c \
            src/core/ngx_palloc.c \
            src/core/ngx_array.c \
            src/core/ngx_list.c \
+           src/core/ngx_hash.c \
            src/core/ngx_buf.c \
            src/core/ngx_output_chain.c \
            src/core/ngx_string.c \
@@ -243,6 +244,7 @@ HTTP_DEPS="src/http/ngx_http.h \
            src/http/ngx_http_core_module.h \
            src/http/ngx_http_cache.h \
            src/http/ngx_http_variables.h \
+           src/http/ngx_http_script.h \
            src/http/ngx_http_upstream.h \
            src/http/ngx_http_busy_lock.h \
            src/http/ngx_http_log_module.h"
@@ -258,6 +260,7 @@ HTTP_SRCS="src/http/ngx_http.c \
            src/http/ngx_http_log_module.c \
            src/http/ngx_http_request_body.c \
            src/http/ngx_http_variables.c \
+           src/http/ngx_http_script.c \
            src/http/ngx_http_upstream.c \
            src/http/ngx_http_parse_time.c \
            src/http/modules/ngx_http_static_module.c \
@@ -320,6 +323,8 @@ HTTP_SSL_SRCS=src/http/modules/ngx_http_
 
 
 HTTP_PROXY_MODULE=ngx_http_proxy_module
+#HTTP_PROXY_SRCS=src/http/modules/ngx_http_proxy_module.c
+
 HTTP_PROXY_INCS="src/http/modules/proxy"
 HTTP_PROXY_DEPS=src/http/modules/proxy/ngx_http_proxy_handler.h
 HTTP_PROXY_SRCS="src/http/modules/proxy/ngx_http_proxy_handler.c \
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -4,21 +4,27 @@ types {
     text/xml                       xml rss;
     text/css                       css;
     text/plain                     txt;
+    text/x-component               htc;
 
     image/gif                      gif;
     image/png                      png;
     image/jpeg                     jpeg jpg;
     image/x-icon                   ico;
+    image/x-jng                    jng;
 
     application/pdf                pdf;
     application/x-shockwave-flash  swf;
     application/x-javascript       js;
+    application/x-rar-compressed   rar;
+    application/x-xpinstall        xpi;
 
     audio/mpeg                     mp3;
     audio/x-realaudio              ra;
 
     video/mpeg                     mpeg mpg;
     video/quicktime                mov;
+    video/x-flv                    flv;
     video/x-msvideo                avi;
     video/x-ms-wmv                 wmv;
+    video/x-mng                    mng;
 }
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.1.27"
+#define NGINX_VER          "nginx/0.1.28"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_NEWPID_EXT     ".newbin"
--- a/src/core/ngx_buf.c
+++ b/src/core/ngx_buf.c
@@ -44,6 +44,27 @@ ngx_create_temp_buf(ngx_pool_t *pool, si
 
 
 ngx_chain_t *
+ngx_alloc_chain_link(ngx_pool_t *pool)
+{
+    ngx_chain_t  *cl;
+
+    cl = pool->chain;
+
+    if (cl) {
+        pool->chain = cl->next;
+        return cl;
+    }
+
+    cl = ngx_palloc(pool, sizeof(ngx_chain_t));
+    if (cl == NULL) {
+        return NULL;
+    }
+
+    return cl;
+}
+
+
+ngx_chain_t *
 ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
 {
     u_char       *p;
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -55,8 +55,6 @@ struct ngx_buf_s {
 };
 
 
-typedef struct ngx_chain_s       ngx_chain_t;
-
 struct ngx_chain_s {
     ngx_buf_t    *buf;
     ngx_chain_t  *next;
@@ -119,7 +117,11 @@ ngx_chain_t *ngx_create_chain_of_bufs(ng
 #define ngx_alloc_buf(pool)  ngx_palloc(pool, sizeof(ngx_buf_t))
 #define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t))
 
-#define ngx_alloc_chain_link(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
+ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);
+#define ngx_free_chain(pool, cl)                                             \
+    cl->next = pool->chain;                                                  \
+    pool->chain = cl
+
 
 
 ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in);
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -137,7 +137,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t
             }
 
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                         "%s in %s:%d",
+                         "%s in %s:%ui",
                          rv, cf->conf_file->file.name.data,
                          cf->conf_file->line);
             rc = NGX_ERROR;
@@ -207,7 +207,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int
 
                 if (!(cmd->type & cf->cmd_type)) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "directive \"%s\" in %s:%d "
+                                  "directive \"%s\" in %s:%ui "
                                   "is not allowed here",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -216,7 +216,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int
 
                 if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "directive \"%s\" in %s:%d "
+                                  "directive \"%s\" in %s:%ui "
                                   "is not terminated by \";\"",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -227,7 +227,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int
                     && last != NGX_CONF_BLOCK_START)
                 {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "directive \"%s\" in %s:%d "
+                                  "directive \"%s\" in %s:%ui "
                                   "has not the opening \"{\"",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -276,7 +276,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int
                 if (!valid) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                                   "invalid number arguments in "
-                                  "directive \"%s\" in %s:%d",
+                                  "directive \"%s\" in %s:%ui",
                                   name->data, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
                     return NGX_ERROR;
@@ -311,7 +311,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int
                 }
 
                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                              "the \"%s\" directive %s in %s:%d",
+                              "the \"%s\" directive %s in %s:%ui",
                               name->data, rv, cf->conf_file->file.name.data,
                               cf->conf_file->line);
 
@@ -323,7 +323,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int
     }
 
     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                  "unknown directive \"%s\" in %s:%d",
+                  "unknown directive \"%s\" in %s:%ui",
                   name->data, cf->conf_file->file.name.data,
                   cf->conf_file->line);
 
@@ -360,7 +360,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
             {
                 if (cf->args->nelts > 0) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "unexpected end of file in %s:%d, "
+                                  "unexpected end of file in %s:%ui, "
                                   "expecting \";\" or \"}\"",
                                   cf->conf_file->file.name.data,
                                   cf->conf_file->line);
@@ -423,7 +423,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
             }
 
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          "unexpected \"%c\" in %s:%d",
+                          "unexpected \"%c\" in %s:%ui",
                           ch, cf->conf_file->file.name.data,
                           cf->conf_file->line);
 
@@ -443,7 +443,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
             case '{':
                 if (cf->args->nelts == 0) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "unexpected \"%c\" in %s:%d",
+                                  "unexpected \"%c\" in %s:%ui",
                                   ch, cf->conf_file->file.name.data,
                                   cf->conf_file->line);
                     return NGX_ERROR;
@@ -458,7 +458,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
             case '}':
                 if (cf->args->nelts > 0) {
                     ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                  "unexpected \"}\" in %s:%d",
+                                  "unexpected \"}\" in %s:%ui",
                                   cf->conf_file->file.name.data,
                                   cf->conf_file->line);
                     return NGX_ERROR;
@@ -729,7 +729,7 @@ ngx_conf_log_error(ngx_uint_t level, ngx
         *buf = '\0';
     }
 
-    ngx_log_error(level, cf->log, 0, "%s in %s:%d",
+    ngx_log_error(level, cf->log, 0, "%s in %s:%ui",
                   errstr, cf->conf_file->file.name.data, cf->conf_file->line);
 }
 
@@ -1065,7 +1065,7 @@ ngx_conf_check_num_bounds(ngx_conf_t *cf
         }
 
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "value must be equal or more than %d", bounds->low);
+                           "value must be equal or more than %i", bounds->low);
 
         return NGX_CONF_ERROR;
     }
@@ -1075,7 +1075,7 @@ ngx_conf_check_num_bounds(ngx_conf_t *cf
     }
 
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                       "value must be between %d and %d",
+                       "value must be between %i and %i",
                        bounds->low, bounds->high);
 
     return NGX_CONF_ERROR;
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -73,60 +73,60 @@
 
 
 struct ngx_command_s {
-    ngx_str_t     name;
-    int           type;
-    char       *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-    int           conf;
-    int           offset;
-    void         *post;
+    ngx_str_t             name;
+    ngx_uint_t            type;
+    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+    ngx_uint_t            conf;
+    ngx_uint_t            offset;
+    void                 *post;
 };
 
 #define ngx_null_command   { ngx_null_string, 0, NULL, 0, 0, NULL }
 
 
 struct ngx_open_file_s {
-    ngx_fd_t   fd;
-    ngx_str_t  name;
+    ngx_fd_t              fd;
+    ngx_str_t             name;
 #if 0
     /* e.g. append mode, error_log */
-    int        flags;
+    ngx_uint_t            flags;
     /* e.g. reopen db file */
-    int      (*handler)(void *data, ngx_open_file_t *file);
-    void      *data;
+    ngx_uint_t          (*handler)(void *data, ngx_open_file_t *file);
+    void                 *data;
 #endif
 };
 
 
 struct ngx_module_s {
-    ngx_uint_t       ctx_index;
-    ngx_uint_t       index;
-    void            *ctx;
-    ngx_command_t   *commands;
-    ngx_uint_t       type;
-    ngx_int_t      (*init_module)(ngx_cycle_t *cycle);
-    ngx_int_t      (*init_process)(ngx_cycle_t *cycle);
+    ngx_uint_t            ctx_index;
+    ngx_uint_t            index;
+    void                 *ctx;
+    ngx_command_t        *commands;
+    ngx_uint_t            type;
+    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);
+    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
 #if 0
-    ngx_int_t      (*init_thread)(ngx_cycle_t *cycle);
+    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
 #endif
 };
 
 
 typedef struct {
-    ngx_str_t       name;
-    void         *(*create_conf)(ngx_cycle_t *cycle);
-    char         *(*init_conf)(ngx_cycle_t *cycle, void *conf);
+    ngx_str_t             name;
+    void               *(*create_conf)(ngx_cycle_t *cycle);
+    char               *(*init_conf)(ngx_cycle_t *cycle, void *conf);
 } ngx_core_module_t; 
 
 
 typedef struct {
-    ngx_file_t   file;
-    ngx_buf_t   *buffer;
-    ngx_uint_t   line;
+    ngx_file_t            file;
+    ngx_buf_t            *buffer;
+    ngx_uint_t            line;
 } ngx_conf_file_t;
 
 
 typedef char *(*ngx_conf_handler_pt)(ngx_conf_t *cf,
-                                     ngx_command_t *dummy, void *conf);
+    ngx_command_t *dummy, void *conf);
 
 
 struct ngx_conf_s {
@@ -157,22 +157,22 @@ typedef struct {
 
 typedef struct {
     ngx_conf_post_handler_pt  post_handler;
-    int                       low;
-    int                       high;
+    ngx_int_t                 low;
+    ngx_int_t                 high;
 } ngx_conf_num_bounds_t;
 
 
 typedef struct {
-    ngx_str_t   name;
-    ngx_uint_t  value;
+    ngx_str_t                 name;
+    ngx_uint_t                value;
 } ngx_conf_enum_t;
 
 
 #define NGX_CONF_BITMASK_SET  1
 
 typedef struct {
-    ngx_str_t   name;
-    ngx_uint_t  mask;
+    ngx_str_t                 name;
+    ngx_uint_t                mask;
 } ngx_conf_bitmask_t;
 
 
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -12,6 +12,7 @@ typedef struct ngx_module_s      ngx_mod
 typedef struct ngx_conf_s        ngx_conf_t;
 typedef struct ngx_cycle_s       ngx_cycle_t;
 typedef struct ngx_pool_s        ngx_pool_t;
+typedef struct ngx_chain_s       ngx_chain_t; 
 typedef struct ngx_log_s         ngx_log_t;
 typedef struct ngx_array_s       ngx_array_t;
 typedef struct ngx_open_file_s   ngx_open_file_t;
@@ -51,7 +52,7 @@ typedef void (*ngx_event_handler_pt)(ngx
 #include <ngx_buf.h>
 #include <ngx_array.h>
 #include <ngx_list.h>
-#include <ngx_table.h>
+#include <ngx_hash.h>
 #include <ngx_file.h>
 #include <ngx_files.h>
 #include <ngx_crc.h>
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -54,7 +54,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 
     log = old_cycle->log;
 
-    pool = ngx_create_pool(16 * 1024, log);
+    pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
     if (pool == NULL) {
         return NULL;
     }
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -12,6 +12,11 @@
 #include <ngx_core.h>
 
 
+#ifndef NGX_CYCLE_POOL_SIZE
+#define NGX_CYCLE_POOL_SIZE     16384
+#endif
+
+
 #define NGX_DEBUG_POINTS_STOP   1
 #define NGX_DEBUG_POINTS_ABORT  2
 
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_hash.c
@@ -0,0 +1,160 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+ngx_int_t
+ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
+{
+    u_char      *p;
+    ngx_str_t   *n, *bucket;
+    ngx_uint_t   i, key, size, best, *test, buckets, min_buckets;
+
+    test = ngx_alloc(hash->max_size * sizeof(ngx_uint_t), pool->log);
+    if (test == NULL) {
+        return NGX_ERROR;
+    }
+
+    min_buckets = hash->bucket_limit + 1;
+
+#if (NGX_SUPPRESS_WARN)
+    best = 0;
+#endif
+
+    for (size = 1; size < hash->max_size; size++) {
+
+        buckets = 0;
+
+        for (i = 0; i < size; i++) {
+            test[i] = 0;
+        }
+
+        for (n = (ngx_str_t *) names;
+             n->len;
+             n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+        {
+            key = 0;
+
+            for (i = 0; i < n->len; i++) {
+                key += ngx_tolower(n->data[i]);
+            }
+
+            key %= size;
+
+            if (test[key] == hash->bucket_limit) {
+                break;
+            }
+
+            test[key]++;
+
+            if (buckets < test[key]) {
+                buckets = test[key];
+            }
+        }
+
+        if (n->len == 0) {
+            if (min_buckets > buckets) {
+                min_buckets = buckets;
+                best = size;
+            }
+
+            if (hash->bucket_limit == 1) {
+                break;
+            }
+        }
+    }
+
+    if (min_buckets == hash->bucket_limit + 1) {
+        ngx_log_error(NGX_LOG_EMERG, pool->log, 0,
+                      "could not build the %s hash, you should increase "
+                      "either %s_size: %i or %s_bucket_limit: %i",
+                      hash->name, hash->name, hash->max_size,
+                      hash->name, hash->bucket_limit);
+        ngx_free(test);
+        return NGX_ERROR;
+    }
+
+    hash->buckets = ngx_pcalloc(pool, best * hash->bucket_size);
+    if (hash->buckets == NULL) {
+        ngx_free(test);
+        return NGX_ERROR;
+    }
+
+    if (hash->bucket_limit != 1) {
+
+        for (i = 0; i < best; i++) {
+            test[i] = 0;
+        }
+
+        for (n = (ngx_str_t *) names;
+             n->len;
+             n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+        {
+            key = 0;
+
+            for (i = 0; i < n->len; i++) {
+                key += ngx_tolower(n->data[i]);
+            }
+
+            key %= best;
+
+            test[key]++;
+        }
+
+        for (i = 0; i < best; i++) {
+            if (test[i] == 0) {
+                continue;
+            }
+
+            bucket = ngx_palloc(pool, test[i] * hash->bucket_size);
+            if (bucket == NULL) {
+                ngx_free(test);
+                return NGX_ERROR;
+            }
+
+            hash->buckets[i] = bucket;
+            bucket->len = 0;
+        }
+    }
+
+    for (n = (ngx_str_t *) names;
+         n->len;
+         n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+    {
+        key = 0;
+
+        for (i = 0; i < n->len; i++) {
+            key += ngx_tolower(n->data[i]);
+        }
+
+        key %= best;
+
+        if (hash->bucket_limit == 1) {
+            p = (u_char *) hash->buckets + key * hash->bucket_size;
+            ngx_memcpy(p, n, hash->bucket_size);
+            continue;
+        }
+
+        for (bucket = hash->buckets[key];
+             bucket->len;
+             bucket = (ngx_str_t *) ((char *) bucket + hash->bucket_size))
+        {
+            bucket->len &= 0x7fffffff;
+        }
+
+        ngx_memcpy(bucket, n, hash->bucket_size);
+        bucket->len |= 0x80000000;
+    }
+
+    ngx_free(test);
+
+    hash->hash_size = best;
+    hash->min_buckets = min_buckets;
+
+    return NGX_OK;
+}
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_hash.h
@@ -0,0 +1,37 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_HASH_H_INCLUDED_
+#define _NGX_HASH_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct {
+    void        **buckets;
+    ngx_uint_t    hash_size;
+
+    ngx_uint_t    max_size;
+    ngx_uint_t    bucket_limit;
+    size_t        bucket_size;
+    char         *name;
+    ngx_uint_t    min_buckets;
+} ngx_hash_t;
+
+
+typedef struct {
+    ngx_uint_t  hash;
+    ngx_str_t   key;
+    ngx_str_t   value;
+} ngx_table_elt_t;
+
+
+ngx_int_t ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names);
+
+
+#endif /* _NGX_HASH_H_INCLUDED_ */
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -119,8 +119,10 @@ ngx_output_chain(ngx_output_chain_ctx_t 
                 /* get the free buf */
 
                 if (ctx->free) {
-                    ctx->buf = ctx->free->buf;
-                    ctx->free = ctx->free->next;
+                    cl = ctx->free;
+                    ctx->buf = cl->buf;
+                    ctx->free = cl->next;
+                    ngx_free_chain(ctx->pool, cl);
 
                 } else if (out || ctx->allocated == ctx->bufs.num) {
 
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -22,6 +22,7 @@ ngx_create_pool(size_t size, ngx_log_t *
     p->end = (u_char *) p + size;
     p->next = NULL;
     p->large = NULL;
+    p->chain = NULL;
     p->log = log;
 
     return p;
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -33,6 +33,7 @@ struct ngx_pool_large_s {
 struct ngx_pool_s {
     u_char            *last;
     u_char            *end;
+    ngx_chain_t       *chain;
     ngx_pool_t        *next;
     ngx_pool_large_t  *large;
     ngx_log_t         *log;
deleted file mode 100644
--- a/src/core/ngx_table.h
+++ /dev/null
@@ -1,27 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_TABLE_H_INCLUDED_
-#define _NGX_TABLE_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-
-
-typedef ngx_array_t  ngx_table_t;
-
-typedef struct {
-    ngx_str_t  key;
-    ngx_str_t  value;
-} ngx_table_elt_t;
-
-
-#define ngx_create_table(p, n)  ngx_create_array(p, n, 2 * sizeof(ngx_str_t))
-#define ngx_push_table(t)       ngx_push_array(t)
-
-
-#endif /* _NGX_TABLE_H_INCLUDED_ */
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -84,7 +84,7 @@ static ngx_int_t ngx_event_pipe_read_ups
     ssize_t       n, size;
     ngx_int_t     rc;
     ngx_buf_t    *b;
-    ngx_chain_t  *chain, *cl;
+    ngx_chain_t  *chain, *cl, *ln;
 
     if (p->upstream_eof || p->upstream_error || p->upstream_done) {
         return NGX_OK;
@@ -293,7 +293,9 @@ static ngx_int_t ngx_event_pipe_read_ups
                 }
 
                 n -= size;
+                ln = cl;
                 cl = cl->next;
+                ngx_free_chain(p->pool, ln);
 
             } else {
                 cl->buf->last += n;
@@ -686,8 +688,10 @@ ngx_int_t ngx_event_pipe_copy_input_filt
     }
 
     if (p->free) {
-        b = p->free->buf;
-        p->free = p->free->next;
+        cl = p->free;
+        b = cl->buf;
+        p->free = cl->next;
+        ngx_free_chain(p->pool, cl);
 
     } else {
         b = ngx_alloc_buf(p->pool);
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -396,7 +396,7 @@ ngx_http_fastcgi_handler(ngx_http_reques
 
     u->conf = &flcf->upstream;
 
-    u->location = flcf->location;
+    u->location0 = flcf->location;
 
     u->create_request = ngx_http_fastcgi_create_request;
     u->reinit_request = ngx_http_fastcgi_reinit_request;
@@ -411,10 +411,10 @@ ngx_http_fastcgi_handler(ngx_http_reques
     u->log_ctx = r->connection->log->data;
     u->log_handler = ngx_http_upstream_log_error;
 
-    u->schema.len = sizeof("fastcgi://") - 1;
-    u->schema.data = (u_char *) "fastcgi://";
-    u->uri.len = sizeof("/") - 1;
-    u->uri.data = (u_char *) "/";
+    u->schema0.len = sizeof("fastcgi://") - 1;
+    u->schema0.data = (u_char *) "fastcgi://";
+    u->uri0.len = sizeof("/") - 1;
+    u->uri0.data = (u_char *) "/";
 
     r->upstream = u;
 
@@ -1244,7 +1244,8 @@ ngx_http_fastcgi_reinit_request(ngx_http
 }
 
 
-static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r)
+static ngx_int_t
+ngx_http_fastcgi_process_header(ngx_http_request_t *r)
 {
     u_char                  *start, *last;
     ngx_str_t               *status_line, line;
@@ -2127,16 +2128,16 @@ ngx_http_fastcgi_create_loc_conf(ngx_con
 
     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
+    conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
+
     conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
-
     conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE;
-    conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
     conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE;
-
     conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE; 
     conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE;
     
     conf->upstream.redirect_errors = NGX_CONF_UNSET;
+    conf->upstream.pass_unparsed_uri = NGX_CONF_UNSET;
     conf->upstream.x_powered_by = NGX_CONF_UNSET;
 
     /* "fastcgi_cyclic_temp_file" is disabled */
@@ -2156,25 +2157,21 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
 
     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
                               prev->upstream.connect_timeout, 60000);
+
     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
                               prev->upstream.send_timeout, 60000);
-    ngx_conf_merge_size_value(conf->upstream.send_lowat,
-                              prev->upstream.send_lowat, 0);
 
     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
                               prev->upstream.read_timeout, 60000);
 
-    ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
-                              prev->upstream.redirect_errors, 0);
-
-    ngx_conf_merge_msec_value(conf->upstream.x_powered_by,
-                              prev->upstream.x_powered_by, 1);
-
+    ngx_conf_merge_size_value(conf->upstream.send_lowat,
+                              prev->upstream.send_lowat, 0);
 
     ngx_conf_merge_size_value(conf->upstream.header_buffer_size, 
                               prev->upstream.header_buffer_size,
                               (size_t) ngx_pagesize);
 
+
     ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
                               8, ngx_pagesize);
 
@@ -2267,6 +2264,23 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
                               ngx_garbage_collector_temp_handler, cf);
 
 
+    ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
+                              prev->upstream.redirect_errors, 0);
+
+    ngx_conf_merge_msec_value(conf->upstream.pass_unparsed_uri,
+                              prev->upstream.pass_unparsed_uri, 0);
+
+    if (conf->upstream.pass_unparsed_uri && conf->location->len > 1) {
+        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                      "\"fastcgi_pass_unparsed_uri\" can be set for "
+                      "location \"/\" or given by regular expression.");
+        return NGX_CONF_ERROR;
+    }
+
+    ngx_conf_merge_msec_value(conf->upstream.x_powered_by,
+                              prev->upstream.x_powered_by, 1);
+
+
     ngx_conf_merge_bitmask_value(conf->params, prev->params,
                               (NGX_CONF_BITMASK_SET
                                |NGX_HTTP_FASTCGI_REMOTE_ADDR
@@ -2290,5 +2304,10 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
         conf->vars = prev->vars;
     }
 
+    if (conf->peers == NULL) {
+        conf->peers = prev->peers;
+        conf->upstream = prev->upstream;
+    }
+
     return NGX_CONF_OK;
 }
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -1021,6 +1021,7 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com
     regex->uri = 1;
     regex->args = 1;
     regex->redirect = 0;
+    regex->break_cycle = 0;
     regex->name = value[1];
 
     last = 0;
@@ -1466,6 +1467,7 @@ ngx_http_rewrite_if_condition(ngx_conf_t
         regex->uri = 0;
         regex->args = 0;
         regex->redirect = 0;
+        regex->break_cycle = 0;
         regex->name = value[last];
 
         return NGX_CONF_OK;
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -197,6 +197,12 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *
         return NGX_CONF_ERROR;
     }
 
+#if 0
+    SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL);
+    SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_NO_SSLv3);
+    SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_SINGLE_DH_USE);
+#endif
+
     if (conf->ciphers.len) {
         if (SSL_CTX_set_cipher_list(conf->ssl_ctx,
                                    (const char *) conf->ciphers.data) == 0)
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -1332,6 +1332,11 @@ static char *ngx_http_proxy_merge_loc_co
         conf->x_vars = prev->x_vars;
     }
 
+    if (conf->peers == NULL) {
+        conf->peers = prev->peers;
+        conf->upstream = prev->upstream;
+    }
+
     return NULL;
 }
 
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -90,7 +90,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
     ngx_memzero(&in_ports, sizeof(ngx_array_t));
 #endif
 
-
     /* the main http context */
 
     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
@@ -317,6 +316,22 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
     cmcf->phases[NGX_HTTP_CONTENT_PHASE].type = NGX_OK;
 
 
+    cmcf->headers_in_hash.max_size = 100;
+    cmcf->headers_in_hash.bucket_limit = 1;
+    cmcf->headers_in_hash.bucket_size = sizeof(ngx_http_header_t);
+    cmcf->headers_in_hash.name = "http headers_in";
+
+    if (ngx_hash_init(&cmcf->headers_in_hash, cf->pool, ngx_http_headers_in)
+        != NGX_OK)
+    {
+        return NGX_CONF_ERROR;
+    }
+
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+                   "http headers_in hash size: %ui, max buckets per entry: %ui",
+                    cmcf->headers_in_hash.hash_size,
+                    cmcf->headers_in_hash.min_buckets);
+
     /*
      * create the lists of ports, addresses and server names
      * to quickly find the server core module configuration at run-time
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -32,6 +32,7 @@ typedef struct ngx_http_variable_value_s
 #include <ngx_http_log_module.h>
 #include <ngx_http_core_module.h>
 #include <ngx_http_variables.h>
+#include <ngx_http_script.h>
 
 #if (NGX_HTTP_SSL)
 #include <ngx_http_ssl_module.h>
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -48,6 +48,8 @@ typedef struct {
     ngx_http_phase_t           phases[NGX_HTTP_LAST_PHASE];
     ngx_array_t                index_handlers;
 
+    ngx_hash_t                 headers_in_hash;
+
     ngx_uint_t                 server_names_hash;
     ngx_uint_t                 server_names_hash_threshold;
 
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -11,7 +11,7 @@
 
 ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
 {
-    u_char  ch, *p, *m;
+    u_char  c, ch, *p, *m;
     enum {
         sw_start = 0,
         sw_method,
@@ -109,7 +109,9 @@ ngx_int_t ngx_http_parse_request_line(ng
 
         /* space* before URI */
         case sw_spaces_before_uri:
-            if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+
+            c = (u_char) (ch | 0x20);
+            if (c >= 'a' && c <= 'f') {
                 r->schema_start = p;
                 state = sw_schema;
                 break;
@@ -128,7 +130,9 @@ ngx_int_t ngx_http_parse_request_line(ng
             break;
 
         case sw_schema:
-            if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+
+            c = (u_char) (ch | 0x20);
+            if (c >= 'a' && c <= 'f') {
                 break;
             }
 
@@ -164,8 +168,13 @@ ngx_int_t ngx_http_parse_request_line(ng
             break;
 
         case sw_host:
-            if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')
-                || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-')
+
+            c = (u_char) (ch | 0x20);
+            if (c >= 'a' && c <= 'f') {
+                break;
+            }
+
+            if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-')
             {
                 break;
             }
@@ -204,10 +213,13 @@ ngx_int_t ngx_http_parse_request_line(ng
         /* check "/.", "//", "%", and "\" (Win32) in URI */
         case sw_after_slash_in_uri:
 
-            if ((ch >= 'a' && ch <= 'z')
-                || (ch >= 'A' && ch <= 'Z')
-                || (ch >= '0' && ch <= '9'))
-            {
+            c = (u_char) (ch | 0x20);
+            if (c >= 'a' && c <= 'f') {
+                state = sw_check_uri;
+                break;
+            }
+
+            if (ch >= '0' && ch <= '9') {
                 state = sw_check_uri;
                 break;
             }
@@ -263,10 +275,12 @@ ngx_int_t ngx_http_parse_request_line(ng
         /* check "/", "%" and "\" (Win32) in URI */
         case sw_check_uri:
 
-            if ((ch >= 'a' && ch <= 'z')
-                || (ch >= 'A' && ch <= 'Z')
-                || (ch >= '0' && ch <= '9'))
-            {
+            c = (u_char) (ch | 0x20);
+            if (c >= 'a' && c <= 'f') {
+                break;
+            }
+
+            if (ch >= '0' && ch <= '9') {
                 break;
             }
 
@@ -490,7 +504,8 @@ done:
 
 ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
 {
-    u_char  c, ch, *p;
+    u_char      c, ch, *p;
+    ngx_uint_t  hash;
     enum {
         sw_start = 0,
         sw_name,
@@ -504,6 +519,7 @@ ngx_int_t ngx_http_parse_header_line(ngx
     } state;
 
     state = r->state;
+    hash = r->header_hash;
 
     for (p = b->pos; p < b->last; p++) {
         ch = *p;
@@ -528,14 +544,17 @@ ngx_int_t ngx_http_parse_header_line(ngx
 
                 c = (u_char) (ch | 0x20);
                 if (c >= 'a' && c <= 'z') {
+                    hash = c;
                     break;
                 }
 
                 if (ch == '-') {
+                    hash = ch;
                     break;
                 }
 
                 if (ch >= '0' && ch <= '9') {
+                    hash = ch;
                     break;
                 }
 
@@ -550,6 +569,7 @@ ngx_int_t ngx_http_parse_header_line(ngx
         case sw_name:
             c = (u_char) (ch | 0x20);
             if (c >= 'a' && c <= 'z') {
+                hash += c;
                 break;
             }
 
@@ -560,10 +580,12 @@ ngx_int_t ngx_http_parse_header_line(ngx
             }
 
             if (ch == '-') {
+                hash += ch;
                 break;
             }
 
             if (ch >= '0' && ch <= '9') {
+                hash += ch;
                 break;
             }
 
@@ -681,6 +703,7 @@ ngx_int_t ngx_http_parse_header_line(ngx
 
     b->pos = p;
     r->state = state;
+    r->header_hash = hash;
 
     return NGX_AGAIN;
 
@@ -688,6 +711,7 @@ done:
 
     b->pos = p + 1;
     r->state = sw_start;
+    r->header_hash = hash;
 
     return NGX_OK;
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -344,7 +344,7 @@ void ngx_http_init_request(ngx_event_t *
 
         if (c->ssl == NULL) {
             if (ngx_ssl_create_session(sscf->ssl_ctx, c, NGX_SSL_BUFFER)
-                                                                  == NGX_ERROR)
+                == NGX_ERROR)
             {
                 ngx_http_close_connection(c);
                 return;
@@ -707,12 +707,15 @@ ngx_http_process_request_line(ngx_event_
 static void
 ngx_http_process_request_headers(ngx_event_t *rev)
 {
-    ssize_t              n;
-    ngx_int_t            rc, rv, i;
-    ngx_str_t            header;
-    ngx_table_elt_t     *h, **cookie;
-    ngx_connection_t    *c;
-    ngx_http_request_t  *r;
+    ssize_t                     n;
+    ngx_int_t                   rc, rv;
+    ngx_uint_t                  key;
+    ngx_str_t                   header;
+    ngx_table_elt_t            *h, **cookie;
+    ngx_connection_t           *c;
+    ngx_http_header_t          *hh;
+    ngx_http_request_t         *r;
+    ngx_http_core_main_conf_t  *cmcf;
 
     c = rev->data;
     r = c->data;
@@ -728,6 +731,9 @@ ngx_http_process_request_headers(ngx_eve
         return;
     }
 
+    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+    hh = (ngx_http_header_t *) cmcf->headers_in_hash.buckets;
+
     rc = NGX_AGAIN;
 
     for ( ;; ) {
@@ -791,6 +797,8 @@ ngx_http_process_request_headers(ngx_eve
                 return;
             }
 
+            h->hash = r->header_hash;
+
             h->key.len = r->header_name_end - r->header_name_start;
             h->key.data = r->header_name_start;
             h->key.data[h->key.len] = '\0';
@@ -812,19 +820,13 @@ ngx_http_process_request_headers(ngx_eve
                 *cookie = h;
 
             } else {
-
-                for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) {
-                    if (ngx_http_headers_in[i].name.len != h->key.len) {
-                        continue;
-                    }
-
-                    if (ngx_strcasecmp(ngx_http_headers_in[i].name.data,
-                                       h->key.data) == 0)
-                    {
-                        *((ngx_table_elt_t **) ((char *) &r->headers_in
-                                         + ngx_http_headers_in[i].offset)) = h;
-                        break;
-                    }
+                key = h->hash % cmcf->headers_in_hash.hash_size;
+
+                if (hh[key].name.len == h->key.len
+                    && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
+                {
+                    *((ngx_table_elt_t **)
+                              ((char *) &r->headers_in + hh[key].offset)) = h;
                 }
             }
 
@@ -1237,9 +1239,9 @@ ngx_http_find_virtual_server(ngx_http_re
     ngx_int_t                   rc;
     ngx_uint_t                  i, n, key, found;
     ngx_http_server_name_t     *name;
-    ngx_http_core_main_conf_t  *cmcf;
+    ngx_http_core_loc_conf_t   *clcf;
     ngx_http_core_srv_conf_t   *cscf;
-    ngx_http_core_loc_conf_t   *clcf;
+    ngx_http_core_main_conf_t  *cmcf;
 
     if (r->virtual_names->hash) {
         cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -386,11 +386,12 @@ struct ngx_http_request_s {
     u_char                           *header_name_end;
     u_char                           *header_start;
     u_char                           *header_end;
+    ngx_uint_t                        header_hash;
 };
 
 
-extern ngx_http_header_t ngx_http_headers_in[];
-extern ngx_http_header_t ngx_http_headers_out[];
+extern ngx_http_header_t   ngx_http_headers_in[];
+extern ngx_http_header_t   ngx_http_headers_out[];
 
 
 
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_script.c
@@ -0,0 +1,194 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+ngx_int_t
+ngx_http_script_compile_lite(ngx_conf_t *cf, ngx_array_t *sources,
+    ngx_array_t **lengths, ngx_array_t **values,
+    ngx_http_script_compile_lite_start_pt start,
+    ngx_http_script_compile_lite_end_pt end)
+{
+    uintptr_t                   *code;
+    ngx_uint_t                   i;
+    ngx_table_elt_t             *src;
+    ngx_http_variable_t         *var;
+    ngx_http_script_var_code_t  *var_code;
+
+    if (sources->nelts == 0) {
+        return NGX_OK;
+    }
+
+    if (*lengths == NULL) {
+        *lengths = ngx_array_create(cf->pool, 64, 1);
+        if (*lengths == NULL) {
+            return NGX_ERROR;
+        }
+    }
+
+    if (*values == NULL) {
+        *values = ngx_array_create(cf->pool, 256, 1);
+        if (*values == NULL) {
+            return NGX_ERROR;
+        }
+    }
+
+    src = sources->elts;
+    for (i = 0; i < sources->nelts; i++) {
+
+        if (src[i].value.data[0] == '$') {
+            if (start(&src[i], *lengths, *values, 0) != NGX_OK) {
+                return NGX_ERROR;
+            }
+
+            src[i].value.len--;
+            src[i].value.data++;
+
+            var = ngx_http_add_variable(cf, &src[i].value, 0);
+
+            if (var == NULL) {
+                return NGX_ERROR;
+            }
+
+            var_code = ngx_array_push_n(*lengths,
+                                        sizeof(ngx_http_script_var_code_t));
+            if (var_code == NULL) {
+                return NGX_ERROR;
+            }
+
+            var_code->code = (ngx_http_script_code_pt)
+                                                  ngx_http_script_copy_var_len;
+            var_code->index = var->index;
+
+
+            var_code = ngx_array_push_n(*values,
+                                        sizeof(ngx_http_script_var_code_t));
+            if (var_code == NULL) {
+                return NGX_ERROR;
+            }
+
+            var_code->code = ngx_http_script_copy_var;
+            var_code->index = var->index;
+
+
+            if (end(*lengths, *values) != NGX_OK) {
+                return NGX_ERROR;
+            }
+
+            continue;
+        }
+
+        if (start(&src[i], *lengths, *values, 1) != NGX_OK) {
+            return NGX_ERROR;
+        }
+    }
+
+    code = ngx_array_push_n(*lengths, sizeof(uintptr_t));
+    if (code == NULL) {
+        return NGX_ERROR;
+    }
+
+    *code = (uintptr_t) NULL;
+
+    code = ngx_array_push_n(*values, sizeof(uintptr_t));
+    if (code == NULL) {
+        return NGX_ERROR;
+    }
+
+    *code = (uintptr_t) NULL;
+
+    return NGX_OK;
+}
+
+
+#if 0
+
+static void *
+ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
+{
+    if (*codes == NULL) {
+        *codes = ngx_array_create(pool, 256, 1);
+        if (*codes == NULL) {
+            return NULL;
+        }
+    }
+
+    return ngx_array_push_n(*codes, size);
+}
+
+#endif
+
+
+size_t
+ngx_http_script_copy_len(ngx_http_script_engine_t *e)
+{
+    ngx_http_script_copy_code_t  *code;
+
+    code = (ngx_http_script_copy_code_t *) e->lite.ip;
+
+    e->lite.ip += sizeof(ngx_http_script_copy_code_t);
+
+    return code->len;
+}
+
+
+void
+ngx_http_script_copy(ngx_http_script_engine_t *e)
+{
+    ngx_http_script_copy_code_t  *code;
+
+    code = (ngx_http_script_copy_code_t *) e->lite.ip;
+
+    e->lite.pos = ngx_cpymem(e->lite.pos,
+                             e->lite.ip + sizeof(ngx_http_script_copy_code_t),
+                             code->len);
+
+    e->lite.ip += sizeof(ngx_http_script_copy_code_t)
+            + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
+}
+
+
+size_t
+ngx_http_script_copy_var_len(ngx_http_script_engine_t *e)
+{
+    ngx_http_variable_value_t   *value;
+    ngx_http_script_var_code_t  *code;
+
+    code = (ngx_http_script_var_code_t *) e->lite.ip;
+
+    e->lite.ip += sizeof(ngx_http_script_var_code_t);
+
+    value = ngx_http_get_indexed_variable(e->lite.request, code->index);
+
+    if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) {
+        return 0;
+    }
+
+    return value->text.len;
+}
+
+
+void
+ngx_http_script_copy_var(ngx_http_script_engine_t *e)
+{
+    ngx_http_variable_value_t   *value;
+    ngx_http_script_var_code_t  *code;
+
+    code = (ngx_http_script_var_code_t *) e->lite.ip;
+
+    e->lite.ip += sizeof(ngx_http_script_var_code_t);
+
+    value = ngx_http_get_indexed_variable(e->lite.request, code->index);
+
+    if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) {
+        return;
+    }
+
+    e->lite.pos = ngx_cpymem(e->lite.pos, value->text.data, value->text.len);
+}
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_script.h
@@ -0,0 +1,66 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_HTTP_SCRIPT_H_INCLUDED_
+#define _NGX_HTTP_SCRIPT_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    u_char                         *ip;
+    u_char                         *pos;
+    ngx_http_request_t             *request;
+} ngx_http_script_lite_engine_t;
+
+
+typedef struct {
+    ngx_http_script_lite_engine_t   lite;
+} ngx_http_script_engine_t;
+
+
+typedef void (*ngx_http_script_code_pt) (ngx_http_script_engine_t *e);
+typedef size_t (*ngx_http_script_len_code_pt)
+    (ngx_http_script_lite_engine_t *e);
+
+typedef ngx_int_t (*ngx_http_script_compile_lite_start_pt) (ngx_table_elt_t *h,
+    ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value);
+typedef ngx_int_t (*ngx_http_script_compile_lite_end_pt) (ngx_array_t *lengths,
+    ngx_array_t *values);
+
+
+typedef struct {
+    ngx_http_script_code_pt         code;
+    uintptr_t                       len;
+} ngx_http_script_copy_code_t;
+
+
+typedef struct {
+    ngx_http_script_code_pt         code;
+    uintptr_t                       index;
+} ngx_http_script_var_code_t;
+
+
+ngx_int_t ngx_http_script_compile_lite(ngx_conf_t *cf, ngx_array_t *sources,
+    ngx_array_t **lengths, ngx_array_t **values,
+    ngx_http_script_compile_lite_start_pt start,
+    ngx_http_script_compile_lite_end_pt end);
+
+
+static void *ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes,
+    size_t size);
+
+size_t ngx_http_script_copy_len(ngx_http_script_engine_t *e);
+void ngx_http_script_copy(ngx_http_script_engine_t *e);
+size_t ngx_http_script_copy_var_len(ngx_http_script_engine_t *e);
+void ngx_http_script_copy_var(ngx_http_script_engine_t *e);
+
+
+
+#endif /* _NGX_HTTP_SCRIPT_H_INCLUDED_ */
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -1135,7 +1135,7 @@ u_char *
 ngx_http_upstream_log_error(ngx_log_t *log, u_char *buf, size_t len)
 {
     u_char                 *p;
-    ngx_int_t               escape;
+    uintptr_t               escape;
     ngx_http_log_ctx_t     *ctx;
     ngx_http_request_t     *r;
     ngx_http_upstream_t    *u;
@@ -1153,29 +1153,29 @@ ngx_http_upstream_log_error(ngx_log_t *l
                      &r->connection->addr_text,
                      &r->server_name,
                      &r->unparsed_uri,
-                     &u->schema,
+                     &u->schema0,
                      &peer->peers->peer[peer->cur_peer].name,
                      peer->peers->peer[peer->cur_peer].uri_separator,
-                     &u->uri);
+                     &u->uri0);
     len -= p - buf;
     buf = p;
 
     if (r->quoted_uri) {
-        escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location->len,
-                                    r->uri.len - u->location->len,
+        escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location0->len,
+                                    r->uri.len - u->location0->len,
                                     NGX_ESCAPE_URI);
     } else {
         escape = 0;
     }
 
     if (escape) {
-        if (len >= r->uri.len - u->location->len + escape) {
+        if (len >= r->uri.len - u->location0->len + escape) {
 
-            ngx_escape_uri(buf, r->uri.data + u->location->len,
-                           r->uri.len - u->location->len, NGX_ESCAPE_URI);
+            ngx_escape_uri(buf, r->uri.data + u->location0->len,
+                           r->uri.len - u->location0->len, NGX_ESCAPE_URI);
 
-            buf += r->uri.len - u->location->len + escape;
-            len -= r->uri.len - u->location->len + escape;
+            buf += r->uri.len - u->location0->len + escape;
+            len -= r->uri.len - u->location0->len + escape;
 
             if (r->args.len) {
                 p = ngx_snprintf(buf, len, "?%V", &r->args);
@@ -1186,19 +1186,19 @@ ngx_http_upstream_log_error(ngx_log_t *l
             return ngx_http_log_error_info(r, buf, len);
         }
 
-        p = ngx_palloc(r->pool, r->uri.len - u->location->len + escape);
+        p = ngx_palloc(r->pool, r->uri.len - u->location0->len + escape);
         if (p == NULL) {
             return buf;
         }
 
-        ngx_escape_uri(p, r->uri.data + u->location->len,
-                       r->uri.len - u->location->len, NGX_ESCAPE_URI);
+        ngx_escape_uri(p, r->uri.data + u->location0->len,
+                       r->uri.len - u->location0->len, NGX_ESCAPE_URI);
 
-        p = ngx_cpymem(buf, p, r->uri.len - u->location->len + escape);
+        p = ngx_cpymem(buf, p, r->uri.len - u->location0->len + escape);
 
     } else {
-        p = ngx_cpymem(buf, r->uri.data + u->location->len,
-                       r->uri.len - u->location->len);
+        p = ngx_cpymem(buf, r->uri.data + u->location0->len,
+                       r->uri.len - u->location0->len);
     }
 
     len -= p - buf;
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -55,6 +55,7 @@ typedef struct {
     ngx_bufs_t                  bufs;
 
     ngx_flag_t                  redirect_errors;
+    ngx_flag_t                  pass_unparsed_uri;
     ngx_flag_t                  x_powered_by;
     ngx_flag_t                  cyclic_temp_file;
 
@@ -87,9 +88,9 @@ struct ngx_http_upstream_s {
                                                   ngx_int_t rc);
     ngx_uint_t                  method;
 
-    ngx_str_t                   schema;
-    ngx_str_t                   uri;
-    ngx_str_t                  *location;
+    ngx_str_t                   schema0;
+    ngx_str_t                   uri0;
+    ngx_str_t                  *location0;
 
     ngx_http_log_ctx_t         *log_ctx;
     ngx_log_handler_pt          log_handler;
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -231,6 +231,12 @@ ngx_http_write_filter(ngx_http_request_t
         return NGX_ERROR;
     }
 
+    for (cl = ctx->out; cl && cl != chain; /* void */) {
+        ln = cl;
+        cl = cl->next;
+        ngx_free_chain(r->pool, ln);
+    }
+
     ctx->out = chain;
 
     if (chain || (last && c->buffered)) {
--- a/src/os/unix/ngx_setproctitle.c
+++ b/src/os/unix/ngx_setproctitle.c
@@ -88,7 +88,7 @@ ngx_setproctitle(char *title)
 
     ngx_os_argv[1] = NULL;
 
-    p = ngx_cpystrn((u_char *) ngx_os_argv[0], "nginx: ",
+    p = ngx_cpystrn((u_char *) ngx_os_argv[0], (u_char *) "nginx: ",
                     ngx_os_argv_last - ngx_os_argv[0]);
 
     p = ngx_cpystrn(p, (u_char *) title, ngx_os_argv_last - (char *) p);