summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2006-04-05 13:40:54 +0000
committerIgor Sysoev <igor@sysoev.ru>2006-04-05 13:40:54 +0000
commit6d16e1e1df3e9a68b3dabd583ea2361867b9aa83 (patch)
tree1375fdd9994ce3915280665135ea29d531e284c8
parent0d20332bb895aa144d976b5deceef95df7572c6b (diff)
nginx-0.3.36-RELEASE importrelease-0.3.36
*) Feature: the ngx_http_addition_filter_module. *) Feature: the "proxy_pass" and "fastcgi_pass" directives may be used inside the "if" block. *) Feature: the "proxy_ignore_client_abort" and "fastcgi_ignore_client_abort" directives. *) Feature: the "$request_completion" variable. *) Feature: the ngx_http_perl_module supports the $r->request_method and $r->remote_addr. *) Feature: the ngx_http_ssi_module supports the "elif" command. *) Bugfix: the "\/" string in the expression of the "if" command of the ngx_http_ssi_module was treated incorrectly. *) Bugfix: in the regular expressions in the "if" command of the ngx_http_ssi_module. *) Bugfix: if the relative path was specified in the "client_body_temp_path", "proxy_temp_path", "fastcgi_temp_path", and "perl_modules" directives, then the directory was used relatively to a current path but not to a server prefix.
-rw-r--r--auto/modules6
-rw-r--r--auto/options2
-rw-r--r--auto/os/linux4
-rw-r--r--auto/sources4
-rw-r--r--docs/xml/nginx/changes.xml98
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_conf_file.c19
-rw-r--r--src/core/ngx_file.c7
-rw-r--r--src/core/ngx_palloc.c40
-rw-r--r--src/http/modules/ngx_http_addition_filter_module.c228
-rw-r--r--src/http/modules/ngx_http_chunked_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c14
-rw-r--r--src/http/modules/ngx_http_memcached_module.c2
-rw-r--r--src/http/modules/ngx_http_proxy_module.c22
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c63
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.h10
-rw-r--r--src/http/modules/perl/nginx.xs29
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c49
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_cache.c628
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.c1512
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.h275
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_header.c206
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_parse.c216
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_upstream.c1656
-rw-r--r--src/http/ngx_http_request.c5
-rw-r--r--src/http/ngx_http_request.h2
-rw-r--r--src/http/ngx_http_upstream.c17
-rw-r--r--src/http/ngx_http_upstream.h1
-rw-r--r--src/http/ngx_http_variables.c29
29 files changed, 575 insertions, 4573 deletions
diff --git a/auto/modules b/auto/modules
index ef3a35d94..56dad56de 100644
--- a/auto/modules
+++ b/auto/modules
@@ -78,6 +78,7 @@ fi
# ngx_http_postpone_filter
# ngx_http_charset_filter
# ngx_http_ssi_filter
+# ngx_http_addition_filter
# ngx_http_userid_filter
# ngx_http_headers_filter
# ngx_http_copy_filter
@@ -114,6 +115,11 @@ if [ $HTTP_SSI = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS"
fi
+if [ $HTTP_ADDITION = YES ]; then
+ HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_ADDITION_FILTER_MODULE"
+ HTTP_SRCS="$HTTP_SRCS $HTTP_ADDITION_SRCS"
+fi
+
if [ $HTTP_USERID = YES ]; then
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_USERID_FILTER_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS"
diff --git a/auto/options b/auto/options
index 4ff11000c..f80b5fc14 100644
--- a/auto/options
+++ b/auto/options
@@ -52,6 +52,7 @@ HTTP_SSL=NO
HTTP_SSI=YES
HTTP_POSTPONE=NO
HTTP_REALIP=NO
+HTTP_ADDITION=NO
HTTP_ACCESS=YES
HTTP_AUTH_BASIC=YES
HTTP_USERID=YES
@@ -139,6 +140,7 @@ do
--with-http_ssl_module) HTTP_SSL=YES ;;
--with-http_realip_module) HTTP_REALIP=YES ;;
+ --with-http_addition_module) HTTP_ADDITION=YES ;;
--without-http_charset_module) HTTP_CHARSET=NO ;;
--without-http_gzip_module) HTTP_GZIP=NO ;;
--without-http_ssi_module) HTTP_SSI=NO ;;
diff --git a/auto/os/linux b/auto/os/linux
index a7a8d713d..413648633 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -59,7 +59,7 @@ fi
# sendfile()
-CC_AUX_FLAGS="-D_GNU_SOURCE"
+CC_AUX_FLAGS="$CC_AUX_FLAGS -D_GNU_SOURCE"
ngx_feature="sendfile()"
ngx_feature_name="NGX_HAVE_SENDFILE"
ngx_feature_run=yes
@@ -79,7 +79,7 @@ fi
# sendfile64()
-CC_AUX_FLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
+CC_AUX_FLAGS="$CC_AUX_FLAGS -D_FILE_OFFSET_BITS=64"
ngx_feature="sendfile64()"
ngx_feature_name="NGX_HAVE_SENDFILE64"
ngx_feature_run=yes
diff --git a/auto/sources b/auto/sources
index 20866f699..4731f4878 100644
--- a/auto/sources
+++ b/auto/sources
@@ -319,6 +319,10 @@ HTTP_REALIP_MODULE=ngx_http_realip_module
HTTP_REALIP_SRCS=src/http/modules/ngx_http_realip_module.c
+HTTP_ADDITION_FILTER_MODULE=ngx_http_addition_filter_module
+HTTP_ADDITION_SRCS=src/http/modules/ngx_http_addition_filter_module.c
+
+
HTTP_ACCESS_MODULE=ngx_http_access_module
HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_module.c
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index a110b37f5..f4c85e45a 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -9,6 +9,102 @@
<title lang="en">nginx changelog</title>
+<changes ver="0.3.36" date="05.04.2006">
+
+<change type="feature">
+<para lang="ru">
+модуль ngx_http_addition_filter_module.
+</para>
+<para lang="en">
+the ngx_http_addition_filter_module.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+директивы proxy_pass и fastcgi_pass можно использовать внутри блока if.
+</para>
+<para lang="en">
+the "proxy_pass" and "fastcgi_pass" directives may be used inside
+the "if" block.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+директивы proxy_ignore_client_abort и fastcgi_ignore_client_abort.
+</para>
+<para lang="en">
+the "proxy_ignore_client_abort" and "fastcgi_ignore_client_abort" directives.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+переменная $request_completion.
+</para>
+<para lang="en">
+the "$request_completion" variable.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+модуль ngx_http_perl_module поддерживает методы $r->request_method и
+$r->remote_addr.
+</para>
+<para lang="en">
+the ngx_http_perl_module supports the $r->request_method and $r->remote_addr.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+модуль ngx_http_ssi_module поддерживает команду elif.
+</para>
+<para lang="en">
+the ngx_http_ssi_module supports the "elif" command.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+строка "\/" в начале выражения команды if модуля ngx_http_ssi_module
+воспринималась неверно.
+</para>
+<para lang="en">
+the "\/" string in the expression of the "if" command of the
+ngx_http_ssi_module was treated incorrectly.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+в использовании регулярных выражениях в команде if модуля ngx_http_ssi_module.
+</para>
+<para lang="en">
+in the regular expressions in the "if" command of the ngx_http_ssi_module.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+при задании относительного пути в директивах
+client_body_temp_path, proxy_temp_path, fastcgi_temp_path и perl_modules
+использовался каталог относительно текущего каталога, а не относительно
+префикса сервера.
+</para>
+<para lang="en">
+if the relative path was specified in the "client_body_temp_path",
+"proxy_temp_path", "fastcgi_temp_path", and "perl_modules" directives,
+then the directory was used relatively to a current path but not
+to a server prefix.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="0.3.35" date="22.03.2006">
<change type="bugfix">
@@ -64,7 +160,7 @@ the "http_503" parameter of the "proxy_next_upstream" or
<change type="bugfix">
<para lang="ru">
-ngx_http_perl_module не работал со встроенным в конфигурацинный файл кодом,
+ngx_http_perl_module не работал со встроенным в конфигурационный файл кодом,
если он не начинался сразу же с "sub".
</para>
<para lang="en">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 46d0a3dd4..3f910cb26 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.35"
+#define NGINX_VER "nginx/0.3.36"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index ab097c049..7c22948a3 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -63,6 +63,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
char *rv;
ngx_fd_t fd;
ngx_int_t rc;
+ ngx_buf_t *b;
ngx_uint_t block;
ngx_conf_file_t *prev;
@@ -95,11 +96,23 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
ngx_fd_info_n " \"%s\" failed", filename->data);
}
- cf->conf_file->buffer = ngx_create_temp_buf(cf->pool, ngx_pagesize);
- if (cf->conf_file->buffer == NULL) {
+ b = ngx_calloc_buf(cf->pool);
+ if (b == NULL) {
return NGX_CONF_ERROR;
}
+ cf->conf_file->buffer = b;
+
+ b->start = ngx_alloc(ngx_pagesize, cf->log);
+ if (b->start == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ b->pos = b->start;
+ b->last = b->start;
+ b->end = b->last + ngx_pagesize;
+ b->temporary = 1;
+
cf->conf_file->file.fd = fd;
cf->conf_file->file.name.len = filename->len;
cf->conf_file->file.name.data = filename->data;
@@ -183,7 +196,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
if (filename) {
- ngx_pfree(cf->pool, cf->conf_file->buffer->start);
+ ngx_free(cf->conf_file->buffer->start);
cf->conf_file = prev;
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 0c6576087..e3e719022 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -211,8 +211,8 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
char *p = conf;
ssize_t level;
- ngx_uint_t i, n;
ngx_str_t *value;
+ ngx_uint_t i, n;
ngx_path_t *path, **slot;
slot = (ngx_path_t **) (p + cmd->offset);
@@ -229,6 +229,11 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
path->name = value[1];
+
+ if (ngx_conf_full_name(cf->cycle, &path->name) == NGX_ERROR) {
+ return NULL;
+ }
+
path->len = 0;
path->cleaner = (ngx_gc_handler_pt) cmd->post;
path->conf_file = cf->conf_file->file.name.data;
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index eb0e86d0a..1797e96d0 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -86,7 +86,7 @@ ngx_palloc(ngx_pool_t *pool, size_t size)
{
u_char *m;
ngx_pool_t *p, *n;
- ngx_pool_large_t *large, *last;
+ ngx_pool_large_t *large;
if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL
&& size <= (size_t) (pool->end - (u_char *) pool)
@@ -134,34 +134,6 @@ ngx_palloc(ngx_pool_t *pool, size_t size)
return m;
}
- /* allocate a large block */
-
- large = NULL;
- last = NULL;
-
- if (pool->large) {
- for (last = pool->large; /* void */ ; last = last->next) {
- if (last->alloc == NULL) {
- large = last;
- last = NULL;
- break;
- }
-
- if (last->next == NULL) {
- break;
- }
- }
- }
-
- if (large == NULL) {
- large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
- if (large == NULL) {
- return NULL;
- }
-
- large->next = NULL;
- }
-
#if 0
p = ngx_memalign(ngx_pagesize, size, pool->log);
if (p == NULL) {
@@ -174,14 +146,14 @@ ngx_palloc(ngx_pool_t *pool, size_t size)
}
#endif
- if (pool->large == NULL) {
- pool->large = large;
-
- } else if (last) {
- last->next = large;
+ large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
+ if (large == NULL) {
+ return NULL;
}
large->alloc = p;
+ large->next = pool->large;
+ pool->large = large;
return p;
}
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
new file mode 100644
index 000000000..efd622e5a
--- /dev/null
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -0,0 +1,228 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+ ngx_str_t before_body;
+ ngx_str_t after_body;
+} ngx_http_addition_conf_t;
+
+
+typedef struct {
+ unsigned before_body_sent:1;
+ unsigned after_body_sent:1;
+} ngx_http_addition_ctx_t;
+
+
+static ngx_int_t ngx_http_addition_filter_init(ngx_cycle_t *cycle);
+static void *ngx_http_addition_create_conf(ngx_conf_t *cf);
+static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent,
+ void *child);
+
+
+static ngx_command_t ngx_http_addition_commands[] = {
+
+ { ngx_string("add_before_body"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_addition_conf_t, before_body),
+ NULL },
+
+ { ngx_string("add_after_body"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_addition_conf_t, after_body),
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_http_module_t ngx_http_addition_filter_module_ctx = {
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_http_addition_create_conf, /* create location configuration */
+ ngx_http_addition_merge_conf /* merge location configuration */
+};
+
+
+ngx_module_t ngx_http_addition_filter_module = {
+ NGX_MODULE_V1,
+ &ngx_http_addition_filter_module_ctx, /* module context */
+ ngx_http_addition_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init master */
+ ngx_http_addition_filter_init, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
+
+
+static ngx_int_t
+ngx_http_addition_header_filter(ngx_http_request_t *r)
+{
+ ngx_http_addition_ctx_t *ctx;
+ ngx_http_addition_conf_t *conf;
+
+ if (r->headers_out.status != NGX_HTTP_OK || r != r->main) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ if (ngx_strncasecmp(r->headers_out.content_type.data, "text/html",
+ sizeof("text/html") - 1)
+ != 0)
+ {
+ return ngx_http_next_header_filter(r);
+ }
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
+
+ if (conf->before_body.len == 0 && conf->after_body.len == 0) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module);
+
+ ngx_http_clear_content_length(r);
+ ngx_http_clear_accept_ranges(r);
+
+ return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ ngx_int_t rc;
+ ngx_uint_t last;
+ ngx_chain_t *cl;
+ ngx_http_addition_ctx_t *ctx;
+ ngx_http_addition_conf_t *conf;
+
+ if (in == NULL || r->header_only) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module);
+
+ if (ctx == NULL) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
+
+ if (!ctx->before_body_sent) {
+ ctx->before_body_sent = 1;
+
+ if (conf->before_body.len) {
+ if (ngx_http_subrequest(r, &conf->before_body, NULL, 0) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+ }
+
+ last = 0;
+
+ for (cl = in; cl; cl = cl->next) {
+ if (cl->buf->last_buf) {
+ cl->buf->last_buf = 0;
+ last = 1;
+ }
+ }
+
+ rc = ngx_http_next_body_filter(r, in);
+
+ if (rc == NGX_ERROR
+ || !last
+ || ctx->after_body_sent
+ || conf->after_body.len == 0)
+ {
+ return rc;
+ }
+
+ if (ngx_http_subrequest(r, &conf->after_body, NULL, 0) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ ctx->after_body_sent = 1;
+
+ return ngx_http_send_special(r, NGX_HTTP_LAST);
+}
+
+
+static ngx_int_t
+ngx_http_addition_filter_init(ngx_cycle_t *cycle)
+{
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
+ ngx_http_top_header_filter = ngx_http_addition_header_filter;
+
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_addition_body_filter;
+
+ return NGX_OK;
+}
+
+
+static void *
+ngx_http_addition_create_conf(ngx_conf_t *cf)
+{
+ ngx_http_addition_conf_t *conf;
+
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t));
+ if (conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ /*
+ * set by ngx_pcalloc():
+ *
+ * conf->before_body.len = 0;
+ * conf->before_body.date = NULL;
+ * conf->after_body.len = 0;
+ * conf->after_body.date = NULL;
+ */
+
+ return conf;
+}
+
+
+static char *
+ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_http_addition_conf_t *prev = parent;
+ ngx_http_addition_conf_t *conf = child;
+
+ ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
+ ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
+
+ return NGX_CONF_OK;
+}
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index d8d12088c..45110c59e 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -23,7 +23,7 @@ static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
NULL, /* merge server configuration */
NULL, /* create location configuration */
- NULL, /* merge location configuration */
+ NULL /* merge location configuration */
};
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 66e221f2b..ee603d17d 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -170,7 +170,7 @@ static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = {
static ngx_command_t ngx_http_fastcgi_commands[] = {
{ ngx_string("fastcgi_pass"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
ngx_http_fastcgi_pass,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -183,6 +183,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, index),
NULL },
+ { ngx_string("fastcgi_ignore_client_abort"),
+ 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_fastcgi_loc_conf_t, upstream.ignore_client_abort),
+ NULL },
+
{ ngx_string("fastcgi_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -1470,6 +1477,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
*/
conf->upstream.buffering = NGX_CONF_UNSET;
+ conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
@@ -1520,6 +1528,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->upstream.buffering,
prev->upstream.buffering, 1);
+ ngx_conf_merge_value(conf->upstream.ignore_client_abort,
+ prev->upstream.ignore_client_abort, 0);
+
ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
prev->upstream.connect_timeout, 60000);
@@ -1670,6 +1681,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->peers == NULL) {
conf->peers = prev->peers;
+ conf->upstream.schema = prev->upstream.schema;
}
if (conf->params_source == NULL) {
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index 89a568d2e..73c018ed9 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -517,6 +517,8 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cyclic_temp_file = 0;
/* the hardcoded values */
+ conf->upstream.buffering = 0;
+ conf->upstream.ignore_client_abort = 0;
conf->upstream.send_lowat = 0;
conf->upstream.bufs.num = 0;
conf->upstream.busy_buffers_size = 0;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index f8dfdc4e1..e96ba042e 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -130,7 +130,7 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
static ngx_command_t ngx_http_proxy_commands[] = {
{ ngx_string("proxy_pass"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
ngx_http_proxy_pass,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -150,6 +150,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
NULL },
+ { ngx_string("proxy_ignore_client_abort"),
+ 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.ignore_client_abort),
+ 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,
@@ -1415,6 +1422,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
*/
conf->upstream.buffering = NGX_CONF_UNSET;
+ conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
@@ -1468,6 +1476,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->upstream.buffering,
prev->upstream.buffering, 1);
+ ngx_conf_merge_value(conf->upstream.ignore_client_abort,
+ prev->upstream.ignore_client_abort, 0);
+
ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
prev->upstream.connect_timeout, 60000);
@@ -1654,6 +1665,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->peers == NULL) {
conf->peers = prev->peers;
+
+ conf->host_header = prev->host_header;
+ conf->port_text = prev->port_text;
+ conf->upstream.schema = prev->upstream.schema;
}
@@ -2057,11 +2072,12 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_PCRE)
- if (clcf->regex) {
+ if (clcf->regex || clcf->noname) {
if (plcf->upstream.uri.len) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"proxy_pass\" may not have URI part in "
- "location given by regular expression");
+ "location given by regular expression or "
+ "inside the \"if\" statement");
return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 1b528f7fb..f116634e8 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -13,6 +13,7 @@
#define NGX_HTTP_SSI_DATE_LEN 2048
#define NGX_HTTP_SSI_ADD_PREFIX 1
+#define NGX_HTTP_SSI_ADD_ZERO 2
typedef struct {
@@ -247,8 +248,12 @@ static ngx_http_ssi_command_t ngx_http_ssi_commands[] = {
{ ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 },
{ ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
- { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, 1, 0 },
- { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params, 1, 0 },
+ { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
+ NGX_HTTP_SSI_COND_IF, 0 },
+ { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
+ NGX_HTTP_SSI_COND_IF, 0 },
+ { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
+ NGX_HTTP_SSI_COND_ELSE, 0 },
{ ngx_null_string, NULL, NULL, 0, 0 }
};
@@ -523,7 +528,17 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
continue;
}
- if (!ctx->output && !cmd->conditional) {
+ if (cmd->conditional
+ && (ctx->conditional == 0
+ || ctx->conditional > cmd->conditional))
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid context of SSI command: \"%V\"",
+ &ctx->command);
+ goto ssi_error;
+ }
+
+ if (!ctx->output && cmd->conditional == 0) {
continue;
}
@@ -926,6 +941,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
ctx->key = ngx_hash(ctx->key, ch);
ctx->params.nelts = 0;
+
state = ssi_command_state;
break;
}
@@ -1565,7 +1581,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
}
- p = ngx_palloc(r->pool, len);
+ p = ngx_palloc(r->pool, len + ((flags & NGX_HTTP_SSI_ADD_ZERO) ? 1 : 0));
if (p == NULL) {
return NGX_ERROR;
}
@@ -1809,13 +1825,26 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
u_char *p, *last;
ngx_str_t *expr, left, right;
ngx_int_t rc;
- ngx_uint_t negative, noregex;
+ ngx_uint_t negative, noregex, flags;
#if (NGX_PCRE)
ngx_str_t err;
ngx_regex_t *regex;
u_char errstr[NGX_MAX_CONF_ERRSTR];
#endif
+ if (ctx->command.len == 2) {
+ if (ctx->conditional) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "the \"if\" command inside the \"if\" command");
+ return NGX_HTTP_SSI_ERROR;
+ }
+ }
+
+ if (ctx->output_chosen) {
+ ctx->output = 0;
+ return NGX_OK;
+ }
+
expr = params[NGX_HTTP_SSI_IF_EXPR];
left.data = expr->data;
@@ -1857,11 +1886,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
if (p == last) {
if (left.len) {
ctx->output = 1;
+ ctx->output_chosen = 1;
} else {
ctx->output = 0;
}
+ ctx->conditional = NGX_HTTP_SSI_COND_IF;
+
return NGX_OK;
}
@@ -1887,11 +1919,17 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
noregex = 0;
+ flags = NGX_HTTP_SSI_ADD_ZERO;
last--;
p++;
} else {
noregex = 1;
+ flags = 0;
+
+ if (p < last - 1 && p[0] == '\\' && p[1] == '/') {
+ p++;
+ }
}
right.len = last - p;
@@ -1900,7 +1938,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"right: \"%V\"", &right);
- if (ngx_http_ssi_evaluate_string(r, ctx, &right, 0) != NGX_OK) {
+ if (ngx_http_ssi_evaluate_string(r, ctx, &right, flags) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
@@ -1948,11 +1986,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
if ((rc == 0 && !negative) || (rc != 0 && negative)) {
ctx->output = 1;
+ ctx->output_chosen = 1;
} else {
ctx->output = 0;
}
+ ctx->conditional = NGX_HTTP_SSI_COND_IF;
+
return NGX_OK;
invalid_expression:
@@ -1968,7 +2009,13 @@ static ngx_int_t
ngx_http_ssi_else(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
- ctx->output = !ctx->output;
+ if (ctx->output_chosen) {
+ ctx->output = 0;
+ } else {
+ ctx->output = 1;
+ }
+
+ ctx->conditional = NGX_HTTP_SSI_COND_ELSE;
return NGX_OK;
}
@@ -1979,6 +2026,8 @@ ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
ctx->output = 1;
+ ctx->output_chosen = 0;
+ ctx->conditional = 0;
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h
index 5337e942a..eff236050 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -20,6 +20,10 @@
#define NGX_HTTP_SSI_PARAMS_N 4
+#define NGX_HTTP_SSI_COND_IF 1
+#define NGX_HTTP_SSI_COND_ELSE 2
+
+
typedef struct {
ngx_hash_t hash;
ngx_hash_keys_arrays_t commands;
@@ -54,7 +58,9 @@ typedef struct {
ngx_array_t variables;
- ngx_uint_t output; /* unsigned output:1; */
+ unsigned conditional:2;
+ unsigned output:1;
+ unsigned output_chosen:1;
void *value_buf;
ngx_str_t timefmt;
@@ -80,7 +86,7 @@ typedef struct {
ngx_http_ssi_command_pt handler;
ngx_http_ssi_param_t *params;
- unsigned conditional:1;
+ unsigned conditional:2;
unsigned flush:1;
} ngx_http_ssi_command_t;
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index 4d57bb63e..d0453ea8d 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -178,6 +178,35 @@ args(r, ...)
char *
+request_method(r)
+ nginx r
+
+ CODE:
+
+ RETVAL = ngx_palloc(r->pool, r->method_name.len + 1);
+ if (RETVAL == NULL) {
+ XSRETURN_UNDEF;
+ }
+
+ ngx_cpystrn((u_char *) RETVAL, r->method_name.data, r->method_name.len + 1);
+
+ OUTPUT:
+ RETVAL
+
+
+char *
+remote_addr(r)
+ nginx r
+
+ CODE:
+
+ RETVAL = (char *) r->connection->addr_text.data;
+
+ OUTPUT:
+ RETVAL
+
+
+char *
header_in(r, key)
nginx r
SV *key
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 0bcad5ccb..e453dc38b 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -39,6 +39,7 @@ static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
#endif
+static void ngx_http_perl_handle_request(ngx_http_request_t *r);
static ngx_int_t
ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf,
PerlInterpreter **perl, ngx_log_t *log);
@@ -174,23 +175,39 @@ ngx_http_perl_xs_init(pTHX)
static ngx_int_t
ngx_http_perl_handler(ngx_http_request_t *r)
{
- ngx_int_t rc;
- ngx_str_t uri, args;
- ngx_http_perl_ctx_t *ctx;
- ngx_http_perl_loc_conf_t *plcf;
- ngx_http_perl_main_conf_t *pmcf;
+ ngx_int_t rc;
/* TODO: Win32 */
if (r->zero_in_uri) {
return NGX_HTTP_NOT_FOUND;
}
+ rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
+
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+ return rc;
+ }
+
+ return NGX_DONE;
+}
+
+
+static void
+ngx_http_perl_handle_request(ngx_http_request_t *r)
+{
+ ngx_int_t rc;
+ ngx_str_t uri, args;
+ ngx_http_perl_ctx_t *ctx;
+ ngx_http_perl_loc_conf_t *plcf;
+ ngx_http_perl_main_conf_t *pmcf;
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler");
/* mod_perl's content handler assumes that content type was already set */
if (ngx_http_set_content_type(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
}
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
@@ -198,7 +215,8 @@ ngx_http_perl_handler(ngx_http_request_t *r)
if (ctx == NULL) {
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
if (ctx == NULL) {
- return NGX_ERROR;
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
}
ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
@@ -209,7 +227,8 @@ ngx_http_perl_handler(ngx_http_request_t *r)
rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
if (rc != NGX_OK) {
- return rc;
+ ngx_http_finalize_request(r, rc);
+ return;
}
{
@@ -235,20 +254,24 @@ ngx_http_perl_handler(ngx_http_request_t *r)
if (ctx->redirect_uri.len) {
uri = ctx->redirect_uri;
args = ctx->redirect_args;
+
+ } else {
+ uri.len = 0;
}
ctx->filename = NULL;
ctx->redirect_uri.len = 0;
if (uri.len) {
- return ngx_http_internal_redirect(r, &uri, &args);
+ ngx_http_internal_redirect(r, &uri, &args);
+ return;
}
if (rc == NGX_OK || rc == NGX_HTTP_OK) {
- return ngx_http_send_special(r, NGX_HTTP_LAST);
+ ngx_http_send_special(r, NGX_HTTP_LAST);
}
- return rc;
+ ngx_http_finalize_request(r, rc);
}
@@ -448,6 +471,10 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
}
#endif
+ if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
PERL_SYS_INIT(&ngx_argc, &ngx_argv);
pmcf->perl = ngx_http_perl_create_interpreter(pmcf, cf->log);
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c
deleted file mode 100644
index 86b8424c6..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ /dev/null
@@ -1,628 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p,
- int rc);
-static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p);
-
-
-int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p)
-{
- char *last;
- ngx_http_request_t *r;
- ngx_http_proxy_cache_t *c;
- ngx_http_proxy_upstream_conf_t *u;
-
- r = p->request;
-
- if (!(c = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_cache_t)))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->cache = c;
-
- c->ctx.file.fd = NGX_INVALID_FILE;
- c->ctx.file.log = r->connection->log;
- c->ctx.path = p->lcf->cache_path;
-
- u = p->lcf->upstream;
-
- c->ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len;
- if (!(c->ctx.key.data = ngx_palloc(r->pool, c->ctx.key.len + 1))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- last = ngx_cpymem(c->ctx.key.data, u->url.data, u->url.len);
-
- last = ngx_cpymem(last, r->uri.data + u->location->len,
- r->uri.len - u->location->len);
-
- if (r->args.len > 0) {
- *(last++) = '?';
- last = ngx_cpymem(last, r->args.data, r->args.len);
- }
- *last = '\0';
-
- p->header_in = ngx_create_temp_hunk(r->pool, p->lcf->header_buffer_size);
- if (p->header_in == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module;
-
- c->ctx.buf = p->header_in;
- c->ctx.log = r->connection->log;
-
- return ngx_http_proxy_process_cached_response(p,
- ngx_http_cache_get_file(r, &c->ctx));
-}
-
-
-static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p,
- int rc)
-{
- if (rc == NGX_OK) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_HIT;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
-
- if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->valid_header_in = 1;
-
- return ngx_http_proxy_send_cached_response(p);
- }
-
- if (rc == NGX_HTTP_CACHE_STALE) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_EXPR;
-
- } else if (rc == NGX_HTTP_CACHE_AGED) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_AGED;
- }
-
- if (rc == NGX_HTTP_CACHE_STALE || rc == NGX_HTTP_CACHE_AGED) {
- p->state->expired = ngx_time() - p->cache->ctx.expires;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
-
- if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
-
- p->stale = 1;
- p->valid_header_in = 1;
-
- } else if (rc == NGX_DECLINED) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_MISS;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
- }
-
- if (p->lcf->busy_lock) {
- p->try_busy_lock = 1;
-
- p->header_in->pos = p->header_in->start;
- p->header_in->last = p->header_in->start;
-
- p->busy_lock.time = 0;
- p->busy_lock.event = p->request->connection->read;
- p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler;
- p->busy_lock.md5 = p->cache->ctx.md5;
-
- ngx_http_proxy_cache_busy_lock(p);
- return NGX_DONE;
- }
-
- return ngx_http_proxy_request_upstream(p);
-}
-
-
-static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p)
-{
- int rc, i;
- ngx_table_elt_t *h;
- ngx_http_request_t *r;
- ngx_http_proxy_cache_t *c;
-
- rc = ngx_http_proxy_parse_status_line(p);
-
- c = p->cache;
- r = p->request;
-
- if (rc == NGX_AGAIN) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"proxy_header_buffer_size\" "
- "is too small to read header from \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-
- if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no valid HTTP/1.0 header in \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-
- /* rc == NGX_OK */
-
- c->status = p->status;
- c->status_line.len = p->status_end - p->status_start;
- c->status_line.data = ngx_palloc(r->pool, c->status_line.len + 1);
- if (c->status_line.data == NULL) {
- return NGX_ERROR;
- }
-
- /* reset for the possible parsing the upstream header */
-
- p->status = 0;
- p->status_count = 0;
-
- ngx_cpystrn(c->status_line.data, p->status_start, c->status_line.len + 1);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http cache status %ui \"%V\"",
- c->status, &c->status_line);
-
- /* TODO: ngx_init_table */
- c->headers_in.headers = ngx_create_table(r->pool, 20);
-
- for ( ;; ) {
- rc = ngx_http_parse_header_line(r, p->header_in);
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_http_add_header(&c->headers_in, ngx_http_proxy_headers_in);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->key.len = r->header_name_end - r->header_name_start;
- h->value.len = r->header_end - r->header_start;
-
- h->key.data = ngx_palloc(r->pool,
- h->key.len + 1 + h->value.len + 1);
- if (h->key.data == NULL) {
- return NGX_ERROR;
- }
-
- h->value.data = h->key.data + h->key.len + 1;
- ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
- ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
-
- for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) {
- if (ngx_http_proxy_headers_in[i].name.len != h->key.len) {
- continue;
- }
-
- if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data,
- h->key.data) == 0)
- {
- *((ngx_table_elt_t **) ((char *) &c->headers_in
- + ngx_http_proxy_headers_in[i].offset)) = h;
- break;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http cache header: \"%V: %V\"", &h->key, &h->value);
-
- continue;
-
- } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http cache header done");
-
- c->ctx.file_start = p->header_in->pos - p->header_in->start;
-
- return NGX_OK;
-
- } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) {
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid header in \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-
- /* rc == NGX_AGAIN || rc == NGX_HTTP_PARSE_TOO_LONG_HEADER */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"proxy_header_buffer_size\" "
- "is too small to read header from \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-}
-
-
-void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p)
-{
- int rc, ft_type;
-
- rc = ngx_http_busy_lock_cachable(p->lcf->busy_lock, &p->busy_lock,
- p->try_busy_lock);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http cache busy lock cachable: %d", rc);
-
- if (rc == NGX_OK) {
- if (p->try_busy_lock) {
- p->busy_locked = 1;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
-
- ngx_http_proxy_request_upstream(p);
- return;
- }
-
- ngx_http_proxy_cache_look_complete_request(p);
- return;
- }
-
- p->try_busy_lock = 0;
-
- if (p->cache->ctx.file.fd != NGX_INVALID_FILE
- && !p->cache->ctx.file.info_valid)
- {
- if (ngx_fd_info(p->cache->ctx.file.fd, &p->cache->ctx.file.info)
- == NGX_FILE_ERROR)
- {
- ngx_log_error(NGX_LOG_CRIT, p->request->connection->log, ngx_errno,
- ngx_fd_info_n " \"%s\" failed",
- p->cache->ctx.file.name.data);
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- p->cache->ctx.file.info_valid = 1;
- }
-
- if (rc == NGX_AGAIN) {
-
- if ((ngx_event_flags & (NGX_USE_CLEAR_EVENT|NGX_USE_KQUEUE_EVENT))
- && !p->request->connection->write->active)
- {
- /*
- * kqueue allows to detect when client closes prematurely
- * connection
- */
-
- p->request->connection->write->event_handler =
- ngx_http_proxy_check_broken_connection;
-
- if (ngx_add_event(p->request->connection->write, NGX_WRITE_EVENT,
- NGX_CLEAR_EVENT) == NGX_ERROR)
- {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- }
-
- return;
- }
-
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
- if (rc == NGX_DONE) {
- ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
-
- } else {
- /* rc == NGX_ERROR */
- ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
- }
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
- p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
-}
-
-
-static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_http_cache_ctx_t *ctx;
-
- if (!(ctx = ngx_pcalloc(p->request->pool, sizeof(ngx_http_cache_ctx_t)))) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- *ctx = p->cache->ctx;
-
- rc = ngx_http_cache_open_file(ctx, ngx_file_uniq(&p->cache->ctx.file.info));
-
- if (rc == NGX_DECLINED || rc == NGX_HTTP_CACHE_THE_SAME) {
- p->try_busy_lock = 1;
- p->busy_lock.time = 0;
- ngx_http_proxy_cache_busy_lock(p);
- return;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http cache old fd:%d, new fd:%d",
- p->cache->ctx.file.fd, ctx->file.fd);
-
- if (p->cache->ctx.file.fd != NGX_INVALID_FILE) {
- if (ngx_close_file(p->cache->ctx.file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, p->request->connection->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- p->cache->ctx.file.name.data);
- }
- }
-
- p->cache->ctx = *ctx;
-
- p->status = 0;
- p->status_count = 0;
-
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_process_cached_response(p, rc));
-}
-
-
-int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p)
-{
- int rc, len, i;
- off_t rest;
- ngx_hunk_t *h0, *h1;
- ngx_chain_t out[2];
- ngx_http_request_t *r;
-
- r = p->request;
-
- r->headers_out.status = p->cache->status;
-
-#if 0
- r->headers_out.content_length_n = -1;
- r->headers_out.content_length = NULL;
-#endif
-
- /* copy an cached header to r->headers_out */
-
- if (ngx_http_proxy_copy_header(p, &p->cache->headers_in) == NGX_ERROR) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* we need to allocate all before the header would be sent */
-
- len = p->header_in->end - (p->header_in->start + p->cache->ctx.file_start);
-
- h0 = NULL;
- h1 = NULL;
-
- if (len) {
- if (!((h0 = ngx_calloc_hunk(r->pool)))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (!((h0->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- if (len < p->cache->ctx.length) {
- if (!((h1 = ngx_calloc_hunk(r->pool)))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (!((h1->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- rc = ngx_http_send_header(r);
-
- /* NEEDED ??? */ p->header_sent = 1;
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- rest = p->cache->ctx.length;
-
- if (len) {
- if (p->valid_header_in) {
- h0->pos = p->header_in->start + p->cache->ctx.file_start;
-
- if (len > p->cache->ctx.length) {
- h0->last = h0->pos + p->cache->ctx.length;
-
- } else {
- h0->last = p->header_in->end;
- }
-
- h0->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
- }
-
- h0->type |= NGX_HUNK_FILE;
- h0->file_pos = p->cache->ctx.file_start;
-
- h0->file->fd = p->cache->ctx.file.fd;
- h0->file->log = r->connection->log;
-
- if (len > p->cache->ctx.length) {
- h0->file_last = h0->file_pos + p->cache->ctx.length;
- rest = 0;
-
- } else {
- h0->file_last = h0->file_pos + len;
- rest -= len;
- }
-
- out[0].hunk = h0;
- out[0].next = &out[1];
- i = 0;
-
- } else {
- i = -1;
- }
-
- if (rest) {
- h1->file_pos = p->cache->ctx.file_start + len;
- h1->file_last = h1->file_pos + rest;
- h1->type = NGX_HUNK_FILE;
-
- h1->file->fd = p->cache->ctx.file.fd;
- h1->file->log = r->connection->log;
-
- out[++i].hunk = h1;
- }
-
- out[i].next = NULL;
- if (!r->main) {
- out[i].hunk->type |= NGX_HUNK_LAST;
- }
-
- r->file.fd = p->cache->ctx.file.fd;
-
- return ngx_http_output_filter(r, out);
-}
-
-
-int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p)
-{
- time_t date, last_modified, expires, t;
- ngx_http_proxy_headers_in_t *h;
-
- switch (p->upstream->status) {
- case NGX_HTTP_OK:
- case NGX_HTTP_MOVED_PERMANENTLY:
- case NGX_HTTP_MOVED_TEMPORARILY:
- break;
-
-#if 0
- case NGX_HTTP_NOT_MODIFIED:
- return 1;
-#endif
-
- default:
- return 0;
- }
-
- h = &p->upstream->headers_in;
-
- date = NGX_ERROR;
- if (h->date) {
- date = ngx_http_parse_time(h->date->value.data, h->date->value.len);
- }
- if (date == NGX_ERROR) {
- date = ngx_time();
- }
- p->cache->ctx.date = date;
-
- last_modified = NGX_ERROR;
- if (h->last_modified) {
- last_modified = ngx_http_parse_time(h->last_modified->value.data,
- h->last_modified->value.len);
- p->cache->ctx.last_modified = last_modified;
- }
-
- if (h->x_accel_expires) {
- expires = ngx_atoi(h->x_accel_expires->value.data,
- h->x_accel_expires->value.len);
- if (expires != NGX_ERROR) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_XAE;
- p->state->expires = expires;
- p->cache->ctx.expires = date + expires;
- return (expires > 0);
- }
- }
-
- if (!p->lcf->ignore_expires) {
-
- /* TODO: Cache-Control: no-cache, max-age= */
-
- if (h->expires) {
- expires = ngx_http_parse_time(h->expires->value.data,
- h->expires->value.len);
- if (expires != NGX_ERROR) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_EXP;
- p->state->expires = expires - date;
- p->cache->ctx.expires = expires;
- return (date < expires);
- }
- }
- }
-
- if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_MVD;
- p->state->expires = /* STUB: 1 hour */ 60 * 60;
- p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60;
- return 1;
- }
-
- if (p->upstream->status == NGX_HTTP_MOVED_TEMPORARILY) {
- return 1;
- }
-
- if (last_modified != NGX_ERROR && p->lcf->lm_factor > 0) {
-
- /* FIXME: time_t == int_64_t, we can use fpu */
-
- p->state->reason = NGX_HTTP_PROXY_CACHE_LMF;
- t = (time_t)
- ((((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100);
- p->state->expires = t;
- p->cache->ctx.expires = ngx_time() + t;
- return 1;
- }
-
- if (p->lcf->default_expires > 0) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_PDE;
- p->state->expires = p->lcf->default_expires;
- p->cache->ctx.expires = ngx_time() + p->lcf->default_expires;
- return 1;
- }
-
- return 0;
-}
-
-
-int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p)
-{
- ngx_event_pipe_t *ep;
-
- if (p->cache == NULL) {
- return NGX_OK;
- }
-
- ep = p->upstream->event_pipe;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http cache update len: %O:%O",
- p->cache->ctx.length, ep->read_length);
-
- if (p->cache->ctx.length == -1) {
- /* TODO: test rc */
- ngx_write_file(&ep->temp_file->file,
- (char *) &ep->read_length, sizeof(off_t),
- offsetof(ngx_http_cache_header_t, length));
- }
-
- return ngx_http_cache_update_file(p->request, &p->cache->ctx,
- &ep->temp_file->file.name);
-}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
deleted file mode 100644
index bc91df9a1..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ /dev/null
@@ -1,1512 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r);
-#if 0
-static ngx_int_t ngx_http_proxy_cache_get(ngx_http_proxy_ctx_t *p);
-#endif
-
-static size_t ngx_http_proxy_log_proxy_state_getlen(ngx_http_request_t *r,
- uintptr_t data);
-static u_char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r,
- u_char *buf,
- ngx_http_log_op_t *op);
-
-#if 0
-static u_char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r,
- u_char *buf, uintptr_t data);
-static u_char *ngx_http_proxy_log_reason(ngx_http_request_t *r, u_char *buf,
- uintptr_t data);
-#endif
-
-static ngx_int_t ngx_http_proxy_add_log_formats(ngx_conf_t *cf);
-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_set_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 next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER },
- { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 },
- { ngx_string("http_404"), NGX_HTTP_PROXY_FT_HTTP_404 },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_bitmask_t use_stale_masks[] = {
- { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER },
- { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 },
- { ngx_string("busy_lock"), NGX_HTTP_PROXY_FT_BUSY_LOCK },
- { ngx_string("max_waiting"), NGX_HTTP_PROXY_FT_MAX_WAITING },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_num_bounds_t ngx_http_proxy_lm_factor_bounds = {
- ngx_conf_check_num_bounds, 0, 100
-};
-
-
-static ngx_command_t ngx_http_proxy_commands[] = {
-
- { ngx_string("proxy_pass"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_set_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, 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, 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, send_lowat),
- &ngx_http_proxy_lowat_post },
-
- { 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_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, pass_unparsed_uri),
- 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, 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, 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, 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, busy_buffers_size),
- NULL },
-
-#if 0
-
- { ngx_string("proxy_cache_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, cache_path),
- (void *) ngx_http_cache_cleaner_handler },
-
-#endif
-
- { 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, 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, 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, temp_file_write_size),
- NULL },
-
- { ngx_string("proxy_cache"),
- 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, cache),
- NULL },
-
-
- { ngx_string("proxy_busy_lock"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13,
- ngx_http_set_busy_lock_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, busy_lock),
- NULL },
-
-
- { 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_string("proxy_ignore_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, ignore_expires),
- NULL },
-
- { ngx_string("proxy_lm_factor"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, lm_factor),
- &ngx_http_proxy_lm_factor_bounds },
-
- { ngx_string("proxy_default_expires"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_sec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, default_expires),
- 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, next_upstream),
- &next_upstream_masks },
-
- { ngx_string("proxy_use_stale"),
- 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, use_stale),
- &use_stale_masks },
-
- ngx_null_command
-};
-
-
-ngx_http_module_t ngx_http_proxy_module_ctx = {
- ngx_http_proxy_add_log_formats, /* 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 */
- NULL, /* init module */
- NULL /* init process */
-};
-
-
-
-static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = {
- { ngx_string("proxy"), 0, NULL,
- ngx_http_proxy_log_proxy_state_getlen,
- ngx_http_proxy_log_proxy_state },
-
-#if 0
- { ngx_string("proxy_cache_state"), 0, ngx_http_proxy_log_cache_state },
- { ngx_string("proxy_reason"), 0, ngx_http_proxy_log_reason },
-#endif
-
- { ngx_null_string, 0, NULL, NULL, NULL }
-};
-
-
-
-ngx_http_header0_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 }
-};
-
-
-static ngx_str_t cache_states[] = {
- ngx_string("PASS"),
- ngx_string("BYPASS"),
- ngx_string("AUTH"),
- ngx_string("PGNC"),
- ngx_string("MISS"),
- ngx_string("EXPR"),
- ngx_string("AGED"),
- ngx_string("HIT")
-};
-
-
-static ngx_str_t cache_reasons[] = {
- ngx_string("BPS"),
- ngx_string("XAE"),
- ngx_string("CTL"),
- ngx_string("EXP"),
- ngx_string("MVD"),
- ngx_string("LMF"),
- ngx_string("PDE")
-};
-
-
-#if (NGX_PCRE)
-static ngx_str_t ngx_http_proxy_uri = ngx_string("/");
-#endif
-
-
-static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r)
-{
- ngx_http_proxy_ctx_t *p;
-
- p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
- if (p == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_http_set_ctx(r, p, ngx_http_proxy_module);
-
-
- p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
- p->request = r;
-
- /* TODO: we currently support reverse proxy only */
- p->accel = 1;
-
- if (ngx_array_init(&p->states, r->pool, p->lcf->peers->number,
- sizeof(ngx_http_proxy_state_t)) == NGX_ERROR)
- {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->state = ngx_array_push(&p->states);
- if (p->state == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
-
-#if 0
-
- if (!p->lcf->cache
- || (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD))
- {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_PASS;
-
- } else if (r->bypass_cache) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_BYPASS;
-
- } else if (r->headers_in.authorization) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_AUTH;
-
- } else if (r->no_cache) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_PGNC;
- p->cachable = 1;
-
- } else {
- p->cachable = 1;
- }
-
-
- if (p->state->cache_state != 0) {
- return ngx_http_proxy_request_upstream(p);
- }
-
- return ngx_http_proxy_cache_get(p);
-
-#else
-
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_PASS;
-
- return ngx_http_proxy_request_upstream(p);
-
-#endif
-}
-
-
-#if 0
-
-static ngx_int_t ngx_http_proxy_cache_get(ngx_http_proxy_ctx_t *p)
-{
- u_char *last;
- ngx_http_request_t *r;
- ngx_http_cache_ctx_t ctx;
- ngx_http_proxy_upstream_conf_t *u;
-
- r = p->request;
- u = p->lcf->upstream;
-
- ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len;
- ctx.key.data = ngx_palloc(r->pool, ctx.key.len);
- if (ctx.key.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- last = ngx_cpymem(ctx.key.data, u->url.data, u->url.len);
-
- last = ngx_cpymem(last, r->uri.data + u->location->len,
- r->uri.len - u->location->len);
-
- if (r->args.len > 0) {
- *(last++) = '?';
- last = ngx_cpymem(last, r->args.data, r->args.len);
- }
-
- p->header_in = ngx_create_temp_buf(r->pool, p->lcf->header_buffer_size);
- if (p->header_in == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- p->header_in->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
-
- ctx.buf = p->header_in;
- ctx.path = p->lcf->cache_path;
- ctx.file = 1;
- ctx.primary = 1;
-
- ngx_http_cache_get(r, &ctx);
-
- return ngx_http_proxy_request_upstream(p);
-}
-
-#endif
-
-
-void ngx_http_proxy_rd_check_broken_connection(ngx_http_request_t *r)
-{
- ngx_http_proxy_check_broken_connection(r, r->connection->read);
-}
-
-
-void ngx_http_proxy_wr_check_broken_connection(ngx_http_request_t *r)
-{
- ngx_http_proxy_check_broken_connection(r, r->connection->read);
-}
-
-
-void ngx_http_proxy_check_broken_connection(ngx_http_request_t *r,
- ngx_event_t *ev)
-{
- int n;
- char buf[1];
- ngx_err_t err;
- ngx_connection_t *c;
- ngx_http_proxy_ctx_t *p;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy check client, write event:%d", ev->write);
-
-#if (NGX_HAVE_KQUEUE)
-
- if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
-
- if (!ev->pending_eof) {
- return;
- }
-
- c = r->connection;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- ev->eof = 1;
-
- if (ev->kq_errno) {
- ev->error = 1;
- }
-
- if (!p->cachable && p->upstream->peer.connection) {
- ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
- "kevent() reported that client closed "
- "prematurely connection, "
- "so upstream connection is closed too");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
- "kevent() reported that client closed "
- "prematurely connection");
-
- if (p->upstream == NULL || p->upstream->peer.connection == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- }
-
- return;
- }
-
-#endif
-
- c = r->connection;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- n = recv(c->fd, buf, 1, MSG_PEEK);
-
- err = ngx_socket_errno;
-
- /*
- * we do not need to disable the write event because
- * that event has NGX_USE_CLEAR_EVENT type
- */
-
- if (ev->write && (n >= 0 || err == NGX_EAGAIN)) {
- return;
- }
-
- if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
- if (ngx_del_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- }
- }
-
- if (n > 0) {
- return;
- }
-
- ev->eof = 1;
-
- if (n == -1) {
- if (err == NGX_EAGAIN) {
- return;
- }
-
- ev->error = 1;
-
- } else {
- /* n == 0 */
- err = 0;
- }
-
- if (!p->cachable && p->upstream->peer.connection) {
- ngx_log_error(NGX_LOG_INFO, ev->log, err,
- "client closed prematurely connection, "
- "so upstream connection is closed too");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- ngx_log_error(NGX_LOG_INFO, ev->log, err,
- "client closed prematurely connection");
-
- if (p->upstream == NULL || p->upstream->peer.connection == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- }
-}
-
-
-void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev)
-{
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_proxy_ctx_t *p;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http proxy busy lock");
-
- c = rev->data;
- r = c->data;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
- p->action = "waiting upstream in busy lock";
-
- if (p->request->connection->write->eof) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- if (rev->timedout) {
- rev->timedout = 0;
- p->busy_lock.time++;
- p->state->bl_time = p->busy_lock.time;
-
-#if (NGX_HTTP_FILE_CACHE)
-
- if (p->state->cache_state < NGX_HTTP_PROXY_CACHE_MISS) {
- ngx_http_proxy_upstream_busy_lock(p);
-
- } else {
- ngx_http_proxy_cache_busy_lock(p);
- }
-#else
-
- ngx_http_proxy_upstream_busy_lock(p);
-
-#endif
-
- return;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy: client sent while busy lock");
-
- /*
- * TODO: kevent() notify about error, otherwise we need to
- * call ngx_peek(): recv(MSG_PEEK) to get errno. THINK about aio.
- * if there's no error we need to disable event.
- */
-
-#if 0
-#if (NGX_HAVE_KQUEUE)
-
- if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && rev->kq_eof) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
- ngx_del_timer(rev);
-
- ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno,
- "client() closed connection");
-
- if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
-#endif
-#endif
-
-}
-
-
-void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
-{
- ngx_http_request_t *r;
-
- r = p->request;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize http proxy request");
-
- if (p->upstream && p->upstream->peer.connection) {
- ngx_http_proxy_close_connection(p);
- }
-
- if (p->header_sent
- && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
- {
- rc = 0;
- }
-
- if (p->saved_ctx) {
- r->connection->log->data = p->saved_ctx;
- r->connection->log->handler = p->saved_handler;
- }
-
- if (p->upstream && p->upstream->event_pipe) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy temp fd: %d",
- p->upstream->event_pipe->temp_file->file.fd);
- }
-
- if (p->cache) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy cache fd: %d",
- p->cache->ctx.file.fd);
- }
-
- if (rc == 0 && r->main == NULL) {
- rc = ngx_http_send_last(r);
- }
-
- ngx_http_finalize_request(r, rc);
-}
-
-
-void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p)
-{
- ngx_socket_t fd;
- ngx_connection_t *c;
-
- c = p->upstream->peer.connection;
- p->upstream->peer.connection = NULL;
-
- if (p->lcf->busy_lock) {
- p->lcf->busy_lock->busy--;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy close connection: %d", c->fd);
-
- if (c->fd == -1) {
-#if 0
- ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
-#endif
- return;
- }
-
- if (c->read->timer_set) {
- ngx_del_timer(c->read);
- }
-
- if (c->write->timer_set) {
- ngx_del_timer(c->write);
- }
-
- /* TODO: move connection to the connection pool */
-
- if (ngx_del_conn) {
- ngx_del_conn(c, NGX_CLOSE_EVENT);
-
- } else {
- if (c->read->active || c->read->disabled) {
- ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
- }
-
- if (c->write->active || c->read->disabled) {
- ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
- }
- }
-
- /*
- * we have to clean the connection information before the closing
- * because another thread may reopen the same file descriptor
- * before we clean the connection
- */
-
- if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_OK) {
-
- if (c->read->prev) {
- ngx_delete_posted_event(c->read);
- }
-
- if (c->write->prev) {
- ngx_delete_posted_event(c->write);
- }
-
- c->read->closed = 1;
- c->write->closed = 1;
-
- ngx_mutex_unlock(ngx_posted_events_mutex);
- }
-
- fd = c->fd;
- c->fd = (ngx_socket_t) -1;
- c->data = NULL;
-
- if (ngx_close_socket(fd) == -1) {
- ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
- ngx_close_socket_n " failed");
- }
-}
-
-
-u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len)
-{
- u_char *p;
- ngx_int_t escape;
- ngx_http_request_t *r;
- ngx_peer_connection_t *peer;
- ngx_http_proxy_log_ctx_t *ctx;
- ngx_http_proxy_upstream_conf_t *uc;
-
- ctx = log->data;
- r = ctx->proxy->request;
- uc = ctx->proxy->lcf->upstream;
- peer = &ctx->proxy->upstream->peer;
-
- p = ngx_snprintf(buf, len,
- " while %s, client: %V, server: %V, URL: \"%V\","
- " upstream: http://%V%s%V",
- ctx->proxy->action,
- &r->connection->addr_text,
- &r->server_name,
- &r->unparsed_uri,
- &peer->peers->peer[peer->cur_peer].name,
- ctx->proxy->lcf->upstream->uri_separator,
- &ctx->proxy->lcf->upstream->uri);
- len -= p - buf;
- buf = p;
-
- if (ctx->proxy->lcf->pass_unparsed_uri && r->valid_unparsed_uri) {
- p = ngx_cpymem(buf, r->unparsed_uri.data + 1, r->unparsed_uri.len - 1);
- len -= p - buf;
-
- return ngx_http_log_error_info(r, p, len);
- }
-
- if (r->quoted_uri) {
- escape = 2 * ngx_escape_uri(NULL, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len,
- NGX_ESCAPE_URI);
- } else {
- escape = 0;
- }
-
- if (escape) {
- if (len >= r->uri.len - uc->location->len + escape) {
-
- ngx_escape_uri(buf, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len, NGX_ESCAPE_URI);
-
- buf += r->uri.len - uc->location->len + escape;
- len -= r->uri.len - uc->location->len + escape;
-
- if (r->args.len) {
- p = ngx_snprintf(buf, len, "?%V", &r->args);
- len -= p - buf;
- buf = p;
- }
-
- return ngx_http_log_error_info(r, buf, len);
- }
-
- p = ngx_palloc(r->pool, r->uri.len - uc->location->len + escape);
- if (p == NULL) {
- return buf;
- }
-
- ngx_escape_uri(p, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len, NGX_ESCAPE_URI);
-
- p = ngx_cpymem(buf, p, r->uri.len - uc->location->len + escape);
-
- } else {
- p = ngx_cpymem(buf, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len);
- }
-
- len -= p - buf;
- buf = p;
-
- if (r->args.len) {
- p = ngx_snprintf(buf, len, "?%V", &r->args);
- len -= p - buf;
- buf = p;
- }
-
- return ngx_http_log_error_info(r, buf, len);
-}
-
-
-static size_t ngx_http_proxy_log_proxy_state_getlen(ngx_http_request_t *r,
- uintptr_t data)
-{
- ngx_http_proxy_ctx_t *p;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL) {
- return 1;
- }
-
- return p->states.nelts * /* STUB */ 100;
-}
-
-
-static u_char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r,
- u_char *buf,
- ngx_http_log_op_t *op)
-{
- ngx_uint_t i;
- ngx_http_proxy_ctx_t *p;
- ngx_http_proxy_state_t *state;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL) {
- *buf = '-';
- return buf + 1;
- }
-
- i = 0;
- state = p->states.elts;
-
- for ( ;; ) {
- if (state[i].cache_state == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data,
- cache_states[state[i].cache_state - 1].len);
- }
-
- *buf++ = '/';
-
- if (state[i].expired == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%T", state[i].expired);
- }
-
- *buf++ = '/';
-
- if (state[i].bl_time == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%T", state[i].bl_time);
- }
-
- *buf++ = '/';
-
- *buf++ = '*';
-
- *buf++ = ' ';
-
- if (state[i].status == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%ui", state[i].status);
- }
-
- *buf++ = '/';
-
- if (state[i].reason == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data,
- cache_reasons[state[i].reason - 1].len);
- }
-
- *buf++ = '/';
-
- if (state[i].reason < NGX_HTTP_PROXY_CACHE_XAE) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%T", state[i].expires);
- }
-
- *buf++ = ' ';
- *buf++ = '*';
-
- if (++i == p->states.nelts) {
- return buf;
- }
-
- *buf++ = ',';
- *buf++ = ' ';
- }
-}
-
-
-#if 0
-
-static u_char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r,
- u_char *buf, uintptr_t data)
-{
- ngx_uint_t i;
- ngx_http_proxy_ctx_t *p;
- ngx_http_proxy_state_t *state;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL || p->state->cache_state == 0) {
- if (buf == NULL) {
- return (u_char *) 1;
- }
-
- *buf = '-';
- return buf + 1;
- }
-
- if (buf == NULL) {
- /* find the request line length */
- return (u_char *) (p->states.nelts * sizeof("BYPASS") - 1);
- }
-
- i = 0;
- state = p->states.elts;
-
- for ( ;; ) {
- buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data,
- cache_states[state[i].cache_state - 1].len);
-
- if (++i == p->states.nelts) {
- return buf;
- }
-
- *buf++ = ',';
- *buf++ = ' ';
- }
-}
-
-
-static u_char *ngx_http_proxy_log_reason(ngx_http_request_t *r, u_char *buf,
- uintptr_t data)
-{
- ngx_uint_t i;
- ngx_http_proxy_ctx_t *p;
- ngx_http_proxy_state_t *state;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL || p->state->reason == 0) {
- if (buf == NULL) {
- return (u_char *) 1;
- }
-
- *buf = '-';
- return buf + 1;
- }
-
- if (buf == NULL) {
- /* find the request line length */
- return (u_char *) (p->states.nelts * sizeof("BPS") - 1);
- }
-
- i = 0;
- state = p->states.elts;
-
- for ( ;; ) {
- buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data,
- cache_reasons[state[i].reason - 1].len);
-
- if (++i == p->states.nelts) {
- return buf;
- }
-
- *buf++ = ',';
- *buf++ = ' ';
- }
-}
-
-#endif
-
-
-static ngx_int_t ngx_http_proxy_add_log_formats(ngx_conf_t *cf)
-{
- 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;
-
- return NGX_OK;
-}
-
-
-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->bufs.num = 0;
- * conf->path = NULL;
- * conf->next_upstream = 0;
- * conf->use_stale = 0;
- * conf->upstreams = NULL;
- * conf->peers = NULL;
- * conf->cache_path = NULL;
- * conf->temp_path = NULL;
- * conf->x_vars;
- * conf->busy_lock = NULL;
- */
-
- conf->connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->send_timeout = NGX_CONF_UNSET_MSEC;
- conf->send_lowat = NGX_CONF_UNSET_SIZE;
-
- conf->pass_unparsed_uri = NGX_CONF_UNSET;
- 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->header_buffer_size = NGX_CONF_UNSET_SIZE;
- conf->read_timeout = NGX_CONF_UNSET_MSEC;
- conf->busy_buffers_size = NGX_CONF_UNSET_SIZE;
-
- conf->max_temp_file_size = NGX_CONF_UNSET_SIZE;
- conf->temp_file_write_size = NGX_CONF_UNSET_SIZE;
-
- /* "proxy_cyclic_temp_file" is disabled */
- conf->cyclic_temp_file = 0;
-
- conf->cache = NGX_CONF_UNSET;
-
- conf->pass_server = NGX_CONF_UNSET;
- conf->pass_x_accel_expires = NGX_CONF_UNSET;
- conf->ignore_expires = NGX_CONF_UNSET;
- conf->lm_factor = NGX_CONF_UNSET;
- conf->default_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_conf_merge_msec_value(conf->connect_timeout,
- prev->connect_timeout, 60000);
- ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
- ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
-
- ngx_conf_merge_value(conf->pass_unparsed_uri, prev->pass_unparsed_uri, 0);
-
- if (conf->pass_unparsed_uri && conf->upstream->location->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_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);
-
- ngx_conf_merge_msec_value(conf->read_timeout, prev->read_timeout, 60000);
-
- ngx_conf_merge_size_value(conf->header_buffer_size,
- prev->header_buffer_size, (size_t) ngx_pagesize);
-
- ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 8, ngx_pagesize);
-
- if (conf->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->header_buffer_size;
- if (size < conf->bufs.size) {
- size = conf->bufs.size;
- }
-
-
- ngx_conf_merge_size_value(conf->busy_buffers_size,
- prev->busy_buffers_size, NGX_CONF_UNSET_SIZE);
-
- if (conf->busy_buffers_size == NGX_CONF_UNSET_SIZE) {
- conf->busy_buffers_size = 2 * size;
-
- } else if (conf->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->busy_buffers_size > (conf->bufs.num - 1) * conf->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->temp_file_write_size,
- prev->temp_file_write_size, NGX_CONF_UNSET_SIZE);
-
- if (conf->temp_file_write_size == NGX_CONF_UNSET_SIZE) {
- conf->temp_file_write_size = 2 * size;
-
- } else if (conf->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->max_temp_file_size,
- prev->max_temp_file_size, NGX_CONF_UNSET_SIZE);
-
- if (conf->max_temp_file_size == NGX_CONF_UNSET_SIZE) {
-
- /*
- * "proxy_max_temp_file_size" is set to 1G for reverse proxy,
- * it should be much less in the generic proxy
- */
-
- conf->max_temp_file_size = 1024 * 1024 * 1024;
-
-#if 0
- conf->max_temp_file_size = 2 * size;
-#endif
-
-
- } else if (conf->max_temp_file_size != 0
- && conf->max_temp_file_size < size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_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 \"proxy_header_buffer_size\" and "
- "one of the \"proxy_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_bitmask_value(conf->next_upstream, prev->next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_PROXY_FT_ERROR
- |NGX_HTTP_PROXY_FT_TIMEOUT));
-
- ngx_conf_merge_bitmask_value(conf->use_stale, prev->use_stale,
- NGX_CONF_BITMASK_SET);
-
-#if 0
- ngx_conf_merge_path_value(conf->cache_path, prev->cache_path,
- NGX_HTTP_PROXY_CACHE_PATH, 1, 2, 0,
- ngx_garbage_collector_temp_handler, cf);
-#endif
-
- ngx_conf_merge_path_value(conf->temp_path, prev->temp_path,
- NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0,
- ngx_garbage_collector_temp_handler, cf);
-
- ngx_conf_merge_value(conf->cache, prev->cache, 0);
-
-
- /* conf->cache must be merged */
-
- if (conf->busy_lock == NULL) {
- conf->busy_lock = prev->busy_lock;
- }
-
- if (conf->busy_lock && conf->cache && conf->busy_lock->md5 == NULL) {
-
- /* ngx_calloc_shared() */
- conf->busy_lock->md5_mask =
- ngx_pcalloc(cf->pool, (conf->busy_lock->max_busy + 7) / 8);
- if (conf->busy_lock->md5_mask == NULL) {
- return NGX_CONF_ERROR;
- }
-
- /* 16 bytes are 128 bits of the md5 */
-
- /* ngx_alloc_shared() */
- conf->busy_lock->md5 = ngx_palloc(cf->pool,
- 16 * conf->busy_lock->max_busy);
- if (conf->busy_lock->md5 == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
-
- ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0);
- ngx_conf_merge_value(conf->pass_x_accel_expires,
- prev->pass_x_accel_expires, 0);
- ngx_conf_merge_value(conf->ignore_expires, prev->ignore_expires, 0);
- ngx_conf_merge_value(conf->lm_factor, prev->lm_factor, 0);
- ngx_conf_merge_sec_value(conf->default_expires, prev->default_expires, 0);
-
- if (conf->x_vars == NULL) {
- conf->x_vars = prev->x_vars;
- }
-
- if (conf->peers == NULL) {
- conf->peers = prev->peers;
- conf->upstream = prev->upstream;
- }
-
- return NULL;
-}
-
-
-static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf)
-{
- ngx_http_proxy_loc_conf_t *lcf = conf;
-
- 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;
- }
-
- lcf->upstream = ngx_pcalloc(cf->pool,
- sizeof(ngx_http_proxy_upstream_conf_t));
- if (lcf->upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- lcf->upstream->url = *url;
-
- 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->upstream->host_header.len = sizeof("localhost") - 1;
- lcf->upstream->host_header.data = (u_char *) "localhost";
- lcf->upstream->uri = unix_upstream.uri;
- lcf->upstream->uri_separator = ":";
- lcf->upstream->default_port = 1;
-
-#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;
- }
-
- lcf->upstream->host_header = inet_upstream.host_header;
- lcf->upstream->port_text = inet_upstream.port_text;
- lcf->upstream->uri = inet_upstream.uri;
- lcf->upstream->uri_separator = "";
- lcf->upstream->default_port = inet_upstream.default_port;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_proxy_handler;
-
-#if (NGX_PCRE)
- lcf->upstream->location = clcf->regex ? &ngx_http_proxy_uri : &clcf->name;
-#else
- lcf->upstream->location = &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)
-{
- ngx_http_proxy_loc_conf_t *lcf = conf;
-
- ngx_uint_t i, *index;
- ngx_str_t *value;
- ngx_http_variable_t *var;
- ngx_http_core_main_conf_t *cmcf;
-
- if (lcf->x_vars == NULL) {
- lcf->x_vars = ngx_array_create(cf->pool, 4,
- sizeof(ngx_http_variable_t *));
- if (lcf->x_vars == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- value = cf->args->elts;
-
- var = cmcf->variables.elts;
- for (i = 0; i < cmcf->variables.nelts; i++) {
- if (ngx_strcasecmp(var[i].name.data, value[1].data) == 0) {
-
- index = ngx_array_push(lcf->x_vars);
- if (index == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *index = var[i].index;
- return NGX_CONF_OK;
- }
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "unknown variable name \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
-}
-
-
-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/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
deleted file mode 100644
index 11c24b1ea..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ /dev/null
@@ -1,275 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_
-#define _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_event.h>
-#include <ngx_event_connect.h>
-#include <ngx_event_pipe.h>
-#include <ngx_http.h>
-
-
-typedef enum {
- NGX_HTTP_PROXY_CACHE_PASS = 1,
- NGX_HTTP_PROXY_CACHE_BYPASS,
- NGX_HTTP_PROXY_CACHE_AUTH,
- NGX_HTTP_PROXY_CACHE_PGNC,
- NGX_HTTP_PROXY_CACHE_MISS,
- NGX_HTTP_PROXY_CACHE_EXPR,
- NGX_HTTP_PROXY_CACHE_AGED,
- NGX_HTTP_PROXY_CACHE_HIT
-} ngx_http_proxy_state_e;
-
-
-typedef enum {
- NGX_HTTP_PROXY_CACHE_BPS = 1,
- NGX_HTTP_PROXY_CACHE_XAE,
- NGX_HTTP_PROXY_CACHE_CTL,
- NGX_HTTP_PROXY_CACHE_EXP,
- NGX_HTTP_PROXY_CACHE_MVD,
- NGX_HTTP_PROXY_CACHE_LMF,
- NGX_HTTP_PROXY_CACHE_PDE
-} ngx_http_proxy_reason_e;
-
-
-typedef struct {
- ngx_str_t url;
- ngx_str_t host;
- ngx_str_t uri;
- ngx_str_t host_header;
- ngx_str_t port_text;
- ngx_str_t *location;
-
- char *uri_separator;
-
- in_port_t port;
-
- unsigned default_port:1;
-} ngx_http_proxy_upstream_conf_t;
-
-
-typedef struct {
- size_t send_lowat;
- size_t header_buffer_size;
- size_t busy_buffers_size;
- size_t max_temp_file_size;
- size_t temp_file_write_size;
-
- ngx_msec_t connect_timeout;
- ngx_msec_t send_timeout;
- ngx_msec_t read_timeout;
- time_t default_expires;
-
- ngx_int_t lm_factor;
-
- ngx_uint_t next_upstream;
- ngx_uint_t use_stale;
-
- ngx_bufs_t bufs;
-
- ngx_flag_t cyclic_temp_file;
- ngx_flag_t cache;
- 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_unparsed_uri;
- ngx_flag_t pass_server;
- ngx_flag_t pass_x_accel_expires;
- ngx_flag_t ignore_expires;
-
- ngx_path_t *cache_path;
- ngx_path_t *temp_path;
-
- ngx_array_t *x_vars;
-
- ngx_http_busy_lock_t *busy_lock;
-
- ngx_http_proxy_upstream_conf_t *upstream;
- ngx_peers_t *peers;
-} ngx_http_proxy_loc_conf_t;
-
-
-/*
- * "EXPR/10/5/- 200/EXP/60 4"
- * "MISS/-/-/B 503/-/- -"
- * "EXPR/10/20/SB HIT/-/- -"
- * "EXPR/10/15/NB HIT/-/- -"
- */
-
-typedef struct {
- ngx_http_proxy_state_e cache_state;
- time_t expired;
- time_t bl_time;
- ngx_uint_t bl_state;
-
- ngx_uint_t status;
- ngx_http_proxy_reason_e reason;
- time_t time;
- time_t expires;
-
- ngx_str_t *peer;
-} ngx_http_proxy_state_t;
-
-
-typedef struct {
- ngx_list_t headers;
-#if 0
- ngx_table_t headers; /* it must be first field */
-#endif
-
- 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;
-
-
-typedef struct {
- ngx_http_cache_t ctx;
- ngx_uint_t status;
- ngx_str_t status_line;
-
- ngx_http_proxy_headers_in_t headers_in;
-} ngx_http_proxy_cache_t;
-
-
-typedef struct {
- ngx_peer_connection_t peer;
- ngx_uint_t status;
- ngx_str_t status_line;
- ngx_uint_t method;
-
- ngx_output_chain_ctx_t *output_chain_ctx;
- ngx_event_pipe_t *event_pipe;
-
- ngx_http_proxy_headers_in_t headers_in;
-} ngx_http_proxy_upstream_t;
-
-
-typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t;
-
-struct ngx_http_proxy_ctx_s {
- ngx_http_request_t *request;
- ngx_http_proxy_loc_conf_t *lcf;
- ngx_http_proxy_upstream_t *upstream;
- ngx_http_proxy_cache_t *cache;
-
- ngx_buf_t *header_in;
-
- ngx_http_busy_lock_ctx_t busy_lock;
-
- unsigned accel:1;
-
- unsigned cachable:1;
- unsigned stale:1;
- unsigned try_busy_lock:1;
- unsigned busy_locked:1;
- unsigned valid_header_in:1;
-
- unsigned request_sent:1;
- unsigned header_sent:1;
-
-
- /* used to parse an upstream HTTP header */
- ngx_uint_t status;
- u_char *status_start;
- u_char *status_end;
- ngx_uint_t status_count;
- ngx_uint_t parse_state;
-
- ngx_http_proxy_state_t *state;
- ngx_array_t states; /* of ngx_http_proxy_state_t */
-
- /*
- * we declare "action" as "char *" because the actions are usually
- * the static strings and in the "u_char *" case we have to override
- * all the time their types
- */
-
- char *action;
- ngx_http_log_ctx_t *saved_ctx;
- ngx_log_handler_pt saved_handler;
-};
-
-
-typedef struct {
- ngx_uint_t connection;
- ngx_http_proxy_ctx_t *proxy;
-} ngx_http_proxy_log_ctx_t;
-
-
-#define NGX_HTTP_PROXY_PARSE_NO_HEADER 30
-
-
-#define NGX_HTTP_PROXY_FT_ERROR 0x02
-#define NGX_HTTP_PROXY_FT_TIMEOUT 0x04
-#define NGX_HTTP_PROXY_FT_INVALID_HEADER 0x08
-#define NGX_HTTP_PROXY_FT_HTTP_500 0x10
-#define NGX_HTTP_PROXY_FT_HTTP_404 0x20
-#define NGX_HTTP_PROXY_FT_BUSY_LOCK 0x40
-#define NGX_HTTP_PROXY_FT_MAX_WAITING 0x80
-
-
-int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p);
-
-#if (NGX_HTTP_FILE_CACHE)
-
-int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p);
-
-void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p);
-
-#endif
-
-void ngx_http_proxy_rd_check_broken_connection(ngx_http_request_t *r);
-void ngx_http_proxy_wr_check_broken_connection(ngx_http_request_t *r);
-void ngx_http_proxy_check_broken_connection(ngx_http_request_t *r,
- ngx_event_t *ev);
-
-void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev);
-void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
-
-u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len);
-void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
-void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p);
-
-int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
- ngx_http_proxy_headers_in_t *headers_in);
-
-
-
-extern ngx_module_t ngx_http_proxy_module;
-extern ngx_http_header0_t ngx_http_proxy_headers_in[];
-
-
-
-#endif /* _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_ */
diff --git a/src/http/modules/proxy/ngx_http_proxy_header.c b/src/http/modules/proxy/ngx_http_proxy_header.c
deleted file mode 100644
index a46ff9e2a..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_header.c
+++ /dev/null
@@ -1,206 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static int ngx_http_proxy_rewrite_location_header(ngx_http_proxy_ctx_t *p,
- ngx_table_elt_t *loc);
-
-int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
- ngx_http_proxy_headers_in_t *headers_in)
-{
- ngx_uint_t i;
- ngx_list_part_t *part;
- ngx_table_elt_t *ho, *h;
- ngx_http_request_t *r;
-
- r = p->request;
-
- part = &headers_in->headers.part;
- h = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- h = part->elts;
- i = 0;
- }
-
- /* ignore some headers */
-
- if (&h[i] == headers_in->connection) {
- continue;
- }
-
- if (&h[i] == headers_in->x_pad) {
- continue;
- }
-
- if (p->accel) {
- if (&h[i] == headers_in->date
- || &h[i] == headers_in->accept_ranges) {
- continue;
- }
-
- if (&h[i] == headers_in->x_accel_expires
- && !p->lcf->pass_x_accel_expires)
- {
- continue;
- }
-
- if (&h[i] == headers_in->server && !p->lcf->pass_server) {
- continue;
- }
-
- if (&h[i] == headers_in->location) {
- if (ngx_http_proxy_rewrite_location_header(p, &h[i])
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
-
- continue;
- }
- }
-
-
- /* "Content-Type" is handled specially */
-
- if (&h[i] == headers_in->content_type) {
- r->headers_out.content_type = &h[i];
- r->headers_out.content_type->key.len = 0;
- continue;
- }
-
-
- /* copy some header pointers and set up r->headers_out */
-
- ho = ngx_list_push(&r->headers_out.headers);
- if (ho == NULL) {
- return NGX_ERROR;
- }
-
- *ho = h[i];
-
- if (&h[i] == headers_in->expires) {
- r->headers_out.expires = ho;
- continue;
- }
-
- if (&h[i] == headers_in->cache_control) {
- r->headers_out.cache_control = ho;
- continue;
- }
-
- if (&h[i] == headers_in->etag) {
- r->headers_out.etag = ho;
- continue;
- }
-
-#if (NGX_HTTP_GZIP)
- if (&h[i] == headers_in->content_encoding) {
- r->headers_out.content_encoding = ho;
- continue;
- }
-#endif
-
- if (&h[i] == headers_in->last_modified) {
- r->headers_out.last_modified = ho;
- /* TODO: update r->headers_out.last_modified_time */
- continue;
- }
-
- /*
- * ngx_http_header_filter() passes the following headers as is
- * and does not handle them specially if they are set:
- * r->headers_out.server,
- * r->headers_out.date,
- * r->headers_out.content_length
- */
-
- if (&h[i] == headers_in->server) {
- r->headers_out.server = ho;
- continue;
- }
-
- if (&h[i] == headers_in->date) {
- r->headers_out.date = ho;
- continue;
- }
-
- if (&h[i] == headers_in->content_length) {
- r->headers_out.content_length = ho;
- r->headers_out.content_length_n = ngx_atoi(ho->value.data,
- ho->value.len);
- continue;
- }
- }
-
- return NGX_OK;
-}
-
-
-static int ngx_http_proxy_rewrite_location_header(ngx_http_proxy_ctx_t *p,
- ngx_table_elt_t *loc)
-{
- u_char *last;
- ngx_table_elt_t *location;
- ngx_http_request_t *r;
- ngx_http_proxy_upstream_conf_t *uc;
-
- r = p->request;
- uc = p->lcf->upstream;
-
- location = ngx_list_push(&r->headers_out.headers);
- if (location == NULL) {
- return NGX_ERROR;
- }
-
- if (p->lcf->preserve_host
- || uc->url.len > loc->value.len
- || ngx_rstrncmp(loc->value.data, uc->url.data, uc->url.len) != 0)
- {
-
- /*
- * we do not set r->headers_out.location here to avoid the handling
- * the local redirects without a host name by ngx_http_header_filter()
- */
-
- *location = *loc;
- return NGX_OK;
- }
-
- /* TODO: proxy_reverse */
-
- r->headers_out.location = location;
-
- location->key.len = 0;
- location->key.data = NULL;
-
- location->value.len = uc->location->len
- + (loc->value.len - uc->url.len) + 1;
- location->value.data = ngx_palloc(r->pool, location->value.len);
- if (location->value.data == NULL) {
- return NGX_ERROR;
- }
-
- last = ngx_cpymem(location->value.data,
- uc->location->data, uc->location->len);
-
- ngx_cpystrn(last, loc->value.data + uc->url.len,
- loc->value.len - uc->url.len + 1);
-
- return NGX_OK;
-}
diff --git a/src/http/modules/proxy/ngx_http_proxy_parse.c b/src/http/modules/proxy/ngx_http_proxy_parse.c
deleted file mode 100644
index c10cf4924..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_parse.c
+++ /dev/null
@@ -1,216 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
-{
- u_char ch;
- u_char *pos;
- enum {
- sw_start = 0,
- sw_H,
- sw_HT,
- sw_HTT,
- sw_HTTP,
- sw_first_major_digit,
- sw_major_digit,
- sw_first_minor_digit,
- sw_minor_digit,
- sw_status,
- sw_space_after_status,
- sw_status_text,
- sw_almost_done,
- sw_done
- } state;
-
- state = p->parse_state;
- pos = p->header_in->pos;
-
- while (pos < p->header_in->last && state < sw_done) {
- ch = *pos++;
-
- switch (state) {
-
- /* "HTTP/" */
- case sw_start:
- switch (ch) {
- case 'H':
- state = sw_H;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- case sw_H:
- switch (ch) {
- case 'T':
- state = sw_HT;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- case sw_HT:
- switch (ch) {
- case 'T':
- state = sw_HTT;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- case sw_HTT:
- switch (ch) {
- case 'P':
- state = sw_HTTP;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- case sw_HTTP:
- switch (ch) {
- case '/':
- state = sw_first_major_digit;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- /* the first digit of major HTTP version */
- case sw_first_major_digit:
- if (ch < '1' || ch > '9') {
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
-
- state = sw_major_digit;
- break;
-
- /* the major HTTP version or dot */
- case sw_major_digit:
- if (ch == '.') {
- state = sw_first_minor_digit;
- break;
- }
-
- if (ch < '0' || ch > '9') {
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
-
- break;
-
- /* the first digit of minor HTTP version */
- case sw_first_minor_digit:
- if (ch < '0' || ch > '9') {
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
-
- state = sw_minor_digit;
- break;
-
- /* the minor HTTP version or the end of the request line */
- case sw_minor_digit:
- if (ch == ' ') {
- state = sw_status;
- break;
- }
-
- if (ch < '0' || ch > '9') {
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
-
- break;
-
- /* HTTP status code */
- case sw_status:
- if (ch < '0' || ch > '9') {
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
-
- p->status = p->status * 10 + ch - '0';
-
- if (++p->status_count == 3) {
- state = sw_space_after_status;
- p->status_start = pos - 3;
- }
-
- break;
-
- /* space or end of line */
- case sw_space_after_status:
- switch (ch) {
- case ' ':
- state = sw_status_text;
- break;
- case '.': /* IIS may send 403.1, 403.2, etc */
- state = sw_status_text;
- break;
- case CR:
- state = sw_almost_done;
- break;
- case LF:
- state = sw_done;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- /* any text until end of line */
- case sw_status_text:
- switch (ch) {
- case CR:
- state = sw_almost_done;
-
- break;
- case LF:
- state = sw_done;
- break;
- }
- break;
-
- /* end of request line */
- case sw_almost_done:
- p->status_end = pos - 2;
- switch (ch) {
- case LF:
- state = sw_done;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- /* suppress warning */
- case sw_done:
- break;
- }
- }
-
- p->header_in->pos = pos;
-
- if (state == sw_done) {
- if (p->status_end == NULL) {
- p->status_end = pos - 1;
- }
-
- p->parse_state = sw_start;
- return NGX_OK;
- }
-
- p->parse_state = state;
- return NGX_AGAIN;
-}
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
deleted file mode 100644
index 0f17b953f..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ /dev/null
@@ -1,1656 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_event.h>
-#include <ngx_event_connect.h>
-#include <ngx_event_pipe.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_init_upstream(ngx_http_request_t *r);
-static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_send_request_handler(ngx_event_t *wev);
-static void ngx_http_proxy_dummy_handler(ngx_event_t *wev);
-static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev);
-static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
-static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *);
-static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_process_downstream(ngx_http_request_t *r);
-static void ngx_http_proxy_process_body(ngx_event_t *ev);
-static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p,
- ngx_uint_t ft_type);
-
-
-static ngx_str_t http_methods[] = {
- ngx_string("GET "),
- ngx_string("HEAD "),
- ngx_string("POST ")
-};
-
-
-static char *upstream_header_errors[] = {
- "upstream sent invalid header",
- "upstream sent too long header line"
-};
-
-
-static char http_version[] = " HTTP/1.0" CRLF;
-static char host_header[] = "Host: ";
-static char x_url_header[] = "X-URL: http";
-static char x_real_ip_header[] = "X-Real-IP: ";
-static char x_forwarded_for_header[] = "X-Forwarded-For: ";
-static char connection_close_header[] = "Connection: close" CRLF;
-
-
-int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_http_request_t *r;
- ngx_http_proxy_upstream_t *u;
-
- r = p->request;
-
- u = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_upstream_t));
- if (u == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->upstream = u;
-
- u->peer.log_error = NGX_ERROR_ERR;
- u->peer.peers = p->lcf->peers;
- u->peer.tries = p->lcf->peers->number;
-#if (NGX_THREADS)
- u->peer.lock = &r->connection->lock;
-#endif
-
- u->method = r->method;
-
- rc = ngx_http_read_client_request_body(r, ngx_http_proxy_init_upstream);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p)
-{
- size_t len;
- ngx_uint_t i, escape, *index;
- ngx_buf_t *b;
- ngx_chain_t *chain;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_http_request_t *r;
- ngx_http_variable_t *var;
- ngx_http_variable_value_t *value;
- ngx_http_core_main_conf_t *cmcf;
- ngx_http_proxy_upstream_conf_t *uc;
-
- r = p->request;
- uc = p->lcf->upstream;
-
-#if (NGX_SUPPRESS_WARN)
- var = NULL;
- index = NULL;
-#endif
-
- escape = 0;
-
- if (p->upstream->method) {
- len = http_methods[p->upstream->method - 1].len + uc->uri.len;
-
- } else {
- len = r->method_name.len + 1 + uc->uri.len;
- }
-
- if (p->lcf->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 + uc->location->len,
- r->uri.len - uc->location->len,
- NGX_ESCAPE_URI);
- }
-
- len += r->uri.len - uc->location->len + escape
- + sizeof("?") - 1 + r->args.len;
- }
-
- len += sizeof(http_version) - 1
- + sizeof(connection_close_header) - 1
- + sizeof(CRLF) - 1;
-
-
- if (p->lcf->set_x_url) {
- len += sizeof(x_url_header) - 1
- + sizeof("s://") - 1
- + r->port_text->len
- + r->unparsed_uri.len
- + sizeof(CRLF) - 1;
-
- if (r->headers_in.host) {
- len += r->headers_in.host_name_len;
-
- } else {
- len += r->server_name.len;
- }
-
- }
-
-
- if (p->lcf->preserve_host) {
- if (r->headers_in.host) {
- len += sizeof(host_header) - 1
- + r->headers_in.host_name_len + sizeof(":") - 1
- + uc->port_text.len + sizeof(CRLF) - 1;
-
- } else {
- len += sizeof(host_header) - 1
- + r->server_name.len + sizeof(":") - 1
- + uc->port_text.len + sizeof(CRLF) - 1;
- }
-
- } else {
- len += sizeof(host_header) - 1 + uc->host_header.len
- + sizeof(CRLF) - 1;
- }
-
-
- if (p->lcf->set_x_real_ip) {
- len += sizeof(x_real_ip_header) - 1 + INET_ADDRSTRLEN - 1
- + sizeof(CRLF) - 1;
- }
-
-
- if (p->lcf->add_x_forwarded_for) {
- if (r->headers_in.x_forwarded_for) {
- len += sizeof(x_forwarded_for_header) - 1
- + r->headers_in.x_forwarded_for->value.len
- + sizeof(", ") - 1 + INET_ADDRSTRLEN - 1 + sizeof(CRLF) - 1;
-
- } else {
- len += sizeof(x_forwarded_for_header) - 1 + INET_ADDRSTRLEN - 1
- + sizeof(CRLF) - 1;
- }
- }
-
-
- if (p->lcf->x_vars) {
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- var = cmcf->variables.elts;
- index = p->lcf->x_vars->elts;
-
- for (i = 0; i < p->lcf->x_vars->nelts; i++) {
-
- value = ngx_http_get_indexed_variable(r, index[i]);
- if (value == NULL) {
- continue;
- }
-
- if (value->text.len) {
- len += sizeof("X-") - 1 + var[index[i]].name.len
- + sizeof(": ") - 1 + value->text.len + sizeof(CRLF) - 1;
- }
- }
- }
-
-
- 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;
- }
-
- if (&header[i] == r->headers_in.host) {
- continue;
- }
-
- if (&header[i] == r->headers_in.connection) {
- continue;
- }
-
- len += header[i].key.len + sizeof(": ") - 1
- + header[i].value.len + sizeof(CRLF) - 1;
- }
-
-#if (NGX_DEBUG)
- len++;
-#endif
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NULL;
- }
-
- chain = ngx_alloc_chain_link(r->pool);
- if (chain == NULL) {
- return NULL;
- }
-
- chain->buf = b;
- chain->next = NULL;
-
-
- /* the request line */
-
- if (p->upstream->method) {
- b->last = ngx_cpymem(b->last,
- http_methods[p->upstream->method - 1].data,
- http_methods[p->upstream->method - 1].len);
- } else {
- b->last = ngx_cpymem(b->last, r->method_name.data,
- r->method_name.len + 1);
- }
-
- b->last = ngx_cpymem(b->last, uc->uri.data, uc->uri.len);
-
- if (p->lcf->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 + uc->location->len,
- r->uri.len - uc->location->len, NGX_ESCAPE_URI);
- b->last += r->uri.len - uc->location->len + escape;
-
- } else {
- b->last = ngx_cpymem(b->last, r->uri.data + uc->location->len,
- r->uri.len - uc->location->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, http_version, sizeof(http_version) - 1);
-
-
- /* the "Connection: close" header */
-
- b->last = ngx_cpymem(b->last, connection_close_header,
- sizeof(connection_close_header) - 1);
-
-
- /* the "Host" header */
-
- b->last = ngx_cpymem(b->last, host_header, sizeof(host_header) - 1);
-
- if (p->lcf->preserve_host) {
- if (r->headers_in.host) {
- b->last = ngx_cpymem(b->last, r->headers_in.host->value.data,
- r->headers_in.host_name_len);
- } else {
- b->last = ngx_cpymem(b->last, r->server_name.data,
- r->server_name.len);
- }
-
- if (!uc->default_port) {
- *b->last++ = ':';
- b->last = ngx_cpymem(b->last, uc->port_text.data,
- uc->port_text.len);
- }
-
- } else {
- b->last = ngx_cpymem(b->last, uc->host_header.data,
- uc->host_header.len);
- }
- *b->last++ = CR; *b->last++ = LF;
-
-
- /* the "X-URL" header */
-
- if (p->lcf->set_x_url) {
-
- b->last = ngx_cpymem(b->last, x_url_header,
- sizeof(x_url_header) - 1);
-
-#if (NGX_OPENSSL)
-
- if (r->connection->ssl) {
- *b->last++ = 's';
- }
-
-#endif
-
- *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/';
-
- if (r->headers_in.host) {
- b->last = ngx_cpymem(b->last, r->headers_in.host->value.data,
- r->headers_in.host_name_len);
- } else {
- b->last = ngx_cpymem(b->last, r->server_name.data,
- r->server_name.len);
- }
-
- b->last = ngx_cpymem(b->last, r->port_text->data, r->port_text->len);
- b->last = ngx_cpymem(b->last, r->unparsed_uri.data,
- r->unparsed_uri.len);
-
- *b->last++ = CR; *b->last++ = LF;
- }
-
-
- /* the "X-Real-IP" header */
-
- if (p->lcf->set_x_real_ip) {
- b->last = ngx_cpymem(b->last, x_real_ip_header,
- sizeof(x_real_ip_header) - 1);
- b->last = ngx_cpymem(b->last, r->connection->addr_text.data,
- r->connection->addr_text.len);
- *b->last++ = CR; *b->last++ = LF;
- }
-
-
- /* the "X-Forwarded-For" header */
-
- if (p->lcf->add_x_forwarded_for) {
- if (r->headers_in.x_forwarded_for) {
- b->last = ngx_cpymem(b->last, x_forwarded_for_header,
- sizeof(x_forwarded_for_header) - 1);
-
- b->last = ngx_cpymem(b->last,
- r->headers_in.x_forwarded_for->value.data,
- r->headers_in.x_forwarded_for->value.len);
-
- *b->last++ = ','; *b->last++ = ' ';
-
- } else {
- b->last = ngx_cpymem(b->last, x_forwarded_for_header,
- sizeof(x_forwarded_for_header) - 1);
- }
-
- b->last = ngx_cpymem(b->last, r->connection->addr_text.data,
- r->connection->addr_text.len);
- *b->last++ = CR; *b->last++ = LF;
- }
-
-
- if (p->lcf->x_vars) {
- for (i = 0; i < p->lcf->x_vars->nelts; i++) {
-
- value = ngx_http_get_indexed_variable(r, index[i]);
- if (value == NULL) {
- continue;
- }
-
- if (value->text.len == 0) {
- continue;
- }
-
- *b->last++ = 'X'; *b->last++ = '-';
-
- b->last = ngx_cpymem(b->last, var[index[i]].name.data,
- var[index[i]].name.len);
-
- *b->last++ = ':'; *b->last++ = ' ';
-
- b->last = ngx_cpymem(b->last, value->text.data, value->text.len);
-
- *b->last++ = CR; *b->last++ = LF;
- }
- }
-
-
- 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;
- }
-
- if (&header[i] == r->headers_in.host) {
- continue;
- }
-
- if (&header[i] == r->headers_in.connection) {
- continue;
- }
-
- if (&header[i] == r->headers_in.keep_alive) {
- continue;
- }
-
- if (&header[i] == r->headers_in.x_forwarded_for
- && p->lcf->add_x_forwarded_for)
- {
- continue;
- }
-
- if (&header[i] == r->headers_in.x_real_ip && p->lcf->set_x_real_ip) {
- continue;
- }
-
- if (&header[i] == r->headers_in.x_url && p->lcf->set_x_url) {
- 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)
- *b->last = '\0';
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy header:\n\"%s\"", b->pos);
-#endif
-
- return chain;
-}
-
-
-static void ngx_http_proxy_init_upstream(ngx_http_request_t *r)
-{
-
- ngx_chain_t *cl;
- ngx_http_proxy_ctx_t *p;
- ngx_output_chain_ctx_t *output;
- ngx_chain_writer_ctx_t *writer;
- ngx_http_proxy_log_ctx_t *ctx;
-
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy init upstream, client timer: %d",
- r->connection->read->timer_set);
-
- if (r->connection->read->timer_set) {
- ngx_del_timer(r->connection->read);
- }
-
- r->read_event_handler = ngx_http_proxy_rd_check_broken_connection;
-
- if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
-
- r->write_event_handler = ngx_http_proxy_wr_check_broken_connection;
-
- if (!r->connection->write->active) {
- if (ngx_add_event(r->connection->write, NGX_WRITE_EVENT,
- NGX_CLEAR_EVENT) == NGX_ERROR)
- {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- }
- }
-
-
- cl = ngx_http_proxy_create_request(p);
- if (cl == NULL) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (r->request_body->bufs) {
- cl->next = r->request_body->bufs;
- }
-
- r->request_body->bufs = cl;
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_log_ctx_t));
- if (ctx == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- ctx->connection = r->connection->number;
- ctx->proxy = p;
-
- p->upstream->peer.log = r->connection->log;
- p->saved_ctx = r->connection->log->data;
- p->saved_handler = r->connection->log->handler;
- r->connection->log->data = ctx;
- r->connection->log->handler = ngx_http_proxy_log_error;
- p->action = "connecting to upstream";
-
- output = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
- if (output == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- p->upstream->output_chain_ctx = output;
-
- output->sendfile = r->connection->sendfile;
- output->pool = r->pool;
- output->bufs.num = 1;
- output->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
- output->output_filter = ngx_chain_writer;
-
- writer = ngx_palloc(r->pool, sizeof(ngx_chain_writer_ctx_t));
- if (writer == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- output->filter_ctx = writer;
- writer->pool = r->pool;
-
-#if 0
- if (p->lcf->busy_lock && p->busy_lock == NULL) {
-#else
- if (p->lcf->busy_lock && !p->busy_locked) {
-#endif
- ngx_http_proxy_upstream_busy_lock(p);
- } else {
- ngx_http_proxy_connect(p);
- }
-}
-
-
-static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p)
-{
- ngx_chain_t *cl;
- ngx_output_chain_ctx_t *output;
- ngx_http_proxy_state_e state;
-
- /* reinit the request chain */
-
- for (cl = p->request->request_body->bufs; cl; cl = cl->next) {
- cl->buf->pos = cl->buf->start;
- cl->buf->file_pos = 0;
- }
-
- /* reinit the ngx_output_chain() context */
-
- output = p->upstream->output_chain_ctx;
-
- output->buf = NULL;
- output->in = NULL;
- output->free = NULL;
- output->busy = NULL;
-
- /* reinit r->header_in buffer */
-
- if (p->header_in) {
- if (p->cache) {
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
-
- } else {
- p->header_in->pos = p->header_in->start;
- p->header_in->last = p->header_in->start;
- }
- }
-
- /* add one more state */
-
- state = p->state->cache_state;
-
- p->state = ngx_array_push(&p->states);
- if (p->state == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
-
- p->state->cache_state = state;
-
- p->status = 0;
- p->status_count = 0;
-}
-
-
-#if 0
-
-void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
-{
- ngx_int_t rc;
-
- rc = ngx_event_busy_lock(p->lcf->busy_lock, p->busy_lock);
-
- if (rc == NGX_AGAIN) {
- return;
- }
-
- if (rc == NGX_OK) {
- ngx_http_proxy_connect(p);
- return;
- }
-
- if (rc == NGX_ERROR) {
- p->state->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- /* rc == NGX_BUSY */
-
-#if (NGX_HTTP_CACHE)
-
- if (p->busy_lock->timer) {
- ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
- } else {
- ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
- }
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
-#endif
-
- p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
-}
-
-#endif
-
-
-#if 1
-
-void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
-{
- ngx_int_t rc;
-#if (NGX_HTTP_CACHE)
- ngx_int_t ft_type;
-#endif
-
- if (p->busy_lock.time == 0) {
- p->busy_lock.event = p->request->connection->read;
- p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler;
- }
-
- rc = ngx_http_busy_lock(p->lcf->busy_lock, &p->busy_lock);
-
- if (rc == NGX_AGAIN) {
- return;
- }
-
- if (rc == NGX_OK) {
- ngx_http_proxy_connect(p);
- return;
- }
-
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
-#if (NGX_HTTP_CACHE)
-
- if (rc == NGX_DONE) {
- ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
-
- } else {
- /* rc == NGX_ERROR */
- ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
- }
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
-#endif
-
- p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
-}
-
-#endif
-
-
-static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
-{
- ngx_int_t rc;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_output_chain_ctx_t *output;
- ngx_chain_writer_ctx_t *writer;
-
- p->action = "connecting to upstream";
-
- p->request->connection->single_connection = 0;
-
- rc = ngx_event_connect_peer(&p->upstream->peer);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http proxy connect: %i", rc);
-
- if (rc == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- p->state->peer =
- &p->upstream->peer.peers->peer[p->upstream->peer.cur_peer].name;
-
- if (rc == NGX_CONNECT_ERROR) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- r = p->request;
- c = p->upstream->peer.connection;
-
- c->data = p;
- c->write->handler = ngx_http_proxy_send_request_handler;
- c->read->handler = ngx_http_proxy_process_upstream_status_line;
-
- c->sendfile = r->connection->sendfile;
-
- c->pool = r->pool;
- c->read->log = c->write->log = c->log = r->connection->log;
-
- /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
-
- output = p->upstream->output_chain_ctx;
- writer = output->filter_ctx;
- writer->out = NULL;
- writer->last = &writer->out;
- writer->connection = c;
- writer->limit = 0;
-
- if (p->request_sent) {
- ngx_http_proxy_reinit_upstream(p);
- }
-
- if (r->request_body->buf) {
- if (r->request_body->temp_file) {
-
- output->free = ngx_alloc_chain_link(r->pool);
- if (output->free == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- output->free->buf = r->request_body->buf;
- output->free->next = NULL;
- output->allocated = 1;
-
- r->request_body->buf->pos = r->request_body->buf->start;
- r->request_body->buf->last = r->request_body->buf->start;
- r->request_body->buf->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
-
- } else {
- r->request_body->buf->pos = r->request_body->buf->start;
- }
- }
-
- p->request_sent = 0;
-
- if (rc == NGX_AGAIN) {
- ngx_add_timer(c->write, p->lcf->connect_timeout);
- return;
- }
-
- /* rc == NGX_OK */
-
-#if 0 /* test only, see below about "post aio operation" */
-
- if (c->read->ready) {
- /* post aio operation */
- ngx_http_proxy_process_upstream_status_line(c->read);
-#if 0
- return;
-#endif
- }
-
-#endif
-
- ngx_http_proxy_send_request(p);
-}
-
-
-static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_connection_t *c;
-
- c = p->upstream->peer.connection;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy send request");
-
-#if (NGX_HAVE_KQUEUE)
-
- if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT)
- && !p->request_sent
- && c->write->pending_eof)
- {
- ngx_log_error(NGX_LOG_ERR, c->log, c->write->kq_errno,
- "connect() failed");
-
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
-#endif
-
- p->action = "sending request to upstream";
-
- rc = ngx_output_chain(p->upstream->output_chain_ctx,
- p->request_sent ? NULL:
- p->request->request_body->bufs);
-
- p->request_sent = 1;
-
- if (rc == NGX_ERROR) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- if (c->write->timer_set) {
- ngx_del_timer(c->write);
- }
-
- if (rc == NGX_AGAIN) {
- ngx_add_timer(c->write, p->lcf->send_timeout);
-
- if (ngx_handle_write_event(c->write, p->lcf->send_lowat) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- return;
- }
-
- /* rc == NGX_OK */
-
- if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
- if (ngx_tcp_push(c->fd) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, c->log,
- ngx_socket_errno,
- ngx_tcp_push_n " failed");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
- return;
- }
-
- ngx_add_timer(c->read, p->lcf->read_timeout);
-
-#if 1
- if (c->read->ready) {
-
- /* post aio operation */
-
- /*
- * although we can post aio operation just in the end
- * of ngx_http_proxy_connect() CHECK IT !!!
- * it's better to do here because we postpone header buffer allocation
- */
-
- ngx_http_proxy_process_upstream_status_line(c->read);
- return;
- }
-#endif
-
- c->write->handler = ngx_http_proxy_dummy_handler;
-
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-}
-
-
-static void ngx_http_proxy_send_request_handler(ngx_event_t *wev)
-{
- ngx_connection_t *c;
- ngx_http_proxy_ctx_t *p;
-
- c = wev->data;
- p = c->data;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
- "http proxy send request handler");
-
- if (wev->timedout) {
- p->action = "sending request to upstream";
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
- return;
- }
-
- if (p->request->connection->write->eof
- && (!p->cachable || !p->request_sent))
- {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- ngx_http_proxy_send_request(p);
-}
-
-
-static void ngx_http_proxy_dummy_handler(ngx_event_t *wev)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http proxy dummy handler");
-}
-
-
-static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
-{
- int rc;
- ssize_t n;
- ngx_connection_t *c;
- ngx_http_proxy_ctx_t *p;
-
- c = rev->data;
- p = c->data;
- p->action = "reading upstream status line";
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy process status line");
-
- if (rev->timedout) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
- return;
- }
-
- if (p->header_in == NULL) {
- p->header_in = ngx_create_temp_buf(p->request->pool,
- p->lcf->header_buffer_size);
- if (p->header_in == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- p->header_in->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
-
- if (p->cache) {
- p->header_in->pos += p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
- }
- }
-
- n = ngx_http_proxy_read_upstream_header(p);
-
- if (n == NGX_AGAIN) {
- return;
- }
-
- if (n == 0) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream prematurely closed connection");
- }
-
- if (n == NGX_ERROR || n == 0) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- p->valid_header_in = 0;
-
- p->upstream->peer.cached = 0;
-
- rc = ngx_http_proxy_parse_status_line(p);
-
- if (rc == NGX_AGAIN) {
- if (p->header_in->pos == p->header_in->end) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream sent too long status line");
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
- }
- return;
- }
-
- if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream sent no valid HTTP/1.0 header");
-
- if (p->accel) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
-
- } else {
- p->request->http_version = NGX_HTTP_VERSION_9;
- p->upstream->status = NGX_HTTP_OK;
- ngx_http_proxy_send_response(p);
- }
-
- return;
- }
-
- /* rc == NGX_OK */
-
- p->upstream->status = p->status;
- p->state->status = p->status;
-
- if (p->status == NGX_HTTP_INTERNAL_SERVER_ERROR) {
-
- if (p->upstream->peer.tries > 1
- && (p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_500))
- {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_500);
- return;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (p->upstream->peer.tries == 0
- && p->stale
- && (p->lcf->use_stale & NGX_HTTP_PROXY_FT_HTTP_500))
- {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
-
- return;
- }
-
-#endif
- }
-
- if (p->status == NGX_HTTP_NOT_FOUND
- && p->upstream->peer.tries > 1
- && p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_404)
- {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_404);
- return;
- }
-
- /* TODO: "proxy_error_page" */
-
- p->upstream->status_line.len = p->status_end - p->status_start;
- p->upstream->status_line.data = ngx_palloc(p->request->pool,
- p->upstream->status_line.len + 1);
- if (p->upstream->status_line.data == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- ngx_cpystrn(p->upstream->status_line.data, p->status_start,
- p->upstream->status_line.len + 1);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy status %ui \"%V\"",
- p->upstream->status, &p->upstream->status_line);
-
-
- /* init or reinit the p->upstream->headers_in.headers table */
-
- if (p->upstream->headers_in.headers.part.elts) {
- p->upstream->headers_in.headers.part.nelts = 0;
- p->upstream->headers_in.headers.part.next = NULL;
- p->upstream->headers_in.headers.last =
- &p->upstream->headers_in.headers.part;
-
- ngx_memzero(&p->upstream->headers_in.date,
- sizeof(ngx_http_proxy_headers_in_t) - sizeof(ngx_list_t));
-
- } else {
- if (ngx_list_init(&p->upstream->headers_in.headers, p->request->pool,
- 20, sizeof(ngx_table_elt_t)) == NGX_ERROR)
- {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- }
-
-
- c->read->handler = ngx_http_proxy_process_upstream_headers;
- ngx_http_proxy_process_upstream_headers(rev);
-}
-
-
-static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
-{
- int i, rc;
- ssize_t n;
- ngx_table_elt_t *h;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_proxy_ctx_t *p;
-
- c = rev->data;
- p = c->data;
- r = p->request;
- p->action = "reading upstream headers";
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy process header line");
-
- if (rev->timedout) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
- return;
- }
-
- rc = NGX_AGAIN;
-
- for ( ;; ) {
- if (rc == NGX_AGAIN) {
- n = ngx_http_proxy_read_upstream_header(p);
-
- if (n == 0) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream prematurely closed connection");
- }
-
- if (n == NGX_ERROR || n == 0) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- if (n == NGX_AGAIN) {
- return;
- }
- }
-
- rc = ngx_http_parse_header_line(p->request, p->header_in);
-
- if (rc == NGX_OK && !r->invalid_header) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_list_push(&p->upstream->headers_in.headers);
- if (h == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- h->key.len = r->header_name_end - r->header_name_start;
- h->value.len = r->header_end - r->header_start;
-
- h->key.data = ngx_palloc(p->request->pool,
- h->key.len + 1 + h->value.len + 1);
- if (h->key.data == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- h->value.data = h->key.data + h->key.len + 1;
- ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
- ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
-
- for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) {
- if (ngx_http_proxy_headers_in[i].name.len != h->key.len) {
- continue;
- }
-
- if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data,
- h->key.data) == 0)
- {
- *((ngx_table_elt_t **) ((char *) &p->upstream->headers_in
- + ngx_http_proxy_headers_in[i].offset)) = h;
- break;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy header: \"%V: %V\"", &h->key, &h->value);
-
- continue;
-
- } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy header done");
-
- /* TODO: hook to process the upstream header */
-
-#if (NGX_HTTP_CACHE)
-
- if (p->cachable) {
- p->cachable = ngx_http_proxy_is_cachable(p);
- }
-
-#endif
-
- ngx_http_proxy_send_response(p);
- return;
-
- } else if (rc != NGX_AGAIN) {
-
- if (r->invalid_header) {
- rc = NGX_HTTP_PARSE_INVALID_HEADER;
- }
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- upstream_header_errors[rc - NGX_HTTP_PARSE_HEADER_ERROR]);
-
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
- return;
- }
-
- /* rc == NGX_AGAIN: a header line parsing is still not complete */
-
- if (p->header_in->last == p->header_in->end) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream sent too big header");
-
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
- return;
- }
- }
-}
-
-
-static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
-{
- ssize_t n;
- ngx_event_t *rev;
-
- rev = p->upstream->peer.connection->read;
-
- n = p->header_in->last - p->header_in->pos;
-
- if (n > 0) {
- return n;
- }
-
- n = ngx_recv(p->upstream->peer.connection, p->header_in->last,
- p->header_in->end - p->header_in->last);
-
- if (n == NGX_AGAIN) {
-#if 0
- ngx_add_timer(rev, p->lcf->read_timeout);
-#endif
-
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return NGX_ERROR;
- }
-
- return NGX_AGAIN;
- }
-
- if (n == 0) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream closed prematurely connection");
- }
-
- if (n == 0 || n == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- p->header_in->last += n;
-
- return n;
-}
-
-
-static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_event_pipe_t *ep;
- ngx_http_request_t *r;
- ngx_http_cache_header_t *header;
- ngx_http_core_loc_conf_t *clcf;
-
- r = p->request;
-
- r->headers_out.status = p->upstream->status;
- r->headers_out.status_line = p->upstream->status_line;
-
-#if 0
- r->headers_out.content_length_n = -1;
- r->headers_out.content_length = NULL;
-#endif
-
- /* copy an upstream header to r->headers_out */
-
- if (ngx_http_proxy_copy_header(p, &p->upstream->headers_in) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- /* TODO: preallocate event_pipe bufs, look "Content-Length" */
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK) {
- ngx_http_proxy_finalize_request(p, rc);
- return;
- }
-
- p->header_sent = 1;
-
- if (p->cache && p->cache->ctx.file.fd != NGX_INVALID_FILE) {
- if (ngx_close_file(p->cache->ctx.file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- p->cache->ctx.file.name.data);
- }
- }
-
- if (p->cachable) {
- header = (ngx_http_cache_header_t *) p->header_in->start;
-
- header->expires = p->cache->ctx.expires;
- header->last_modified = p->cache->ctx.last_modified;
- header->date = p->cache->ctx.date;
- header->length = r->headers_out.content_length_n;
- p->cache->ctx.length = r->headers_out.content_length_n;
-
- header->key_len = p->cache->ctx.key0.len;
- ngx_memcpy(&header->key, p->cache->ctx.key0.data, header->key_len);
- header->key[header->key_len] = LF;
- }
-
- ep = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
- if (ep == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
-
- p->upstream->event_pipe = ep;
-
- ep->input_filter = ngx_event_pipe_copy_input_filter;
- ep->output_filter = (ngx_event_pipe_output_filter_pt)
- ngx_http_output_filter;
- ep->output_ctx = r;
- ep->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
- ep->bufs = p->lcf->bufs;
- ep->busy_size = p->lcf->busy_buffers_size;
- ep->upstream = p->upstream->peer.connection;
- ep->downstream = r->connection;
- ep->pool = r->pool;
- ep->log = r->connection->log;
-
- ep->cachable = p->cachable;
-
- ep->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
- if (ep->temp_file == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
-
- ep->temp_file->file.fd = NGX_INVALID_FILE;
- ep->temp_file->file.log = r->connection->log;
- ep->temp_file->path = p->lcf->temp_path;
- ep->temp_file->pool = r->pool;
-
- if (p->cachable) {
- ep->temp_file->persistent = 1;
- } else {
- ep->temp_file->warn = "an upstream response is buffered "
- "to a temporary file";
- }
-
- ep->max_temp_file_size = p->lcf->max_temp_file_size;
- ep->temp_file_write_size = p->lcf->temp_file_write_size;
-
- ep->preread_bufs = ngx_alloc_chain_link(r->pool);
- if (ep->preread_bufs == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- ep->preread_bufs->buf = p->header_in;
- ep->preread_bufs->next = NULL;
- p->header_in->recycled = 1;
-
- ep->preread_size = p->header_in->last - p->header_in->pos;
-
- if (p->cachable) {
- ep->buf_to_file = ngx_calloc_buf(r->pool);
- if (ep->buf_to_file == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- ep->buf_to_file->pos = p->header_in->start;
- ep->buf_to_file->last = p->header_in->pos;
- ep->buf_to_file->temporary = 1;
- }
-
- if (ngx_event_flags & NGX_USE_AIO_EVENT) {
- /* the posted aio operation can currupt a shadow buffer */
- ep->single_buf = 1;
- }
-
- /* TODO: ep->free_bufs = 0 if use ngx_create_chain_of_bufs() */
- ep->free_bufs = 1;
-
- /*
- * event_pipe would do p->header_in->last += ep->preread_size
- * as though these bytes were read.
- */
- p->header_in->last = p->header_in->pos;
-
- if (p->lcf->cyclic_temp_file) {
-
- /*
- * we need to disable the use of sendfile() if we use cyclic temp file
- * because the writing a new data can interfere with sendfile()
- * that uses the same kernel file pages (at least on FreeBSD)
- */
-
- ep->cyclic_temp_file = 1;
- r->connection->sendfile = 0;
-
- } else {
- ep->cyclic_temp_file = 0;
- }
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- ep->read_timeout = p->lcf->read_timeout;
- ep->send_timeout = clcf->send_timeout;
- ep->send_lowat = clcf->send_lowat;
-
- p->upstream->peer.connection->read->handler = ngx_http_proxy_process_body;
- r->write_event_handler = ngx_http_proxy_process_downstream;
-
- ngx_http_proxy_process_body(p->upstream->peer.connection->read);
-
- return;
-}
-
-
-static void ngx_http_proxy_process_downstream(ngx_http_request_t *r)
-{
- ngx_http_proxy_process_body(r->connection->write);
-}
-
-
-static void ngx_http_proxy_process_body(ngx_event_t *ev)
-{
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_proxy_ctx_t *p;
- ngx_event_pipe_t *ep;
-
- c = ev->data;
-
- if (ev->write) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy process downstream");
- r = c->data;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
- p->action = "sending to client";
-
- } else {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy process upstream");
- p = c->data;
- p->action = "reading upstream body";
- }
-
- ep = p->upstream->event_pipe;
-
- if (ev->timedout) {
- if (ev->write) {
- ep->downstream_error = 1;
- ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
- "client timed out");
-
- } else {
- ep->upstream_error = 1;
- ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
- "upstream timed out");
- }
-
- } else {
- if (ngx_event_pipe(ep, ev->write) == NGX_ABORT) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- }
-
- if (p->upstream->peer.connection) {
-
-#if (NGX_HTTP_FILE_CACHE)
-
- if (ep->upstream_done && p->cachable) {
- if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
-
- } else if (ep->upstream_eof && p->cachable) {
-
- /* TODO: check length & update cache */
-
- if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- }
-
-#endif
-
- if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy upstream exit: %p", ep->out);
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- }
-
- if (ep->downstream_error) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy downstream error");
- if (!p->cachable && p->upstream->peer.connection) {
- ngx_http_proxy_finalize_request(p, 0);
- }
- }
-}
-
-
-static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p,
- ngx_uint_t ft_type)
-{
- ngx_uint_t status;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http proxy next upstream: %ui", ft_type);
-
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
- if (ft_type != NGX_HTTP_PROXY_FT_HTTP_404) {
- ngx_event_connect_peer_failed(&p->upstream->peer);
- }
-
- if (ft_type == NGX_HTTP_PROXY_FT_TIMEOUT) {
- ngx_log_error(NGX_LOG_ERR, p->request->connection->log, NGX_ETIMEDOUT,
- "upstream timed out");
- }
-
- if (p->upstream->peer.cached && ft_type == NGX_HTTP_PROXY_FT_ERROR) {
- status = 0;
-
- } else {
- switch(ft_type) {
- case NGX_HTTP_PROXY_FT_TIMEOUT:
- status = NGX_HTTP_GATEWAY_TIME_OUT;
- break;
-
- case NGX_HTTP_PROXY_FT_HTTP_500:
- status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
-
- case NGX_HTTP_PROXY_FT_HTTP_404:
- status = NGX_HTTP_NOT_FOUND;
- break;
-
- /*
- * NGX_HTTP_PROXY_FT_BUSY_LOCK and NGX_HTTP_PROXY_FT_MAX_WAITING
- * never reach here
- */
-
- default:
- status = NGX_HTTP_BAD_GATEWAY;
- }
- }
-
- if (p->upstream->peer.connection) {
- ngx_http_proxy_close_connection(p);
- }
-
- if (p->request->connection->write->eof) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- if (status) {
- p->state->status = status;
-
- if (p->upstream->peer.tries == 0 || !(p->lcf->next_upstream & ft_type))
- {
-
-#if (NGX_HTTP_CACHE)
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
-#endif
-
- ngx_http_proxy_finalize_request(p, status);
- return;
- }
- }
-
- if (p->lcf->busy_lock && !p->busy_locked) {
- ngx_http_proxy_upstream_busy_lock(p);
- } else {
- ngx_http_proxy_connect(p);
- }
-}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 870dd8bcc..514658ca2 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1503,6 +1503,10 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
return;
}
+ if (!r->post_action) {
+ r->request_complete = 1;
+ }
+
if (ngx_http_post_action(r) == NGX_OK) {
return;
}
@@ -2254,6 +2258,7 @@ ngx_http_post_action(ngx_http_request_t *r)
r->http_version = NGX_HTTP_VERSION_9;
r->header_only = 1;
+ r->post_action = 1;
ngx_http_internal_redirect(r, &clcf->post_action, NULL);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 8450b0434..7e1a43b5d 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -405,6 +405,8 @@ struct ngx_http_request_s {
unsigned lingering_close:1;
unsigned discard_body:1;
unsigned internal:1;
+ unsigned post_action:1;
+ unsigned request_complete:1;
unsigned done:1;
unsigned utf8:1;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 9fd1a1ebd..bfaed70a5 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -277,9 +277,9 @@ ngx_http_upstream_init(ngx_http_request_t *r)
ngx_del_timer(c->read);
}
- if (!(r->http_version == NGX_HTTP_VERSION_9 && r->header_only)) {
- /* not a post_action */
+ u = r->upstream;
+ if (!r->post_action && !u->conf->ignore_client_abort) {
r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
}
@@ -296,8 +296,6 @@ ngx_http_upstream_init(ngx_http_request_t *r)
}
}
- u = r->upstream;
-
if (r->request_body) {
u->request_bufs = r->request_body->bufs;
}
@@ -1208,10 +1206,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
rc = ngx_http_send_header(r);
- if (rc == NGX_ERROR
- || rc > NGX_OK
- /* post_action */
- || (r->http_version == NGX_HTTP_VERSION_9 && r->header_only)) {
+ if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
ngx_http_upstream_finalize_request(r, u, rc);
return;
}
@@ -1947,11 +1942,7 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
r->connection->log->action = "sending to client";
- if (rc == 0
- && r == r->main
- /* not a post_action */
- && !(r->http_version == NGX_HTTP_VERSION_9 && r->header_only))
- {
+ if (rc == 0 && r == r->main && !r->post_action) {
rc = ngx_http_send_special(r, NGX_HTTP_LAST);
}
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 117def185..4d07c3e7e 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -73,6 +73,7 @@ typedef struct {
ngx_flag_t pass_request_headers;
ngx_flag_t pass_request_body;
+ ngx_flag_t ignore_client_abort;
ngx_flag_t redirect_errors;
ngx_flag_t cyclic_temp_file;
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 1370162c1..261592978 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -44,6 +44,8 @@ static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
/*
@@ -135,6 +137,9 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("body_bytes_sent"), ngx_http_variable_body_bytes_sent,
0, 0, 0 },
+ { ngx_string("request_completion"), ngx_http_variable_request_completion,
+ 0, 0, 0 },
+
{ ngx_null_string, NULL, 0, 0, 0 }
};
@@ -798,6 +803,30 @@ ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
}
+static ngx_int_t
+ngx_http_variable_request_completion(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ if (r->request_complete) {
+ v->len = 2;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) "OK";
+
+ return NGX_OK;
+ }
+
+ v->len = 0;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) "";
+
+ return NGX_OK;
+}
+
+
ngx_int_t
ngx_http_variables_add_core_vars(ngx_conf_t *cf)
{