summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2007-04-19 18:17:35 +0000
committerJonathan Kolb <jon@b0g.us>2007-04-19 18:17:35 +0000
commitefb46f1637bbe2cf93311b48bd32e0c702ae2af7 (patch)
tree62932d911679ec18aef0af84308352d51ec5355a
parent71b65bfec6b3186bec60fd1dbfac47930ef71b99 (diff)
downloadnginx-0.5.18.tar.gz
Changes with nginx 0.5.18 19 Apr 2007v0.5.18
*) Feature: the ngx_http_sub_filter_module. *) Feature: the "$upstream_http_..." variables. *) Feature: now the $upstream_status and $upstream_response_time variables keep data about all upstreams before X-Accel-Redirect. *) Bugfix: a segmentation fault occurred in master process after first reconfiguration and receiving any signal if nginx was built with ngx_http_perl_module and perl did not support multiplicity; bug appeared in 0.5.9. *) Bugfix: if perl did not support multiplicity, then after reconfiguration perl code did not work; bug appeared in 0.3.38.
-rw-r--r--CHANGES18
-rw-r--r--CHANGES.ru19
-rw-r--r--auto/cc/icc7
-rw-r--r--auto/lib/pcre/make6
-rw-r--r--auto/modules5
-rw-r--r--auto/options3
-rw-r--r--auto/sources4
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_cycle.c13
-rw-r--r--src/core/ngx_regex.h6
-rw-r--r--src/http/modules/ngx_http_dav_module.c4
-rw-r--r--src/http/modules/ngx_http_log_module.c4
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c12
-rw-r--r--src/http/modules/ngx_http_sub_filter_module.c794
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c6
-rw-r--r--src/http/ngx_http_request.h5
-rw-r--r--src/http/ngx_http_upstream.c156
-rw-r--r--src/http/ngx_http_upstream.h4
-rw-r--r--src/http/ngx_http_variables.c23
-rw-r--r--src/http/ngx_http_variables.h4
-rw-r--r--src/mail/ngx_mail_auth_http_module.c20
-rw-r--r--src/mail/ngx_mail_core_module.c2
-rw-r--r--src/mail/ngx_mail_handler.c54
-rw-r--r--src/mail/ngx_mail_proxy_module.c18
25 files changed, 1063 insertions, 128 deletions
diff --git a/CHANGES b/CHANGES
index 8f1e326fd..bb62cffab 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,22 @@
+Changes with nginx 0.5.18 19 Apr 2007
+
+ *) Feature: the ngx_http_sub_filter_module.
+
+ *) Feature: the "$upstream_http_..." variables.
+
+ *) Feature: now the $upstream_status and $upstream_response_time
+ variables keep data about all upstreams before X-Accel-Redirect.
+
+ *) Bugfix: a segmentation fault occurred in master process after first
+ reconfiguration and receiving any signal if nginx was built with
+ ngx_http_perl_module and perl did not support multiplicity; bug
+ appeared in 0.5.9.
+
+ *) Bugfix: if perl did not support multiplicity, then after
+ reconfiguration perl code did not work; bug appeared in 0.3.38.
+
+
Changes with nginx 0.5.17 02 Apr 2007
*) Change: now nginx always returns the 405 status for the TRACE method.
diff --git a/CHANGES.ru b/CHANGES.ru
index 0d8fe2d72..302383d49 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,23 @@
+Изменения в nginx 0.5.18 19.04.2007
+
+ *) Добавление: модуль ngx_http_sub_filter_module.
+
+ *) Добавление: переменные "$upstream_http_...".
+
+ *) Добавление: теперь переменные $upstream_status и
+ $upstream_response_time содержат данные о всех обращениях к
+ апстримам, сделанным до X-Accel-Redirect.
+
+ *) Исправление: если nginx был собран с модулем ngx_http_perl_module и
+ perl не поддерживал multiplicity, то после первой переконфигурации и
+ после получения любого сигнала в основном процессе происходил
+ segmentation fault; ошибка появилась в 0.5.9.
+
+ *) Исправление: если perl не поддерживал multiplicity, то после
+ переконфигурации перловый код не работал; ошибка появилась в 0.3.38.
+
+
Изменения в nginx 0.5.17 02.04.2007
*) Изменение: теперь nginx для метода TRACE всегда возвращает код 405.
diff --git a/auto/cc/icc b/auto/cc/icc
index f1f9d3dcf..91dd95ecf 100644
--- a/auto/cc/icc
+++ b/auto/cc/icc
@@ -5,7 +5,7 @@
# Intel C++ compiler 7.1, 8.0, 8.1, 9.0
NGX_ICC_VER=`$CC -V 2>&1 | grep 'Version' 2>&1 \
- | sed -e 's/^.* Version \(.*\) Build.*$/\1/'`
+ | sed -e 's/^.* Version \([^ ]*\) *Build.*$/\1/'`
echo " + icc version: $NGX_ICC_VER"
@@ -26,6 +26,11 @@ case "$NGX_ICC_VER" in
IPO="-ipo"
;;
+ # 8.1.38 under FreeBSD can not link -ipo
+ 8.1)
+ IPO="-ip"
+ ;;
+
*)
IPO="-ipo -ipo_obj"
;;
diff --git a/auto/lib/pcre/make b/auto/lib/pcre/make
index f5723c852..219b52d73 100644
--- a/auto/lib/pcre/make
+++ b/auto/lib/pcre/make
@@ -53,14 +53,16 @@ END
*)
cat << END >> $NGX_MAKEFILE
-$PCRE/pcre.h: $NGX_MAKEFILE
+$PCRE/pcre.h: $PCRE/Makefile
+
+$PCRE/Makefile: $NGX_MAKEFILE
cd $PCRE \\
&& if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
&& CC="\$(CC)" CFLAGS="$PCRE_OPT" \\
./configure --disable-shared
-$PCRE/.libs/libpcre.a: $PCRE/pcre.h
+$PCRE/.libs/libpcre.a: $PCRE/Makefile
cd $PCRE \\
&& \$(MAKE) libpcre.la
diff --git a/auto/modules b/auto/modules
index dfd6f1220..ee5462dc4 100644
--- a/auto/modules
+++ b/auto/modules
@@ -129,6 +129,11 @@ if [ $HTTP_SSI = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS"
fi
+if [ $HTTP_SUB = YES ]; then
+ HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SUB_FILTER_MODULE"
+ HTTP_SRCS="$HTTP_SRCS $HTTP_SUB_SRCS"
+fi
+
if [ $HTTP_ADDITION = YES ]; then
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_ADDITION_FILTER_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_ADDITION_SRCS"
diff --git a/auto/options b/auto/options
index 379bb2318..6a48076c5 100644
--- a/auto/options
+++ b/auto/options
@@ -53,6 +53,7 @@ HTTP_SSL=NO
HTTP_SSI=YES
HTTP_POSTPONE=NO
HTTP_REALIP=NO
+HTTP_SUB=NO
HTTP_ADDITION=NO
HTTP_DAV=NO
HTTP_ACCESS=YES
@@ -152,6 +153,7 @@ do
--with-http_ssl_module) HTTP_SSL=YES ;;
--with-http_realip_module) HTTP_REALIP=YES ;;
--with-http_addition_module) HTTP_ADDITION=YES ;;
+ --with-http_sub_module) HTTP_SUB=YES ;;
--with-http_dav_module) HTTP_DAV=YES ;;
--with-http_flv_module) HTTP_FLV=YES ;;
@@ -259,6 +261,7 @@ cat << END
--with-http_ssl_module enable ngx_http_ssl_module
--with-http_realip_module enable ngx_http_realip_module
--with-http_addition_module enable ngx_http_addition_module
+ --with-http_sub_module enable ngx_http_sub_module
--with-http_dav_module enable ngx_http_dav_module
--with-http_flv_module enable ngx_http_flv_module
diff --git a/auto/sources b/auto/sources
index 0632d39f8..44d82ee02 100644
--- a/auto/sources
+++ b/auto/sources
@@ -317,6 +317,10 @@ HTTP_SSI_DEPS=src/http/modules/ngx_http_ssi_filter_module.h
HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter_module.c
+HTTP_SUB_FILTER_MODULE=ngx_http_sub_filter_module
+HTTP_SUB_SRCS=src/http/modules/ngx_http_sub_filter_module.c
+
+
HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module
HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter_module.c
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 4a1c31377..d1e3f431f 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.5.17"
+#define NGINX_VERSION "0.5.18"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 243febd0e..f900a2824 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -54,11 +54,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
ngx_list_part_t *part, *opart;
ngx_open_file_t *file;
ngx_listening_t *ls, *nls;
- ngx_core_conf_t *ccf;
+ ngx_core_conf_t *ccf, *old_ccf;
ngx_core_module_t *module;
-#if !(WIN32)
- ngx_core_conf_t *old_ccf;
-#endif
log = old_cycle->log;
@@ -747,6 +744,14 @@ old_shm_zone_done:
failed:
+ if (!ngx_is_init_cycle(old_cycle)) {
+ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,
+ ngx_core_module);
+ if (old_ccf->environment) {
+ environ = old_ccf->environment;
+ }
+ }
+
/* rollback the new cycle configuration */
part = &cycle->open_files.part;
diff --git a/src/core/ngx_regex.h b/src/core/ngx_regex.h
index 7eefdbe49..430637721 100644
--- a/src/core/ngx_regex.h
+++ b/src/core/ngx_regex.h
@@ -22,10 +22,10 @@ typedef pcre ngx_regex_t;
void ngx_regex_init(void);
ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options,
- ngx_pool_t *pool, ngx_str_t *err);
+ ngx_pool_t *pool, ngx_str_t *err);
ngx_int_t ngx_regex_capture_count(ngx_regex_t *re);
-ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s,
- int *captures, ngx_int_t size);
+ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures,
+ ngx_int_t size);
#define ngx_regex_exec_n "pcre_exec()"
#define ngx_regex_capture_count_n "pcre_fullinfo()"
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index f0b70cabc..9fab59bf7 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -585,7 +585,7 @@ destination_done:
if (depth != 0 && depth != NGX_HTTP_DAV_INFINITY_DEPTH) {
return NGX_HTTP_BAD_REQUEST;
}
-
+
over = r->headers_in.overwrite;
if (over) {
@@ -1003,7 +1003,7 @@ static ngx_int_t
ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt)
{
ngx_table_elt_t *depth;
-
+
depth = r->headers_in.depth;
if (depth == NULL) {
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index 55328312c..e4b861bf0 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -302,7 +302,7 @@ ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
log->disk_full_time = now;
}
- if (now - log->error_log_time > 60) {
+ if (now - log->error_log_time > 59) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
ngx_write_fd_n " to \"%V\" failed",
&log->file->name);
@@ -313,7 +313,7 @@ ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
return;
}
- if (now - log->error_log_time > 60) {
+ if (now - log->error_log_time > 59) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
ngx_write_fd_n " to \"%V\" was incomplete: %z of %uz",
&log->file->name, n, len);
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index e1d0e924d..79e89f18a 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -107,8 +107,8 @@ static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_ssi_preconfiguration(ngx_conf_t *cf);
static void *ngx_http_ssi_create_main_conf(ngx_conf_t *cf);
static char *ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf);
-static void *ngx_http_ssi_create_conf(ngx_conf_t *cf);
-static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf,
+static void *ngx_http_ssi_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_http_ssi_filter_init(ngx_conf_t *cf);
@@ -173,8 +173,8 @@ static ngx_http_module_t ngx_http_ssi_filter_module_ctx = {
NULL, /* create server configuration */
NULL, /* merge server configuration */
- ngx_http_ssi_create_conf, /* create location configuration */
- ngx_http_ssi_merge_conf /* merge location configuration */
+ ngx_http_ssi_create_loc_conf, /* create location configuration */
+ ngx_http_ssi_merge_loc_conf /* merge location configuration */
};
@@ -2746,7 +2746,7 @@ ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf)
static void *
-ngx_http_ssi_create_conf(ngx_conf_t *cf)
+ngx_http_ssi_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_ssi_loc_conf_t *slcf;
@@ -2773,7 +2773,7 @@ ngx_http_ssi_create_conf(ngx_conf_t *cf)
static char *
-ngx_http_ssi_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_ssi_loc_conf_t *prev = parent;
ngx_http_ssi_loc_conf_t *conf = child;
diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c
new file mode 100644
index 000000000..d196c1966
--- /dev/null
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -0,0 +1,794 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+ ngx_str_t match;
+ ngx_str_t sub;
+
+ ngx_array_t *types; /* array of ngx_str_t */
+
+ ngx_array_t *sub_lengths;
+ ngx_array_t *sub_values;
+
+ ngx_flag_t once;
+} ngx_http_sub_loc_conf_t;
+
+
+typedef enum {
+ sub_start_state = 0,
+ sub_match_state,
+} ngx_http_sub_state_e;
+
+
+typedef struct {
+ ngx_str_t match;
+
+ ngx_uint_t once; /* unsigned once:1 */
+
+ ngx_buf_t *buf;
+
+ u_char *pos;
+ u_char *copy_start;
+ u_char *copy_end;
+
+ ngx_chain_t *in;
+ ngx_chain_t *out;
+ ngx_chain_t **last_out;
+ ngx_chain_t *busy;
+ ngx_chain_t *free;
+
+ ngx_str_t sub;
+
+ ngx_uint_t state;
+ size_t saved;
+ size_t looked;
+} ngx_http_sub_ctx_t;
+
+
+static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r,
+ ngx_http_sub_ctx_t *ctx);
+static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r,
+ ngx_http_sub_ctx_t *ctx);
+
+static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static char *ngx_http_sub_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static void *ngx_http_sub_create_conf(ngx_conf_t *cf);
+static char *ngx_http_sub_merge_conf(ngx_conf_t *cf,
+ void *parent, void *child);
+static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf);
+
+
+static ngx_command_t ngx_http_sub_filter_commands[] = {
+
+ { ngx_string("sub_filter"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+ ngx_http_sub_filter,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("sub_filter_types"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_http_sub_types,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("sub_filter_once"),
+ 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_sub_loc_conf_t, once),
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_http_module_t ngx_http_sub_filter_module_ctx = {
+ NULL, /* preconfiguration */
+ ngx_http_sub_filter_init, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_http_sub_create_conf, /* create location configuration */
+ ngx_http_sub_merge_conf /* merge location configuration */
+};
+
+
+ngx_module_t ngx_http_sub_filter_module = {
+ NGX_MODULE_V1,
+ &ngx_http_sub_filter_module_ctx, /* module context */
+ ngx_http_sub_filter_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* 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_sub_header_filter(ngx_http_request_t *r)
+{
+ ngx_str_t *type;
+ ngx_uint_t i;
+ ngx_http_sub_ctx_t *ctx;
+ ngx_http_sub_loc_conf_t *slcf;
+
+ slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
+
+ if (slcf->match.len == 0
+ || r->headers_out.content_type.len == 0
+ || r->headers_out.content_length_n == 0)
+ {
+ return ngx_http_next_header_filter(r);
+ }
+
+ type = slcf->types->elts;
+ for (i = 0; i < slcf->types->nelts; i++) {
+ if (r->headers_out.content_type.len >= type[i].len
+ && ngx_strncasecmp(r->headers_out.content_type.data,
+ type[i].data, type[i].len) == 0)
+ {
+ goto found;
+ }
+ }
+
+ return ngx_http_next_header_filter(r);
+
+found:
+
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
+
+ ctx->match = slcf->match;
+ ctx->last_out = &ctx->out;
+ ctx->sub = slcf->sub;
+
+ r->filter_need_in_memory = 1;
+
+ if (r == r->main) {
+ ngx_http_clear_content_length(r);
+ ngx_http_clear_last_modified(r);
+ }
+
+ return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ ngx_int_t rc;
+ ngx_buf_t *b;
+ ngx_chain_t *cl;
+ ngx_http_sub_ctx_t *ctx;
+ ngx_http_sub_loc_conf_t *slcf;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module);
+
+ if (ctx == NULL) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ if ((in == NULL
+ && ctx->buf == NULL
+ && ctx->in == NULL
+ && ctx->busy == NULL))
+ {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ if (ctx->once && (ctx->buf == NULL || ctx->in == NULL)) {
+
+ if (ctx->busy) {
+ if (ngx_http_sub_output(r, ctx) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+ }
+
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ /* add the incoming chain to the chain ctx->in */
+
+ if (in) {
+ if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http sub filter \"%V\"", &r->uri);
+
+ while (ctx->in || ctx->buf) {
+
+ if (ctx->buf == NULL ){
+ ctx->buf = ctx->in->buf;
+ ctx->in = ctx->in->next;
+ ctx->pos = ctx->buf->pos;
+ }
+
+ if (ctx->state == sub_start_state) {
+ ctx->copy_start = ctx->pos;
+ ctx->copy_end = ctx->pos;
+ }
+
+ b = NULL;
+
+ while (ctx->pos < ctx->buf->last) {
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "saved: %d state: %d", ctx->saved, ctx->state);
+
+ rc = ngx_http_sub_parse(r, ctx);
+
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "parse: %d, looked: %d %p-%p",
+ rc, ctx->looked, ctx->copy_start, ctx->copy_end);
+
+ if (rc == NGX_ERROR) {
+ return rc;
+ }
+
+ if (ctx->copy_start != ctx->copy_end) {
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "saved: %d", ctx->saved);
+
+ if (ctx->saved) {
+
+ if (ctx->free) {
+ cl = ctx->free;
+ ctx->free = ctx->free->next;
+ b = cl->buf;
+ ngx_memzero(b, sizeof(ngx_buf_t));
+
+ } else {
+ b = ngx_calloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+ }
+
+ b->memory = 1;
+ b->pos = ctx->match.data;
+ b->last = ctx->match.data + ctx->saved;
+
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+
+ ctx->saved = 0;
+ }
+
+ if (ctx->free) {
+ cl = ctx->free;
+ ctx->free = ctx->free->next;
+ b = cl->buf;
+
+ } else {
+ b = ngx_alloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+ }
+
+ ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
+
+ b->pos = ctx->copy_start;
+ b->last = ctx->copy_end;
+ b->shadow = NULL;
+ b->last_buf = 0;
+ b->recycled = 0;
+
+ if (b->in_file) {
+ b->file_last = b->file_pos + (b->last - b->start);
+ b->file_pos += b->pos - b->start;
+ }
+
+ cl->next = NULL;
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+ }
+
+ if (ctx->state == sub_start_state) {
+ ctx->copy_start = ctx->pos;
+ ctx->copy_end = ctx->pos;
+
+ } else {
+ ctx->copy_start = NULL;
+ ctx->copy_end = NULL;
+ }
+
+ if (rc == NGX_AGAIN) {
+ continue;
+ }
+
+
+ /* rc == NGX_OK */
+
+ b = ngx_calloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
+
+ if (ctx->sub.data == NULL) {
+
+ if (ngx_http_script_run(r, &ctx->sub, slcf->sub_lengths->elts,
+ 0, slcf->sub_values->elts)
+ == NULL)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ b->memory = 1;
+ b->pos = ctx->sub.data;
+ b->last = ctx->sub.data + ctx->sub.len;
+
+ cl->buf = b;
+ cl->next = NULL;
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+
+ ctx->once = slcf->once;
+
+ continue;
+ }
+
+ if (ctx->buf->last_buf || ngx_buf_in_memory(ctx->buf)) {
+ if (b == NULL) {
+ if (ctx->free) {
+ cl = ctx->free;
+ ctx->free = ctx->free->next;
+ b = cl->buf;
+ ngx_memzero(b, sizeof(ngx_buf_t));
+
+ } else {
+ b = ngx_calloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+ }
+
+ b->sync = 1;
+
+ cl->next = NULL;
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+ }
+
+ b->last_buf = ctx->buf->last_buf;
+ b->shadow = ctx->buf;
+
+ b->recycled = ctx->buf->recycled;
+ }
+
+ ctx->buf = NULL;
+
+ ctx->saved = ctx->looked;
+ }
+
+ if (ctx->out == NULL && ctx->busy == NULL) {
+ return NGX_OK;
+ }
+
+ return ngx_http_sub_output(r, ctx);
+}
+
+
+static ngx_int_t
+ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
+{
+ ngx_int_t rc;
+ ngx_buf_t *b;
+ ngx_chain_t *cl;
+
+#if 1
+ b = NULL;
+ for (cl = ctx->out; cl; cl = cl->next) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "sub out: %p %p", cl->buf, cl->buf->pos);
+ if (cl->buf == b) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "the same buf was used in sub");
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
+ b = cl->buf;
+ }
+#endif
+
+ rc = ngx_http_next_body_filter(r, ctx->out);
+
+ if (ctx->busy == NULL) {
+ ctx->busy = ctx->out;
+
+ } else {
+ for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ }
+ cl->next = ctx->out;
+ }
+
+ ctx->out = NULL;
+ ctx->last_out = &ctx->out;
+
+ while (ctx->busy) {
+
+ cl = ctx->busy;
+ b = cl->buf;
+
+ if (ngx_buf_size(b) != 0) {
+ break;
+ }
+
+#if (NGX_HAVE_WRITE_ZEROCOPY)
+ if (b->zerocopy_busy) {
+ break;
+ }
+#endif
+
+ if (b->shadow) {
+ b->shadow->pos = b->shadow->last;
+ }
+
+ ctx->busy = cl->next;
+
+ if (ngx_buf_in_memory(b) || b->in_file) {
+ /* add data bufs only to the free buf chain */
+
+ cl->next = ctx->free;
+ ctx->free = cl;
+ }
+ }
+
+ if (ctx->in || ctx->buf) {
+ r->buffered |= NGX_HTTP_SUB_BUFFERED;
+
+ } else {
+ r->buffered &= ~NGX_HTTP_SUB_BUFFERED;
+ }
+
+ return rc;
+}
+
+
+static ngx_int_t
+ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
+{
+ u_char *p, *last, *copy_end, ch, match;
+ size_t looked;
+ ngx_http_sub_state_e state;
+
+ if (ctx->once) {
+ ctx->copy_start = ctx->pos;
+ ctx->copy_end = ctx->buf->last;
+ ctx->pos = ctx->buf->last;
+ ctx->looked = 0;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once");
+
+ return NGX_AGAIN;
+ }
+
+ state = ctx->state;
+ looked = ctx->looked;
+ last = ctx->buf->last;
+ copy_end = ctx->copy_end;
+
+ for (p = ctx->pos; p < last; p++) {
+
+ ch = *p;
+ ch = ngx_tolower(ch);
+
+ if (state == sub_start_state) {
+
+ /* the tight loop */
+
+ match = ctx->match.data[0];
+
+ for ( ;; ) {
+ if (ch == match) {
+ copy_end = p;
+ looked = 1;
+ state = sub_match_state;
+
+ goto match_started;
+ }
+
+ if (++p == last) {
+ break;
+ }
+
+ ch = *p;
+ ch = ngx_tolower(ch);
+ }
+
+ ctx->pos = p;
+ ctx->looked = looked;
+ ctx->copy_end = p;
+
+ if (ctx->copy_start == NULL) {
+ ctx->copy_start = ctx->buf->pos;
+ }
+
+ return NGX_AGAIN;
+
+ match_started:
+
+ continue;
+ }
+
+ /* state == sub_match_state */
+
+ if (ch == ctx->match.data[looked]) {
+ looked++;
+
+ if (looked == ctx->match.len) {
+ ctx->state = sub_start_state;
+ ctx->pos = p + 1;
+ ctx->looked = looked;
+ ctx->copy_end = copy_end;
+
+ if (ctx->copy_start == NULL && copy_end) {
+ ctx->copy_start = ctx->buf->pos;
+ }
+
+ return NGX_OK;
+ }
+
+ } else if (ch == ctx->match.data[0]) {
+ copy_end = p;
+ looked = 1;
+
+ } else {
+ copy_end = p;
+ looked = 0;
+ state = sub_start_state;
+ }
+ }
+
+ ctx->state = state;
+ ctx->pos = p;
+ ctx->looked = looked;
+
+ ctx->copy_end = (state == sub_start_state) ? p : copy_end;
+
+ if (ctx->copy_start == NULL && ctx->copy_end) {
+ ctx->copy_start = ctx->buf->pos;
+ }
+
+ return NGX_AGAIN;
+}
+
+
+static char *
+ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_sub_loc_conf_t *slcf = conf;
+
+ ngx_str_t *value;
+ ngx_int_t n;
+ ngx_uint_t i;
+ ngx_http_script_compile_t sc;
+
+ if (slcf->match.len) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ slcf->match = value[1];
+
+ for (i = 0; i < value[1].len; i++) {
+ value[1].data[i] = ngx_tolower(value[1].data[i]);
+ }
+
+ n = ngx_http_script_variables_count(&value[2]);
+
+ if (n == 0) {
+ slcf->sub = value[2];
+ return NGX_CONF_OK;
+ }
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &value[2];
+ sc.lengths = &slcf->sub_lengths;
+ sc.values = &slcf->sub_values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_sub_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_sub_loc_conf_t *slcf = conf;
+
+ ngx_str_t *value, *type;
+ ngx_uint_t i;
+
+ if (slcf->types == NULL) {
+ slcf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
+ if (slcf->types == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ type = ngx_array_push(slcf->types);
+ if (type == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ type->len = sizeof("text/html") - 1;
+ type->data = (u_char *) "text/html";
+ }
+
+ value = cf->args->elts;
+
+ for (i = 1; i < cf->args->nelts; i++) {
+
+ if (ngx_strcmp(value[i].data, "text/html") == 0) {
+ continue;
+ }
+
+ type = ngx_array_push(slcf->types);
+ if (type == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ type->len = value[i].len;
+
+ type->data = ngx_palloc(cf->pool, type->len + 1);
+ if (type->data == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_cpystrn(type->data, value[i].data, type->len + 1);
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static void *
+ngx_http_sub_create_conf(ngx_conf_t *cf)
+{
+ ngx_http_sub_loc_conf_t *slcf;
+
+ slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sub_loc_conf_t));
+ if (slcf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ /*
+ * set by ngx_pcalloc():
+ *
+ * conf->match.len = 0;
+ * conf->match.data = NULL;
+ * conf->sub.len = 0;
+ * conf->sub.data = NULL;
+ * conf->sub_lengths = NULL;
+ * conf->sub_values = NULL;
+ * conf->types = NULL;
+ */
+
+ slcf->once = NGX_CONF_UNSET;
+
+ return slcf;
+}
+
+
+static char *
+ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_http_sub_loc_conf_t *prev = parent;
+ ngx_http_sub_loc_conf_t *conf = child;
+
+ ngx_str_t *type;
+
+ ngx_conf_merge_value(conf->once, prev->once, 1);
+ ngx_conf_merge_str_value(conf->match, prev->match, "");
+
+ if (conf->sub.data == NULL && conf->sub_lengths == NULL) {
+ conf->sub = prev->sub;
+ conf->sub_lengths = prev->sub_lengths;
+ conf->sub_values = prev->sub_values;
+ }
+
+ if (conf->types == NULL) {
+ if (prev->types == NULL) {
+ conf->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
+ if (conf->types == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ type = ngx_array_push(conf->types);
+ if (type == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ type->len = sizeof("text/html") - 1;
+ type->data = (u_char *) "text/html";
+
+ } else {
+ conf->types = prev->types;
+ }
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_sub_filter_init(ngx_conf_t *cf)
+{
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
+ ngx_http_top_header_filter = ngx_http_sub_header_filter;
+
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_sub_body_filter;
+
+ return NGX_OK;
+}
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index d58927351..7679367e6 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.5.17';
+our $VERSION = '0.5.18';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index bfdcb647c..b11320dad 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -459,6 +459,11 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
#if !(NGX_HAVE_PERL_MULTIPLICITY)
if (perl) {
+
+ if (ngx_set_environment(cf->cycle, NULL) == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log)
!= NGX_OK)
{
@@ -466,6 +471,7 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
}
pmcf->perl = perl;
+ pmcf->nginx = nginx_stash;
return NGX_CONF_OK;
}
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 939e16960..414efd7a2 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -124,7 +124,8 @@
#define NGX_HTTP_WRITE_BUFFERED 0x10
#define NGX_HTTP_GZIP_BUFFERED 0x20
#define NGX_HTTP_SSI_BUFFERED 0x01
-#define NGX_HTTP_COPY_BUFFERED 0x02
+#define NGX_HTTP_SUB_BUFFERED 0x02
+#define NGX_HTTP_COPY_BUFFERED 0x04
typedef enum {
@@ -329,6 +330,8 @@ struct ngx_http_request_s {
ngx_http_cache_t *cache;
ngx_http_upstream_t *upstream;
+ ngx_array_t *upstream_states;
+ /* of ngx_http_upstream_state_t */
ngx_pool_t *pool;
ngx_buf_t *header_in;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 888bb3b26..fe7ae4a53 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -328,12 +328,25 @@ ngx_http_upstream_init(ngx_http_request_t *r)
u->writer.pool = r->pool;
- if (ngx_array_init(&u->states, r->pool, 1,
- sizeof(ngx_http_upstream_state_t))
- != NGX_OK)
- {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
+ if (r->upstream_states == NULL) {
+
+ r->upstream_states = ngx_array_create(r->pool, 1,
+ sizeof(ngx_http_upstream_state_t));
+ if (r->upstream_states == NULL) {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ } else {
+
+ u->state = ngx_array_push(r->upstream_states);
+ if (u->state == NULL) {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));
}
cln = ngx_http_cleanup_add(r, 0);
@@ -509,7 +522,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->state->response_msec = tp->msec - u->state->response_msec;
}
- u->state = ngx_array_push(&u->states);
+ u->state = ngx_array_push(r->upstream_states);
if (u->state == NULL) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -767,7 +780,7 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
"http upstream send request");
if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
- ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
return;
}
@@ -914,7 +927,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
}
if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
- ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
return;
}
@@ -1259,33 +1272,33 @@ ngx_http_upstream_test_connect(ngx_connection_t *c)
#if (NGX_HAVE_KQUEUE)
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
- if (c->write->pending_eof) {
- (void) ngx_connection_error(c, c->write->kq_errno,
- "kevent() reported that connect() failed");
- return NGX_ERROR;
- }
+ if (c->write->pending_eof) {
+ (void) ngx_connection_error(c, c->write->kq_errno,
+ "kevent() reported that connect() failed");
+ return NGX_ERROR;
+ }
} else
#endif
{
- err = 0;
- len = sizeof(int);
+ err = 0;
+ len = sizeof(int);
- /*
- * BSDs and Linux return 0 and set a pending error in err
- * Solaris returns -1 and sets errno
- */
+ /*
+ * BSDs and Linux return 0 and set a pending error in err
+ * Solaris returns -1 and sets errno
+ */
- if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
- == -1)
- {
- err = ngx_errno;
- }
+ if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
+ == -1)
+ {
+ err = ngx_errno;
+ }
- if (err) {
- (void) ngx_connection_error(c, err, "connect() failed");
- return NGX_ERROR;
- }
+ if (err) {
+ (void) ngx_connection_error(c, err, "connect() failed");
+ return NGX_ERROR;
+ }
}
return NGX_OK;
@@ -2502,21 +2515,18 @@ ngx_http_upstream_status_variable(ngx_http_request_t *r,
u_char *p;
size_t len;
ngx_uint_t i;
- ngx_http_upstream_t *u;
ngx_http_upstream_state_t *state;
v->valid = 1;
v->no_cachable = 0;
v->not_found = 0;
- u = r->upstream;
-
- if (u == NULL || u->states.nelts == 0) {
+ if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
v->not_found = 1;
return NGX_OK;
}
- len = u->states.nelts * (3 + 2);
+ len = r->upstream_states->nelts * (3 + 2);
p = ngx_palloc(r->pool, len);
if (p == NULL) {
@@ -2526,22 +2536,35 @@ ngx_http_upstream_status_variable(ngx_http_request_t *r,
v->data = p;
i = 0;
- state = u->states.elts;
+ state = r->upstream_states->elts;
for ( ;; ) {
- if (state[i].status == 0) {
- *p++ = '-';
+ if (state[i].status) {
+ p = ngx_sprintf(p, "%ui", state[i].status);
} else {
- p = ngx_sprintf(p, "%ui", state[i].status);
+ *p++ = '-';
}
- if (++i == u->states.nelts) {
+ if (++i == r->upstream_states->nelts) {
break;
}
- *p++ = ',';
- *p++ = ' ';
+ if (state[i].peer) {
+ *p++ = ',';
+ *p++ = ' ';
+
+ } else {
+ *p++ = ' ';
+ *p++ = ':';
+ *p++ = ' ';
+
+ if (++i == r->upstream_states->nelts) {
+ break;
+ }
+
+ continue;
+ }
}
v->len = p - v->data;
@@ -2558,21 +2581,18 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
size_t len;
ngx_uint_t i;
ngx_msec_int_t ms;
- ngx_http_upstream_t *u;
ngx_http_upstream_state_t *state;
v->valid = 1;
v->no_cachable = 0;
v->not_found = 0;
- u = r->upstream;
-
- if (u == NULL || u->states.nelts == 0) {
+ if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
v->not_found = 1;
return NGX_OK;
}
- len = u->states.nelts * (NGX_TIME_T_LEN + 4 + 2);
+ len = r->upstream_states->nelts * (NGX_TIME_T_LEN + 4 + 2);
p = ngx_palloc(r->pool, len);
if (p == NULL) {
@@ -2582,24 +2602,37 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
v->data = p;
i = 0;
- state = u->states.elts;
+ state = r->upstream_states->elts;
for ( ;; ) {
- if (state[i].status == 0) {
- *p++ = '-';
-
- } else {
+ if (state[i].status) {
ms = state[i].response_sec * 1000 + state[i].response_msec;
ms = (ms >= 0) ? ms : 0;
p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
+
+ } else {
+ *p++ = '-';
}
- if (++i == u->states.nelts) {
+ if (++i == r->upstream_states->nelts) {
break;
}
- *p++ = ',';
- *p++ = ' ';
+ if (state[i].peer) {
+ *p++ = ',';
+ *p++ = ' ';
+
+ } else {
+ *p++ = ' ';
+ *p++ = ':';
+ *p++ = ' ';
+
+ if (++i == r->upstream_states->nelts) {
+ break;
+ }
+
+ continue;
+ }
}
v->len = p - v->data;
@@ -2608,6 +2641,21 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
}
+ngx_int_t
+ngx_http_upstream_header_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ if (r->upstream == NULL) {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
+ &r->upstream->headers_in.headers.part,
+ sizeof("upstream_http_") - 1);
+}
+
+
static char *
ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index aa5cc3518..b2e3f3e93 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -232,7 +232,6 @@ struct ngx_http_upstream_s {
ngx_str_t method;
ngx_http_upstream_state_t *state;
- ngx_array_t states; /* of ngx_http_upstream_state_t */
ngx_str_t uri;
@@ -248,6 +247,9 @@ struct ngx_http_upstream_s {
};
+ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+
void ngx_http_upstream_init(ngx_http_request_t *r);
ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
ngx_url_t *u, ngx_uint_t flags);
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 5a9b06fe1..5aac76b76 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -23,8 +23,6 @@ static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v,
- ngx_str_t *var, ngx_list_part_t *part, size_t prefix);
static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@@ -451,6 +449,17 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key,
return NULL;
}
+ if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) {
+
+ if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
+ == NGX_OK)
+ {
+ return vv;
+ }
+
+ return NULL;
+ }
+
vv->not_found = 1;
if (nowarn == 0) {
@@ -614,7 +623,7 @@ ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
}
-static ngx_int_t
+ngx_int_t
ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
ngx_list_part_t *part, size_t prefix)
{
@@ -1292,6 +1301,14 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
continue;
}
+ if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) {
+ v[i].get_handler = ngx_http_upstream_header_variable;
+ v[i].data = (uintptr_t) &v[i].name;
+ v[i].flags = NGX_HTTP_VAR_NOCACHABLE;
+
+ continue;
+ }
+
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"unknown \"%V\" variable", &v[i].name);
diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h
index 8a24ffbc7..df487e48e 100644
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -61,6 +61,10 @@ ngx_http_variable_value_t *ngx_http_get_flushed_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r,
ngx_str_t *name, ngx_uint_t key, ngx_uint_t nowarn);
+ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v,
+ ngx_str_t *var, ngx_list_part_t *part, size_t prefix);
+
+
#define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL;
diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c
index febeb55ff..8028c957a 100644
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -686,19 +686,19 @@ ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
ctx->err.len = ctx->errcode.len + ctx->errmsg.len
+ sizeof(" " CRLF) - 1;
- p = ngx_palloc(s->connection->pool, ctx->err.len);
- if (p == NULL) {
- ngx_close_connection(ctx->peer.connection);
- ngx_destroy_pool(ctx->pool);
- ngx_mail_session_internal_server_error(s);
- return;
- }
+ p = ngx_palloc(s->connection->pool, ctx->err.len);
+ if (p == NULL) {
+ ngx_close_connection(ctx->peer.connection);
+ ngx_destroy_pool(ctx->pool);
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
- ctx->err.data = p;
+ ctx->err.data = p;
- p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len);
+ p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len);
*p++ = ' ';
- p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len);
+ p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len);
*p++ = CR; *p = LF;
}
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index 43dcde454..ba62d5553 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -63,7 +63,7 @@ static ngx_conf_bitmask_t ngx_smtp_auth_methods[] = {
static ngx_str_t ngx_smtp_auth_methods_names[] = {
- ngx_string("PLAIN"),
+ ngx_string("PLAIN"),
ngx_string("LOGIN"),
ngx_null_string, /* APOP */
ngx_string("CRAM-MD5")
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
index 418d1444e..e41983248 100644
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -297,19 +297,19 @@ ngx_mail_init_session(ngx_connection_t *c)
- s->salt.data;
if (s->protocol == NGX_MAIL_POP3_PROTOCOL) {
- s->out.data = ngx_palloc(c->pool,
+ s->out.data = ngx_palloc(c->pool,
greetings[0].len + 1 + s->salt.len);
- if (s->out.data == NULL) {
- ngx_mail_session_internal_server_error(s);
- return;
- }
+ if (s->out.data == NULL) {
+ ngx_mail_session_internal_server_error(s);
+ return;
+ }
- p = ngx_cpymem(s->out.data,
+ p = ngx_cpymem(s->out.data,
greetings[0].data, greetings[0].len - 2);
- *p++ = ' ';
- p = ngx_cpymem(p, s->salt.data, s->salt.len);
+ *p++ = ' ';
+ p = ngx_cpymem(p, s->salt.data, s->salt.len);
- s->out.len = p - s->out.data;
+ s->out.len = p - s->out.data;
}
}
@@ -1408,31 +1408,31 @@ ngx_smtp_auth_state(ngx_event_t *rev)
case NGX_SMTP_MAIL:
if (s->connection->log->log_level >= NGX_LOG_INFO) {
- l.len = s->buffer->last - s->buffer->start;
- l.data = s->buffer->start;
+ l.len = s->buffer->last - s->buffer->start;
+ l.data = s->buffer->start;
- for (i = 0; i < l.len; i++) {
- ch = l.data[i];
+ for (i = 0; i < l.len; i++) {
+ ch = l.data[i];
- if (ch != CR && ch != LF) {
- continue;
- }
+ if (ch != CR && ch != LF) {
+ continue;
+ }
- l.data[i] = ' ';
- }
+ l.data[i] = ' ';
+ }
- while (i) {
- if (l.data[i - 1] != ' ') {
- break;
- }
+ while (i) {
+ if (l.data[i - 1] != ' ') {
+ break;
+ }
- i--;
- }
+ i--;
+ }
- l.len = i;
+ l.len = i;
- ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
- "client was rejected: \"%V\"", &l);
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ "client was rejected: \"%V\"", &l);
}
text = smtp_auth_required;
diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c
index 03f21eb4c..894c01d04 100644
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -702,20 +702,20 @@ ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state)
case ngx_smtp_helo:
case ngx_smtp_noxclient:
- if (p[0] == '2' && p[1] == '5' && p[2] == '0') {
- return NGX_OK;
- }
- break;
+ if (p[0] == '2' && p[1] == '5' && p[2] == '0') {
+ return NGX_OK;
+ }
+ break;
case ngx_smtp_start:
case ngx_smtp_xclient:
- if (p[0] == '2' && p[1] == '2' && p[2] == '0') {
- return NGX_OK;
- }
- break;
+ if (p[0] == '2' && p[1] == '2' && p[2] == '0') {
+ return NGX_OK;
+ }
+ break;
}
- break;
+ break;
}
pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);