summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2005-04-08 15:18:55 +0000
committerIgor Sysoev <igor@sysoev.ru>2005-04-08 15:18:55 +0000
commit02f742b45eb8792053d3880641f45651d645e351 (patch)
tree1d5893bcc89c8f879712aa80f9a98a42f397e2c0
parent87ff72436d289ae7b72a23138262e6d156490927 (diff)
downloadnginx-02f742b45eb8792053d3880641f45651d645e351.tar.gz
nginx-0.1.28-RELEASE importrelease-0.1.28
*) Bugfix: nginx hogs CPU while proxying the huge files. *) Bugfix: nginx could not be built by gcc 4.0 on Linux.
-rw-r--r--auto/sources7
-rw-r--r--conf/mime.types6
-rw-r--r--docs/xml/nginx/changes.xml27
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_buf.c21
-rw-r--r--src/core/ngx_buf.h8
-rw-r--r--src/core/ngx_conf_file.c28
-rw-r--r--src/core/ngx_conf_file.h64
-rw-r--r--src/core/ngx_core.h3
-rw-r--r--src/core/ngx_cycle.c2
-rw-r--r--src/core/ngx_cycle.h5
-rw-r--r--src/core/ngx_hash.c160
-rw-r--r--src/core/ngx_hash.h37
-rw-r--r--src/core/ngx_output_chain.c6
-rw-r--r--src/core/ngx_palloc.c1
-rw-r--r--src/core/ngx_palloc.h1
-rw-r--r--src/core/ngx_table.h27
-rw-r--r--src/event/ngx_event_pipe.c10
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c53
-rw-r--r--src/http/modules/ngx_http_proxy_module.c1209
-rw-r--r--src/http/modules/ngx_http_rewrite_module.c2
-rw-r--r--src/http/modules/ngx_http_ssl_module.c6
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.c5
-rw-r--r--src/http/ngx_http.c17
-rw-r--r--src/http/ngx_http.h1
-rw-r--r--src/http/ngx_http_core_module.h2
-rw-r--r--src/http/ngx_http_parse.c52
-rw-r--r--src/http/ngx_http_request.c44
-rw-r--r--src/http/ngx_http_request.h5
-rw-r--r--src/http/ngx_http_script.c178
-rw-r--r--src/http/ngx_http_script.h56
-rw-r--r--src/http/ngx_http_upstream.c32
-rw-r--r--src/http/ngx_http_upstream.h7
-rw-r--r--src/http/ngx_http_write_filter_module.c6
-rw-r--r--src/os/unix/ngx_setproctitle.c2
35 files changed, 1903 insertions, 189 deletions
diff --git a/auto/sources b/auto/sources
index fd46edd11..1a2abad13 100644
--- 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_ssl_module.c
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 \
diff --git a/conf/mime.types b/conf/mime.types
index f8df51cb2..3785e5388 100644
--- 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;
}
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 3e4626bad..9444bac88 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -9,14 +9,37 @@
<title lang="en">nginx changelog</title>
+<changes ver="0.1.28" date="08.04.2005">
+
+<change type="bugfix">
+<para lang="ru">
+при проксировании больших файлов nginx сильно нагружал процессор.
+</para>
+<para lang="en">
+nginx hogs CPU while proxing the huge files.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+nginx не собирался gcc 4.0 на Linux.
+</para>
+<para lang="en">
+nginx could not be built by gcc 4.0 on Linux.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="0.1.27" date="28.03.2005">
<change type="feature">
<para lang="ru">
-параметр blocked в директиве invalid_referers.
+параметр blocked в директиве valid_referers.
</para>
<para lang="en">
-the "blocked" parameter of the "invalid_referers" directive.
+the "blocked" parameter of the "valid_referers" directive.
</para>
</change>
diff --git a/src/core/nginx.h b/src/core/nginx.h
index d097cf749..9fa141ab7 100644
--- 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"
diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c
index 2f0356ffd..4c1b1d5ac 100644
--- a/src/core/ngx_buf.c
+++ b/src/core/ngx_buf.c
@@ -44,6 +44,27 @@ ngx_create_temp_buf(ngx_pool_t *pool, size_t size)
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;
diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h
index 721b9c2df..96394f9f6 100644
--- 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(ngx_pool_t *pool, ngx_bufs_t *bufs);
#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);
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index e8119fcdd..35ee8b8e0 100644
--- 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 *filename)
}
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_t last)
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_t last)
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_t last)
&& 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_t last)
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_t last)
}
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_t last)
}
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_conf_t *cf, ngx_err_t err,
*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, void *post, void *data)
}
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, void *post, void *data)
}
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;
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index d5a7a6622..4fab8c10c 100644
--- 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;
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 13053f200..9646f6c06 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -12,6 +12,7 @@ typedef struct ngx_module_s ngx_module_t;
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_event_t *ev);
#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>
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 51864e3f7..51042058a 100644
--- 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 *old_cycle)
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;
}
diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h
index face67fe8..b1b53482b 100644
--- 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
diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
new file mode 100644
index 000000000..2c062b709
--- /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;
+}
diff --git a/src/core/ngx_hash.h b/src/core/ngx_hash.h
new file mode 100644
index 000000000..5a4bf5fbc
--- /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_ */
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c
index 313557d8e..fc8a0bf2a 100644
--- 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 *ctx, ngx_chain_t *in)
/* 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) {
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 8faf9a77e..2804dd0ba 100644
--- 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 *log)
p->end = (u_char *) p + size;
p->next = NULL;
p->large = NULL;
+ p->chain = NULL;
p->log = log;
return p;
diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h
index b31008288..bd256e8a9 100644
--- 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;
diff --git a/src/core/ngx_table.h b/src/core/ngx_table.h
deleted file mode 100644
index 5e2f3a94f..000000000
--- 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_ */
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index b5488ba7d..5f9d7c090 100644
--- 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_upstream(ngx_event_pipe_t *p)
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_upstream(ngx_event_pipe_t *p)
}
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_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
}
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);
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 986215ba0..4b92cd46f 100644
--- 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_request_t *r)
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_request_t *r)
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_request_t *r)
}
-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_conf_t *cf)
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
+ 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_t *cf, void *parent, void *child)
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_t *cf, void *parent, void *child)
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_t *cf, void *parent, void *child)
conf->vars = prev->vars;
}
+ if (conf->peers == NULL) {
+ conf->peers = prev->peers;
+ conf->upstream = prev->upstream;
+ }
+
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
new file mode 100644
index 000000000..8020856c3
--- /dev/null
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -0,0 +1,1209 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+ ngx_http_upstream_conf_t upstream;
+
+ ngx_peers_t *peers;
+
+ ngx_array_t *headers_set_len;
+ ngx_array_t *headers_set;
+ ngx_hash_t *headers_set_hash;
+
+ ngx_flag_t preserve_host;
+ ngx_flag_t set_x_url;
+ ngx_flag_t set_x_real_ip;
+ ngx_flag_t add_x_forwarded_for;
+ ngx_flag_t pass_server;
+ ngx_flag_t pass_x_accel_expires;
+
+ ngx_str_t *location0;
+
+ ngx_str_t host_header;
+ ngx_str_t uri0;
+
+ ngx_array_t *headers_sources;
+ ngx_array_t *headers_names;
+} ngx_http_proxy_loc_conf_t;
+
+
+typedef struct {
+ ngx_list_t headers;
+
+ ngx_table_elt_t *date;
+ ngx_table_elt_t *server;
+
+ ngx_table_elt_t *expires;
+ ngx_table_elt_t *cache_control;
+ ngx_table_elt_t *etag;
+ ngx_table_elt_t *x_accel_expires;
+
+ ngx_table_elt_t *connection;
+ ngx_table_elt_t *content_type;
+ ngx_table_elt_t *content_length;
+
+#if (NGX_HTTP_GZIP)
+ ngx_table_elt_t *content_encoding;
+#endif
+
+ ngx_table_elt_t *last_modified;
+ ngx_table_elt_t *location;
+ ngx_table_elt_t *accept_ranges;
+ ngx_table_elt_t *x_pad;
+
+ off_t content_length_n;
+} ngx_http_proxy_headers_in_t;
+
+
+static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
+static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
+static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
+static ngx_int_t ngx_http_proxy_send_header(ngx_http_request_t *r);
+static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
+static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
+ ngx_int_t rc);
+
+static ngx_int_t ngx_http_proxy_compile_header_start(ngx_table_elt_t *h,
+ ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value);
+static ngx_int_t ngx_http_proxy_compile_header_end(ngx_array_t *lengths,
+ ngx_array_t *values);
+
+static ngx_int_t ngx_http_proxy_init(ngx_cycle_t *cycle);
+static ngx_http_variable_value_t *ngx_http_proxy_host_variable
+ (ngx_http_request_t *r, uintptr_t data);
+static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
+ void *parent, void *child);
+
+static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+
+static char *ngx_http_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
+
+static ngx_conf_post_t ngx_http_proxy_lowat_post =
+ { ngx_http_proxy_lowat_check };
+
+static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
+ { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
+ { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
+ { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
+ { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
+ { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
+ { ngx_null_string, 0 }
+};
+
+
+static ngx_command_t ngx_http_proxy_commands[] = {
+
+ { ngx_string("proxy_pass"),
+ NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_proxy_pass,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("proxy_connect_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout),
+ NULL },
+
+ { ngx_string("proxy_send_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout),
+ NULL },
+
+ { ngx_string("proxy_send_lowat"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
+ &ngx_http_proxy_lowat_post },
+
+ { ngx_string("proxy_pass_unparsed_uri"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_unparsed_uri),
+ NULL },
+
+ { ngx_string("proxy_preserve_host"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, preserve_host),
+ NULL },
+
+ { ngx_string("proxy_set_x_url"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, set_x_url),
+ NULL },
+
+ { ngx_string("proxy_set_x_real_ip"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, set_x_real_ip),
+ NULL },
+
+ { ngx_string("proxy_set_x_var"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_proxy_set_x_var,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("proxy_add_x_forwarded_for"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, add_x_forwarded_for),
+ NULL },
+
+ { ngx_string("proxy_header_buffer_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.header_buffer_size),
+ NULL },
+
+ { ngx_string("proxy_read_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout),
+ NULL },
+
+ { ngx_string("proxy_buffers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+ ngx_conf_set_bufs_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs),
+ NULL },
+
+ { ngx_string("proxy_busy_buffers_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size),
+ NULL },
+
+ { ngx_string("proxy_temp_path"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
+ ngx_conf_set_path_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
+ (void *) ngx_garbage_collector_temp_handler },
+
+ { ngx_string("proxy_max_temp_file_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size),
+ NULL },
+
+ { ngx_string("proxy_temp_file_write_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size),
+ NULL },
+
+ { ngx_string("proxy_next_upstream"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
+ ngx_conf_set_bitmask_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
+ &ngx_http_proxy_next_upstream_masks },
+
+ { ngx_string("proxy_pass_server"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, pass_server),
+ NULL },
+
+ { ngx_string("proxy_pass_x_accel_expires"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, pass_x_accel_expires),
+ NULL },
+
+ ngx_null_command
+};
+
+
+ngx_http_module_t ngx_http_proxy_module_ctx = {
+ NULL, /* pre conf */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_http_proxy_create_loc_conf, /* create location configration */
+ ngx_http_proxy_merge_loc_conf /* merge location configration */
+};
+
+
+ngx_module_t ngx_http_proxy_module = {
+ NGX_MODULE,
+ &ngx_http_proxy_module_ctx, /* module context */
+ ngx_http_proxy_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ ngx_http_proxy_init, /* init module */
+ NULL /* init process */
+};
+
+
+static ngx_str_t ngx_http_proxy_methods[] = {
+ ngx_string("GET"),
+ ngx_string("HEAD"),
+ ngx_string("POST")
+};
+
+
+static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
+
+static ngx_str_t ngx_http_proxy_host = ngx_string("PROXY_HOST");
+
+
+#if (NGX_PCRE)
+static ngx_str_t ngx_http_proxy_uri = ngx_string("/");
+#endif
+
+
+#if 0
+
+ngx_http_header_t ngx_http_proxy_headers_in[] = {
+ { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) },
+ { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) },
+
+ { ngx_string("Expires"), offsetof(ngx_http_proxy_headers_in_t, expires) },
+ { ngx_string("Cache-Control"),
+ offsetof(ngx_http_proxy_headers_in_t, cache_control) },
+ { ngx_string("ETag"), offsetof(ngx_http_proxy_headers_in_t, etag) },
+ { ngx_string("X-Accel-Expires"),
+ offsetof(ngx_http_proxy_headers_in_t, x_accel_expires) },
+
+ { ngx_string("Connection"),
+ offsetof(ngx_http_proxy_headers_in_t, connection) },
+ { ngx_string("Content-Type"),
+ offsetof(ngx_http_proxy_headers_in_t, content_type) },
+ { ngx_string("Content-Length"),
+ offsetof(ngx_http_proxy_headers_in_t, content_length) },
+
+#if (NGX_HTTP_GZIP)
+ { ngx_string("Content-Encoding"),
+ offsetof(ngx_http_proxy_headers_in_t, content_encoding) },
+#endif
+
+ { ngx_string("Last-Modified"),
+ offsetof(ngx_http_proxy_headers_in_t, last_modified) },
+ { ngx_string("Location"),
+ offsetof(ngx_http_proxy_headers_in_t, location) },
+ { ngx_string("Accept-Ranges"),
+ offsetof(ngx_http_proxy_headers_in_t, accept_ranges) },
+ { ngx_string("X-Pad"), offsetof(ngx_http_proxy_headers_in_t, x_pad) },
+
+ { ngx_null_string, 0 }
+};
+
+#endif
+
+
+static ngx_int_t
+ngx_http_proxy_handler(ngx_http_request_t *r)
+{
+ ngx_int_t rc;
+ ngx_http_upstream_t *u;
+ ngx_http_proxy_loc_conf_t *plcf;
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
+ if (u == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ u->peer.log = r->connection->log;
+ u->peer.log_error = NGX_ERROR_ERR;
+ u->peer.peers = plcf->peers;
+ u->peer.tries = plcf->peers->number;
+#if (NGX_THREADS)
+ u->peer.lock = &r->connection->lock;
+#endif
+
+ u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
+
+ u->conf = &plcf->upstream;
+
+ u->create_request = ngx_http_proxy_create_request;
+ u->reinit_request = ngx_http_proxy_reinit_request;
+ u->process_header = ngx_http_proxy_process_header;
+ u->send_header = ngx_http_proxy_send_header;
+ u->abort_request = ngx_http_proxy_abort_request;
+ u->finalize_request = ngx_http_proxy_finalize_request;
+
+ u->pipe.input_filter = ngx_event_pipe_copy_input_filter;
+
+ u->log_ctx = r->connection->log->data;
+ u->log_handler = ngx_http_upstream_log_error;
+
+ u->schema0.len = sizeof("http://") - 1;
+ u->schema0.data = (u_char *) "http://";
+ u->uri0 = plcf->uri0;
+ u->location0 = plcf->location0;
+
+ r->upstream = u;
+
+ rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
+
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+ return rc;
+ }
+
+ return NGX_DONE;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_create_request(ngx_http_request_t *r)
+{
+ size_t len;
+ ngx_uint_t i, key;
+ uintptr_t escape;
+ ngx_buf_t *b;
+ ngx_str_t *hh;
+ ngx_chain_t *cl;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *header;
+ ngx_http_upstream_t *u;
+ ngx_http_proxy_loc_conf_t *plcf;
+ ngx_http_script_code_pt code;
+ ngx_http_script_len_code_pt lcode;
+ ngx_http_script_lite_engine_t e;
+
+ u = r->upstream;
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
+
+ if (u->method) {
+ len += ngx_http_proxy_methods[u->method - 1].len + u->uri0.len;
+ } else {
+ len += r->method_name.len + u->uri0.len;
+ }
+
+ escape = 0;
+
+ if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) {
+ len += r->unparsed_uri.len - 1;
+
+ } else {
+ if (r->quoted_uri) {
+ escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location0->len,
+ r->uri.len - u->location0->len,
+ NGX_ESCAPE_URI);
+ }
+
+ len += r->uri.len - u->location0->len + escape
+ + sizeof("?") - 1 + r->args.len;
+ }
+
+
+ e.ip = plcf->headers_set_len->elts;
+ e.request = r;
+
+ while (*(uintptr_t *) e.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) e.ip;
+ len += lcode(&e);
+ }
+
+
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+ hh = (ngx_str_t *) plcf->headers_set_hash->buckets;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ key = header[i].hash % plcf->headers_set_hash->hash_size;
+
+ if (hh[key].len == header[i].key.len
+ && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
+ {
+ continue;
+ }
+
+ len += header[i].key.len + sizeof(": ") - 1
+ + header[i].value.len + sizeof(CRLF) - 1;
+ }
+
+ b = ngx_create_temp_buf(r->pool, len);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+ cl->next = NULL;
+
+ r->request_body->bufs = cl;
+
+
+ /* the request line */
+
+ if (u->method) {
+ b->last = ngx_cpymem(b->last,
+ ngx_http_proxy_methods[u->method - 1].data,
+ ngx_http_proxy_methods[u->method - 1].len);
+ } else {
+ b->last = ngx_cpymem(b->last, r->method_name.data, r->method_name.len);
+ }
+
+ b->last = ngx_cpymem(b->last, u->uri0.data, u->uri0.len);
+
+ if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) {
+ b->last = ngx_cpymem(b->last, r->unparsed_uri.data + 1,
+ r->unparsed_uri.len - 1);
+ } else {
+ if (escape) {
+ ngx_escape_uri(b->last, r->uri.data + u->location0->len,
+ r->uri.len - u->location0->len, NGX_ESCAPE_URI);
+ b->last += r->uri.len - u->location0->len + escape;
+
+ } else {
+ b->last = ngx_cpymem(b->last, r->uri.data + u->location0->len,
+ r->uri.len - u->location0->len);
+ }
+
+ if (r->args.len > 0) {
+ *b->last++ = '?';
+ b->last = ngx_cpymem(b->last, r->args.data, r->args.len);
+ }
+ }
+
+ b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
+ sizeof(ngx_http_proxy_version) - 1);
+
+
+ e.ip = plcf->headers_set->elts;
+ e.pos = b->last;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
+ }
+
+ b->last = e.pos;
+
+
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ key = header[i].hash % plcf->headers_set_hash->hash_size;
+
+ if (hh[key].len == header[i].key.len
+ && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
+ {
+ continue;
+ }
+
+ b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len);
+
+ *b->last++ = ':'; *b->last++ = ' ';
+
+ b->last = ngx_cpymem(b->last, header[i].value.data,
+ header[i].value.len);
+
+ *b->last++ = CR; *b->last++ = LF;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http proxy header: \"%V: %V\"",
+ &header[i].key, &header[i].value);
+ }
+
+ /* add "\r\n" at the header end */
+ *b->last++ = CR; *b->last++ = LF;
+
+#if (NGX_DEBUG)
+ {
+ ngx_str_t s;
+
+ s.len = b->last - b->pos;
+ s.data = b->pos;
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http proxy header:\n\"%V\"", &s);
+ }
+#endif
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_reinit_request(ngx_http_request_t *r)
+{
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_process_header(ngx_http_request_t *r)
+{
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_send_header(ngx_http_request_t *r)
+{
+ return NGX_OK;
+}
+
+
+static void
+ngx_http_proxy_abort_request(ngx_http_request_t *r)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "abort http proxy request");
+
+ return;
+}
+
+
+static void
+ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "finalize http proxy request");
+
+ return;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_init(ngx_cycle_t *cycle)
+{
+#if 0
+ ngx_http_variable_t *var;
+
+ var = ngx_http_add_variable(cf, &ngx_http_proxy_host, 1);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->handler = ngx_http_proxy_host_variable;
+#endif
+
+ return NGX_OK;
+
+#if 0
+ ngx_http_log_op_name_t *op;
+
+ for (op = ngx_http_proxy_log_fmt_ops; op->name.len; op++) { /* void */ }
+ op->run = NULL;
+
+ for (op = ngx_http_log_fmt_ops; op->run; op++) {
+ if (op->name.len == 0) {
+ op = (ngx_http_log_op_name_t *) op->run;
+ }
+ }
+
+ op->run = (ngx_http_log_op_run_pt) ngx_http_proxy_log_fmt_ops;
+
+#endif
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data)
+{
+ ngx_http_variable_value_t *var;
+ ngx_http_proxy_loc_conf_t *plcf;
+
+ var = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (var == NULL) {
+ return NULL;
+ }
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ var->value = 0;
+ var->text = plcf->host_header;
+
+ return var;
+}
+
+
+static void *
+ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
+{
+ ngx_http_proxy_loc_conf_t *conf;
+
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
+ if (conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ /*
+ * set by ngx_pcalloc():
+ *
+ * conf->upstream.bufs.num = 0;
+ * conf->upstream.path = NULL;
+ * conf->upstream.next_upstream = 0;
+ * conf->upstream.temp_path = NULL;
+ */
+
+ 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.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;
+
+ /* "proxy_cyclic_temp_file" is disabled */
+ conf->upstream.cyclic_temp_file = 0;
+
+ conf->preserve_host = NGX_CONF_UNSET;
+ conf->set_x_url = NGX_CONF_UNSET;
+ conf->set_x_real_ip = NGX_CONF_UNSET;
+ conf->add_x_forwarded_for = NGX_CONF_UNSET;
+
+ conf->pass_server = NGX_CONF_UNSET;
+ conf->pass_x_accel_expires = NGX_CONF_UNSET;
+
+ return conf;
+}
+
+
+static char *
+ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_http_proxy_loc_conf_t *prev = parent;
+ ngx_http_proxy_loc_conf_t *conf = child;
+
+ size_t size;
+ ngx_str_t *name;
+ ngx_table_elt_t *src;
+ ngx_http_variable_t *var;
+
+ 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_msec_value(conf->upstream.read_timeout,
+ prev->upstream.read_timeout, 60000);
+
+ 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);
+
+ if (conf->upstream.bufs.num < 2) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "there must be at least 2 \"proxy_buffers\"");
+ return NGX_CONF_ERROR;
+ }
+
+
+ size = conf->upstream.header_buffer_size;
+ if (size < conf->upstream.bufs.size) {
+ size = conf->upstream.bufs.size;
+ }
+
+
+ ngx_conf_merge_size_value(conf->upstream.busy_buffers_size,
+ prev->upstream.busy_buffers_size,
+ NGX_CONF_UNSET_SIZE);
+
+ if (conf->upstream.busy_buffers_size == NGX_CONF_UNSET_SIZE) {
+ conf->upstream.busy_buffers_size = 2 * size;
+
+ } else if (conf->upstream.busy_buffers_size < size) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_busy_buffers_size\" must be equal or bigger than "
+ "maximum of the value of \"proxy_header_buffer_size\" and "
+ "one of the \"proxy_buffers\"");
+
+ return NGX_CONF_ERROR;
+
+ } else if (conf->upstream.busy_buffers_size
+ > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_busy_buffers_size\" must be less than "
+ "the size of all \"proxy_buffers\" minus one buffer");
+
+ return NGX_CONF_ERROR;
+ }
+
+
+ ngx_conf_merge_size_value(conf->upstream.temp_file_write_size,
+ prev->upstream.temp_file_write_size,
+ NGX_CONF_UNSET_SIZE);
+
+ if (conf->upstream.temp_file_write_size == NGX_CONF_UNSET_SIZE) {
+ conf->upstream.temp_file_write_size = 2 * size;
+
+ } else if (conf->upstream.temp_file_write_size < size) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_temp_file_write_size\" must be equal or bigger than "
+ "maximum of the value of \"proxy_header_buffer_size\" and "
+ "one of the \"proxy_buffers\"");
+
+ return NGX_CONF_ERROR;
+ }
+
+
+ ngx_conf_merge_size_value(conf->upstream.max_temp_file_size,
+ prev->upstream.max_temp_file_size,
+ NGX_CONF_UNSET_SIZE);
+
+ if (conf->upstream.max_temp_file_size == NGX_CONF_UNSET_SIZE) {
+
+ conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
+
+ } else if (conf->upstream.max_temp_file_size != 0
+ && conf->upstream.max_temp_file_size < size)
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
+ "the temporary files usage or must be equal or bigger than "
+ "maximum of the value of \"fastcgi_header_buffer_size\" and "
+ "one of the \"fastcgi_buffers\"");
+
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
+ prev->upstream.next_upstream,
+ (NGX_CONF_BITMASK_SET
+ |NGX_HTTP_UPSTREAM_FT_ERROR
+ |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
+
+ 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->location0->len > 1) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "\"proxy_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_value(conf->preserve_host, prev->preserve_host, 0);
+ ngx_conf_merge_value(conf->set_x_url, prev->set_x_url, 0);
+ ngx_conf_merge_value(conf->set_x_real_ip, prev->set_x_real_ip, 0);
+ ngx_conf_merge_value(conf->add_x_forwarded_for,
+ prev->add_x_forwarded_for, 0);
+
+ if (conf->peers == NULL) {
+ conf->peers = prev->peers;
+ conf->upstream = prev->upstream;
+ }
+
+ if (conf->headers_set_hash == NULL) {
+ conf->headers_set_len = prev->headers_set_len;
+ conf->headers_set = prev->headers_set;
+ conf->headers_set_hash = prev->headers_set_hash;
+ }
+
+ if (conf->headers_set_hash == NULL) {
+
+ if (conf->headers_names == NULL) {
+ conf->headers_names = ngx_array_create(cf->pool, 4,
+ sizeof(ngx_str_t));
+ if (conf->headers_names == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ if (conf->headers_sources == NULL) {
+ conf->headers_sources = ngx_array_create(cf->pool, 4,
+ sizeof(ngx_table_elt_t));
+ if (conf->headers_sources == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ /* STUB */
+ var = ngx_http_add_variable(cf, &ngx_http_proxy_host, 0);
+ if (var == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ var->handler = ngx_http_proxy_host_variable;
+ /**/
+
+
+ name = ngx_array_push(conf->headers_names);
+ if (name == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ name->len = sizeof("Host") - 1;
+ name->data = (u_char *) "Host";
+
+ src = ngx_array_push(conf->headers_sources);
+ if (src == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ src->hash = 0;
+ src->key.len = sizeof("Host") - 1;
+ src->key.data = (u_char *) "Host";
+ src->value.len = sizeof("$PROXY_HOST") - 1;
+ src->value.data = (u_char *) "$PROXY_HOST";
+
+
+ name = ngx_array_push(conf->headers_names);
+ if (name == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ name->len = sizeof("Connection") - 1;
+ name->data = (u_char *) "Connection";
+
+ src = ngx_array_push(conf->headers_sources);
+ if (src == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ src->hash = 0;
+ src->key.len = sizeof("Connection") - 1;
+ src->key.data = (u_char *) "Connection";
+ src->value.len = sizeof("close") - 1;
+ src->value.data = (u_char *) "close";
+
+
+ name = ngx_array_push(conf->headers_names);
+ if (name == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ name->len = 0;
+ name->data = NULL;
+
+
+ if (ngx_http_script_compile_lite(cf, conf->headers_sources,
+ &conf->headers_set_len, &conf->headers_set,
+ ngx_http_proxy_compile_header_start,
+ ngx_http_proxy_compile_header_end) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+
+ conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash_t));
+ if (conf->headers_set_hash == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ conf->headers_set_hash->max_size = 100;
+ conf->headers_set_hash->bucket_limit = 1;
+ conf->headers_set_hash->bucket_size = sizeof(ngx_str_t);
+ conf->headers_set_hash->name = "proxy_headers";
+
+ if (ngx_hash_init(conf->headers_set_hash, cf->pool,
+ conf->headers_names->elts) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+#if 0
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+#endif
+ ngx_log_error(NGX_LOG_NOTICE, cf->log, 0,
+ "proxy_headers hash size: %ui, "
+ "max buckets per entry: %ui",
+ conf->headers_set_hash->hash_size,
+ conf->headers_set_hash->min_buckets);
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_compile_header_start(ngx_table_elt_t *h,
+ ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value)
+{
+ u_char *p;
+ size_t size;
+ ngx_http_script_copy_code_t *copy;
+
+ copy = ngx_array_push_n(lengths, sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len;
+ copy->len = h->key.len + sizeof(": ") - 1;
+
+ if (value) {
+ copy->len += h->value.len + sizeof(CRLF) - 1;
+ }
+
+ size = (copy->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+
+ copy = ngx_array_push_n(values,
+ sizeof(ngx_http_script_copy_code_t) + size);
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = ngx_http_script_copy;
+ copy->len = h->key.len + sizeof(": ") - 1;
+
+ if (value) {
+ copy->len += h->value.len + sizeof(CRLF) - 1;
+ }
+
+ p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+
+ p = ngx_cpymem(p, h->key.data, h->key.len);
+ p = ngx_cpymem(p, ": ", sizeof(": ") - 1);
+
+ if (value) {
+ p = ngx_cpymem(p, h->value.data, h->value.len);
+ ngx_memcpy(p, CRLF, sizeof(CRLF) - 1);
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_compile_header_end(ngx_array_t *lengths, ngx_array_t *values)
+{
+ size_t size;
+ ngx_http_script_copy_code_t *copy;
+
+ copy = ngx_array_push_n(lengths, sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len;
+ copy->len = sizeof(CRLF) - 1;
+
+ size = (sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ copy = ngx_array_push_n(values,
+ sizeof(ngx_http_script_copy_code_t) + size);
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = ngx_http_script_copy;
+ copy->len = sizeof(CRLF) - 1;
+
+ ngx_memcpy((u_char *) copy + sizeof(ngx_http_script_copy_code_t),
+ CRLF, sizeof(CRLF) - 1);
+
+ return NGX_OK;
+}
+
+
+static char *
+ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_proxy_loc_conf_t *lcf = conf;
+
+ ngx_uint_t i;
+ ngx_str_t *value, *url;
+ ngx_inet_upstream_t inet_upstream;
+ ngx_http_core_loc_conf_t *clcf;
+#if (NGX_HAVE_UNIX_DOMAIN)
+ ngx_unix_domain_upstream_t unix_upstream;
+#endif
+
+ value = cf->args->elts;
+
+ url = &value[1];
+
+ if (ngx_strncasecmp(url->data, "http://", 7) != 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_strncasecmp(url->data + 7, "unix:", 5) == 0) {
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
+
+ unix_upstream.name = *url;
+ unix_upstream.url.len = url->len - 7;
+ unix_upstream.url.data = url->data + 7;
+ unix_upstream.uri_part = 1;
+
+ lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
+ if (lcf->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ lcf->peers->peer[0].uri_separator = ":";
+
+ lcf->host_header.len = sizeof("localhost") - 1;
+ lcf->host_header.data = (u_char *) "localhost";
+ lcf->uri0 = unix_upstream.uri;
+#if 0
+ STUB
+ lcf->upstream->default_port = 1;
+#endif
+
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the unix domain sockets are not supported "
+ "on this platform");
+ return NGX_CONF_ERROR;
+
+#endif
+
+ } else {
+ ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
+
+ inet_upstream.name = *url;
+ inet_upstream.url.len = url->len - 7;
+ inet_upstream.url.data = url->data + 7;
+ inet_upstream.default_port_value = 80;
+ inet_upstream.uri_part = 1;
+
+ lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
+ if (lcf->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; i < lcf->peers->number; i++) {
+ lcf->peers->peer[i].uri_separator = ":";
+ }
+
+ lcf->host_header = inet_upstream.host_header;
+ lcf->uri0 = inet_upstream.uri;
+#if 0
+ STUB
+ lcf->port_text = inet_upstream.port_text;
+ lcf->upstream->default_port = inet_upstream.default_port;
+#endif
+ }
+
+ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+
+ clcf->handler = ngx_http_proxy_handler;
+
+#if (NGX_PCRE)
+ lcf->location0 = clcf->regex ? &ngx_http_proxy_uri : &clcf->name;
+#else
+ lcf->location0 = &clcf->name;
+#endif
+
+ if (clcf->name.data[clcf->name.len - 1] == '/') {
+ clcf->auto_redirect = 1;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
+{
+#if (NGX_FREEBSD)
+ ssize_t *np = data;
+
+ if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_send_lowat\" must be less than %d "
+ "(sysctl net.inet.tcp.sendspace)",
+ ngx_freebsd_net_inet_tcp_sendspace);
+
+ return NGX_CONF_ERROR;
+ }
+
+#elif !(NGX_HAVE_SO_SNDLOWAT)
+ ssize_t *np = data;
+
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "\"proxy_send_lowat\" is not supported, ignored");
+
+ *np = 0;
+
+#endif
+
+ return NGX_CONF_OK;
+}
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index ed1067b9f..1da475cc8 100644
--- 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_command_t *cmd, void *conf)
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 *cf, ngx_http_rewrite_loc_conf_t *lcf)
regex->uri = 0;
regex->args = 0;
regex->redirect = 0;
+ regex->break_cycle = 0;
regex->name = value[last];
return NGX_CONF_OK;
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index 1c4128ca1..c18c493ac 100644
--- 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 *cf, void *parent, void *child)
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)
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 9addfc23a..12d417176 100644
--- 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_conf(ngx_conf_t *cf,
conf->x_vars = prev->x_vars;
}
+ if (conf->peers == NULL) {
+ conf->peers = prev->peers;
+ conf->upstream = prev->upstream;
+ }
+
return NULL;
}
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 2c97d7190..e2d5fe41e 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -90,7 +90,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
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_command_t *cmd, void *conf)
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
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index 4758e84c1..ded94e2ca 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -32,6 +32,7 @@ typedef struct ngx_http_variable_value_s ngx_http_variable_value_t;
#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>
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index f8c601790..ac572d6c9 100644
--- 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;
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 34336adf5..5a9685c86 100644
--- 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(ngx_http_request_t *r, ngx_buf_t *b)
/* 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(ngx_http_request_t *r, ngx_buf_t *b)
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(ngx_http_request_t *r, ngx_buf_t *b)
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(ngx_http_request_t *r, ngx_buf_t *b)
/* 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(ngx_http_request_t *r, ngx_buf_t *b)
/* 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_http_request_t *r, ngx_buf_t *b)
} 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_http_request_t *r, ngx_buf_t *b)
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_http_request_t *r, ngx_buf_t *b)
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_http_request_t *r, ngx_buf_t *b)
}
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_http_request_t *r, ngx_buf_t *b)
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;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 1527af24e..48b735779 100644
--- 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 *rev)
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_t *rev)
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_event_t *rev)
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_event_t *rev)
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_event_t *rev)
*cookie = h;
} else {
+ key = h->hash % cmcf->headers_in_hash.hash_size;
- 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;
- }
+ 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_request_t *r)
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_srv_conf_t *cscf;
ngx_http_core_loc_conf_t *clcf;
+ ngx_http_core_srv_conf_t *cscf;
+ ngx_http_core_main_conf_t *cmcf;
if (r->virtual_names->hash) {
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 1b0680cfe..d9889c82e 100644
--- 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[];
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index e80824b30..c7eb07455 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -9,46 +9,186 @@
#include <ngx_http.h>
-u_char *ngx_http_script_copy(ngx_http_request_t *r, u_char *buf, void *data)
+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)
{
- u_char **p = data;
+ 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;
- ngx_http_script_code_t *code;
+ if (sources->nelts == 0) {
+ return NGX_OK;
+ }
- code = (ngx_http_script_code_t *)
- ((char *) data - sizeof(ngx_http_script_code_t));
+ if (*lengths == NULL) {
+ *lengths = ngx_array_create(cf->pool, 64, 1);
+ if (*lengths == NULL) {
+ return NGX_ERROR;
+ }
+ }
- return ngx_cpymem(buf, *p, code->data_len);
+ 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;
}
-u_char *ngx_http_script_header_in(ngx_http_request_t *r,
- u_char *buf, void *data)
+#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)
{
- size_t *offset = data;
+ ngx_http_script_copy_code_t *code;
- ngx_table_elt_t *h;
+ code = (ngx_http_script_copy_code_t *) e->lite.ip;
- h = *(ngx_table_elt_t **) (((char *) r->headers_in) + *offset);
+ e->lite.ip += sizeof(ngx_http_script_copy_code_t);
- return ngx_cpymem(p, h->value.data, h->value.len);
+ return code->len;
}
-u_char *ngx_http_script_request_line(ngx_http_request_t *r,
- u_char *buf, void *data)
+void
+ngx_http_script_copy(ngx_http_script_engine_t *e)
{
- return ngx_cpymem(p, r->request_line.data, r->request_line.len);
+ 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));
}
-u_char *ngx_http_script_status(ngx_http_request_t *r, u_char *buf, void *data)
+size_t
+ngx_http_script_copy_var_len(ngx_http_script_engine_t *e)
{
- return ngx_sprintf(buf, "%ui", r->headers_out.status);
+ 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;
}
-u_char *ngx_http_script_sent(ngx_http_request_t *r, u_char *buf, void *data)
+void
+ngx_http_script_copy_var(ngx_http_script_engine_t *e)
{
- return ngx_sprintf(buf, "%O", r->connection->sent);
+ 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);
}
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index 658faaa9b..fae2b7bb1 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -13,14 +13,54 @@
#include <ngx_http.h>
-typedef u_char *(*ngx_http_script_code_pt) (ngx_http_request_t *r,
- u_char *buf, void *data);
-
-typedef struct ngx_http_script_code_s {
- size_t data_len;
- size_t code_len;
- ngx_http_script_code_pt code;
-} ngx_http_script_code_t;
+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_ */
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 89dee0e38..3dab5c39d 100644
--- 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 *log, u_char *buf, size_t len)
&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 *log, u_char *buf, size_t len)
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;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index c722152a2..c1bc0d9e7 100644
--- 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;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 8883907ae..a9526972b 100644
--- 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 *r, ngx_chain_t *in)
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)) {
diff --git a/src/os/unix/ngx_setproctitle.c b/src/os/unix/ngx_setproctitle.c
index 25bbc9b1e..712c22c98 100644
--- 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);