summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2009-05-01 18:53:04 +0000
committerJonathan Kolb <jon@b0g.us>2009-05-01 18:53:04 +0000
commit1a537756bb9d3018ea6ab099b22e9734cc8a879d (patch)
tree6d2fe235b46b0de3053db6c84739db4f34e674e7
parentb04081c3ce5d031367a0142d57e287e26ba2e415 (diff)
downloadnginx-0.7.54.tar.gz
Changes with nginx 0.7.54 01 May 2009v0.7.54
*) Feature: the ngx_http_image_filter_module. *) Feature: the "proxy_ignore_headers" and "fastcgi_ignore_headers" directives. *) Bugfix: a segmentation fault might occur in worker process, if an "open_file_cache_errors off" directive was used; the bug had appeared in 0.7.53. *) Bugfix: the "port_in_redirect off" directive did not work; the bug had appeared in 0.7.39. *) Bugfix: improve handling of "select" method errors. *) Bugfix: of "select() failed (10022: ...)" error in nginx/Windows. *) Bugfix: in error text descriptions in nginx/Windows; the bug had appeared in 0.7.53.
-rw-r--r--CHANGES22
-rw-r--r--CHANGES.ru21
-rw-r--r--auto/lib/conf4
-rw-r--r--auto/lib/libgd/conf81
-rw-r--r--auto/modules7
-rw-r--r--auto/options3
-rw-r--r--auto/sources4
-rw-r--r--src/core/nginx.c2
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_conf_file.c48
-rw-r--r--src/core/ngx_connection.c15
-rw-r--r--src/core/ngx_connection.h1
-rw-r--r--src/core/ngx_cycle.c28
-rw-r--r--src/core/ngx_cycle.h2
-rw-r--r--src/core/ngx_file.c4
-rw-r--r--src/core/ngx_log.c143
-rw-r--r--src/core/ngx_log.h5
-rw-r--r--src/core/ngx_open_file_cache.c7
-rw-r--r--src/core/ngx_resolver.c6
-rw-r--r--src/core/ngx_string.c28
-rw-r--r--src/core/ngx_string.h6
-rw-r--r--src/event/modules/ngx_select_module.c139
-rw-r--r--src/event/ngx_event.c8
-rw-r--r--src/event/ngx_event_openssl.c2
-rw-r--r--src/http/modules/ngx_http_dav_module.c8
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c22
-rw-r--r--src/http/modules/ngx_http_image_filter_module.c1026
-rw-r--r--src/http/modules/ngx_http_proxy_module.c48
-rw-r--r--src/http/modules/ngx_http_xslt_filter_module.c22
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http.c2
-rw-r--r--src/http/ngx_http.h3
-rw-r--r--src/http/ngx_http_core_module.c29
-rw-r--r--src/http/ngx_http_core_module.h2
-rw-r--r--src/http/ngx_http_header_filter_module.c3
-rw-r--r--src/http/ngx_http_request.c8
-rw-r--r--src/http/ngx_http_special_response.c34
-rw-r--r--src/http/ngx_http_upstream.c45
-rw-r--r--src/http/ngx_http_upstream.h7
-rw-r--r--src/mail/ngx_mail.c5
-rw-r--r--src/os/unix/ngx_files.h4
41 files changed, 1636 insertions, 224 deletions
diff --git a/CHANGES b/CHANGES
index 4f46a77de..c6a657e4c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,26 @@
+Changes with nginx 0.7.54 01 May 2009
+
+ *) Feature: the ngx_http_image_filter_module.
+
+ *) Feature: the "proxy_ignore_headers" and "fastcgi_ignore_headers"
+ directives.
+
+ *) Bugfix: a segmentation fault might occur in worker process, if an
+ "open_file_cache_errors off" directive was used; the bug had
+ appeared in 0.7.53.
+
+ *) Bugfix: the "port_in_redirect off" directive did not work; the bug
+ had appeared in 0.7.39.
+
+ *) Bugfix: improve handling of "select" method errors.
+
+ *) Bugfix: of "select() failed (10022: ...)" error in nginx/Windows.
+
+ *) Bugfix: in error text descriptions in nginx/Windows; the bug had
+ appeared in 0.7.53.
+
+
Changes with nginx 0.7.53 27 Apr 2009
*) Change: now a log set by --error-log-path is created from the very
diff --git a/CHANGES.ru b/CHANGES.ru
index fd9ffe8b2..63a620089 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,25 @@
+Изменения в nginx 0.7.54 01.05.2009
+
+ *) Добавление: модуль ngx_http_image_filter_module.
+
+ *) Добавление: директивы proxy_ignore_headers и fastcgi_ignore_headers.
+
+ *) Исправление: при использовании переменных "open_file_cache_errors
+ on" в рабочем процессе мог произойти segmentation fault; ошибка
+ появилась в 0.7.53.
+
+ *) Исправление: директива "port_in_redirect off" не работала; ошибка
+ появилась в 0.7.39.
+
+ *) Исправление: улучшение обработки ошибок метода select.
+
+ *) Исправление: ошибки "select() failed (10022: ...)" в nginx/Windows.
+
+ *) Исправление: в текстовых сообщениях об ошибках в nginx/Windows;
+ ошибка появилась в 0.7.53.
+
+
Изменения в nginx 0.7.53 27.04.2009
*) Изменение: теперь лог, указанный в --error-log-path, создаётся с
diff --git a/auto/lib/conf b/auto/lib/conf
index 0462228ab..a4155e1ba 100644
--- a/auto/lib/conf
+++ b/auto/lib/conf
@@ -45,6 +45,10 @@ if [ $USE_LIBXSLT = YES ]; then
. auto/lib/libxslt/conf
fi
+if [ $USE_LIBGD = YES ]; then
+ . auto/lib/libgd/conf
+fi
+
if [ $USE_PERL = YES ]; then
. auto/lib/perl/conf
fi
diff --git a/auto/lib/libgd/conf b/auto/lib/libgd/conf
new file mode 100644
index 000000000..3a5277048
--- /dev/null
+++ b/auto/lib/libgd/conf
@@ -0,0 +1,81 @@
+
+# Copyright (C) Igor Sysoev
+
+
+ ngx_feature="GD library"
+ ngx_feature_name=
+ ngx_feature_run=no
+ ngx_feature_incs="#include <gd.h>"
+ ngx_feature_path=
+ ngx_feature_libs="-lgd"
+ ngx_feature_test="gdImagePtr img = gdImageCreateFromGifPtr(1, NULL);"
+ . auto/feature
+
+
+if [ $ngx_found = no ]; then
+
+ # FreeBSD port
+
+ ngx_feature="GD library in /usr/local/"
+ ngx_feature_path="/usr/local/include"
+
+ if [ $NGX_RPATH = YES ]; then
+ ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lgd"
+ else
+ ngx_feature_libs="-L/usr/local/lib -lgd"
+ fi
+
+ . auto/feature
+fi
+
+
+if [ $ngx_found = no ]; then
+
+ # NetBSD port
+
+ ngx_feature="GD library in /usr/pkg/"
+ ngx_feature_path="/usr/pkg/include/"
+
+ if [ $NGX_RPATH = YES ]; then
+ ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lgd"
+ else
+ ngx_feature_libs="-L/usr/pkg/lib -lgd"
+ fi
+
+ . auto/feature
+fi
+
+
+if [ $ngx_found = no ]; then
+
+ # MacPorts
+
+ ngx_feature="GD library in /opt/local/"
+ ngx_feature_path="/opt/local/include"
+
+ if [ $NGX_RPATH = YES ]; then
+ ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lgd"
+ else
+ ngx_feature_libs="-L/opt/local/lib -lgd"
+ fi
+
+ . auto/feature
+fi
+
+
+if [ $ngx_found = yes ]; then
+
+ CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
+
+else
+
+cat << END
+
+$0: error: the HTTP image filter module requires the GD library.
+You can either do not enable the module or install the libraries.
+
+END
+
+ exit 1
+
+fi
diff --git a/auto/modules b/auto/modules
index 5e9d4d534..9bc2e04db 100644
--- a/auto/modules
+++ b/auto/modules
@@ -104,6 +104,7 @@ fi
# ngx_http_charset_filter
# ngx_http_ssi_filter
# ngx_http_xslt_filter
+# ngx_http_image_filter_filter
# ngx_http_sub_filter
# ngx_http_addition_filter
# ngx_http_userid_filter
@@ -148,6 +149,12 @@ if [ $HTTP_XSLT = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_XSLT_SRCS"
fi
+if [ $HTTP_IMAGE_FILTER = YES ]; then
+ USE_LIBGD=YES
+ HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_IMAGE_FILTER_MODULE"
+ HTTP_SRCS="$HTTP_SRCS $HTTP_IMAGE_SRCS"
+fi
+
if [ $HTTP_SUB = YES ]; then
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SUB_FILTER_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_SUB_SRCS"
diff --git a/auto/options b/auto/options
index 987855723..742a9f825 100644
--- a/auto/options
+++ b/auto/options
@@ -60,6 +60,7 @@ HTTP_SSI=YES
HTTP_POSTPONE=NO
HTTP_REALIP=NO
HTTP_XSLT=NO
+HTTP_IMAGE_FILTER=NO
HTTP_SUB=NO
HTTP_ADDITION=NO
HTTP_DAV=NO
@@ -123,6 +124,7 @@ USE_PERL=NO
NGX_PERL=perl
USE_LIBXSLT=NO
+USE_LIBGD=NO
NGX_GOOGLE_PERFTOOLS=NO
NGX_CPP_TEST=NO
@@ -181,6 +183,7 @@ do
--with-http_realip_module) HTTP_REALIP=YES ;;
--with-http_addition_module) HTTP_ADDITION=YES ;;
--with-http_xslt_module) HTTP_XSLT=YES ;;
+ --with-http_image_filter_module) HTTP_IMAGE_FILTER=YES ;;
--with-http_sub_module) HTTP_SUB=YES ;;
--with-http_dav_module) HTTP_DAV=YES ;;
--with-http_flv_module) HTTP_FLV=YES ;;
diff --git a/auto/sources b/auto/sources
index 7ee0d44e4..319026baf 100644
--- a/auto/sources
+++ b/auto/sources
@@ -328,6 +328,10 @@ HTTP_XSLT_FILTER_MODULE=ngx_http_xslt_filter_module
HTTP_XSLT_SRCS=src/http/modules/ngx_http_xslt_filter_module.c
+HTTP_IMAGE_FILTER_MODULE=ngx_http_image_filter_module
+HTTP_IMAGE_SRCS=src/http/modules/ngx_http_image_filter_module.c
+
+
HTTP_SUB_FILTER_MODULE=ngx_http_sub_filter_module
HTTP_SUB_SRCS=src/http/modules/ngx_http_sub_filter_module.c
diff --git a/src/core/nginx.c b/src/core/nginx.c
index 82efda278..eec48bfa7 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -213,7 +213,7 @@ main(int argc, char *const *argv)
if (ngx_show_help) {
ngx_log_stderr(0,
"Usage: nginx [-?hvVt] [-s signal] [-c filename] "
- "[-g directives]" CRLF CRLF
+ "[-p prefix] [-g directives]" CRLF CRLF
"Options:" CRLF
" -?,-h : this help" CRLF
" -v : show version and exit" CRLF
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 501f7bb5f..8d308d6fa 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 7053
-#define NGINX_VERSION "0.7.53"
+#define nginx_version 7054
+#define NGINX_VERSION "0.7.54"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index ea35515a3..644243781 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -61,6 +61,7 @@ static ngx_uint_t argument_number[] = {
char *
ngx_conf_param(ngx_conf_t *cf)
{
+ char *rv;
ngx_str_t *param;
ngx_buf_t b;
ngx_conf_file_t conf_file;
@@ -82,13 +83,17 @@ ngx_conf_param(ngx_conf_t *cf)
b.temporary = 1;
conf_file.file.fd = NGX_INVALID_FILE;
- conf_file.file.name.data = (u_char *) "command line";
- conf_file.line = 1;
+ conf_file.file.name.data = NULL;
+ conf_file.line = 0;
cf->conf_file = &conf_file;
cf->conf_file->buffer = &b;
- return ngx_conf_parse(cf, NULL);
+ rv = ngx_conf_parse(cf, NULL);
+
+ cf->conf_file = NULL;
+
+ return rv;
}
@@ -853,7 +858,7 @@ ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
full.data = NULL;
#endif
- if (name && name->len) {
+ if (name->len) {
full = *name;
if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
@@ -889,14 +894,13 @@ ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
return NULL;
}
- if (name && name->len) {
+ if (name->len) {
file->fd = NGX_INVALID_FILE;
file->name = full;
} else {
file->fd = ngx_stderr;
- file->name.len = 0;
- file->name.data = NULL;
+ file->name = *name;
}
file->buffer = NULL;
@@ -961,31 +965,11 @@ ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
last = errstr + NGX_MAX_CONF_ERRSTR;
va_start(args, fmt);
- p = ngx_vsnprintf(errstr, last - errstr, fmt, args);
+ p = ngx_vslprintf(errstr, last, fmt, args);
va_end(args);
if (err) {
-
- if (p > last - 50) {
-
- /* leave a space for an error code */
-
- p = last - 50;
- *p++ = '.';
- *p++ = '.';
- *p++ = '.';
- }
-
-#if (NGX_WIN32)
- p = ngx_snprintf(p, last - p, ((unsigned) err < 0x80000000)
- ? " (%d: " : " (%Xd: ", err);
-#else
- p = ngx_snprintf(p, last - p, " (%d: ", err);
-#endif
-
- p = ngx_strerror_r(err, p, last - p);
-
- *p++ = ')';
+ p = ngx_log_errno(p, last, err);
}
if (cf->conf_file == NULL) {
@@ -993,6 +977,12 @@ ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
return;
}
+ if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
+ ngx_log_error(level, cf->log, 0, "%*s in command line",
+ p - errstr, errstr);
+ return;
+ }
+
ngx_log_error(level, cf->log, 0, "%*s in %s:%ui",
p - errstr, errstr,
cf->conf_file->file.name.data, cf->conf_file->line);
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index ed9efe754..19344ab48 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -248,6 +248,8 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
continue;
}
+ ls[i].log = *ls[i].logp;
+
if (ls[i].inherited) {
/* TODO: close on exit */
@@ -801,7 +803,14 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
{
ngx_uint_t level;
- if (err == NGX_ECONNRESET && c->log_error == NGX_ERROR_IGNORE_ECONNRESET) {
+ /* Winsock may return NGX_ECONNABORTED instead of NGX_ECONNRESET */
+
+ if ((err == NGX_ECONNRESET
+#if (NGX_WIN32)
+ || err == NGX_ECONNABORTED
+#endif
+ ) && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
+ {
return 0;
}
@@ -813,7 +822,9 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
if (err == 0
|| err == NGX_ECONNRESET
-#if !(NGX_WIN32)
+#if (NGX_WIN32)
+ || err == NGX_ECONNABORTED
+#else
|| err == NGX_EPIPE
#endif
|| err == NGX_ENOTCONN
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index cc6a92989..de0ef41be 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -34,6 +34,7 @@ struct ngx_listening_s {
void *servers; /* array of ngx_http_in_addr_t, for example */
ngx_log_t log;
+ ngx_log_t *logp;
size_t pool_size;
/* should be here because of the AcceptEx() preread */
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 10d07714b..251892b74 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -82,6 +82,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
cycle->pool = pool;
cycle->log = log;
+ cycle->new_log.log_level = NGX_LOG_ERR;
cycle->old_cycle = old_cycle;
cycle->conf_prefix.len = old_cycle->conf_prefix.len;
@@ -165,14 +166,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
return NULL;
}
-
- cycle->new_log = ngx_log_create_errlog(cycle, &error_log);
- if (cycle->new_log == NULL) {
- ngx_destroy_pool(pool);
- return NULL;
- }
-
-
n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
@@ -336,6 +329,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
+ if (cycle->new_log.file == NULL) {
+ cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);
+ if (cycle->new_log.file == NULL) {
+ goto failed;
+ }
+ }
+
/* open the new files */
part = &cycle->open_files.part;
@@ -382,12 +382,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
#endif
}
- cycle->log = cycle->new_log;
- pool->log = cycle->new_log;
-
- if (cycle->log->log_level == 0) {
- cycle->log->log_level = NGX_LOG_ERR;
- }
+ cycle->log = &cycle->new_log;
+ pool->log = &cycle->new_log;
/* create shared memory */
@@ -1126,7 +1122,9 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) {
ngx_file_info_t fi;
- if (ngx_file_info((const char *) file[i].name.data, &fi) == -1) {
+ if (ngx_file_info((const char *) file[i].name.data, &fi)
+ == NGX_FILE_ERROR)
+ {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
ngx_file_info_n " \"%s\" failed",
file[i].name.data);
diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h
index b4007d4dc..e3905885d 100644
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -38,7 +38,7 @@ struct ngx_cycle_s {
ngx_pool_t *pool;
ngx_log_t *log;
- ngx_log_t *new_log;
+ ngx_log_t new_log;
ngx_connection_t **files;
ngx_connection_t *free_connections;
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 6bff833d6..450da5623 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -489,7 +489,9 @@ ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user)
{
ngx_file_info_t fi;
- if (ngx_file_info((const char *) path[i]->name.data, &fi) == -1) {
+ if (ngx_file_info((const char *) path[i]->name.data, &fi)
+ == NGX_FILE_ERROR)
+ {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
ngx_file_info_n " \"%s\" failed", path[i]->name.data);
return NGX_ERROR;
diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c
index 89df2d769..770a59084 100644
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -8,14 +8,14 @@
#include <ngx_core.h>
-static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_errlog_commands[] = {
{ngx_string("error_log"),
NGX_MAIN_CONF|NGX_CONF_1MORE,
- ngx_set_error_log,
+ ngx_error_log,
0,
0,
NULL},
@@ -53,7 +53,7 @@ ngx_uint_t ngx_use_stderr = 1;
static ngx_str_t err_levels[] = {
- ngx_string("stderr"),
+ ngx_null_string,
ngx_string("emerg"),
ngx_string("alert"),
ngx_string("crit"),
@@ -101,14 +101,14 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
p = errstr + ngx_cached_err_log_time.len;
- p = ngx_snprintf(p, last - p, " [%V] ", &err_levels[level]);
+ p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);
/* pid#tid */
- p = ngx_snprintf(p, last - p, "%P#" NGX_TID_T_FMT ": ",
+ p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
ngx_log_pid, ngx_log_tid);
if (log->connection) {
- p = ngx_snprintf(p, last - p, "*%uA ", log->connection);
+ p = ngx_slprintf(p, last, "*%uA ", log->connection);
}
msg = p;
@@ -116,39 +116,17 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
#if (NGX_HAVE_VARIADIC_MACROS)
va_start(args, fmt);
- p = ngx_vsnprintf(p, last - p, fmt, args);
+ p = ngx_vslprintf(p, last, fmt, args);
va_end(args);
#else
- p = ngx_vsnprintf(p, last - p, fmt, args);
+ p = ngx_vslprintf(p, last, fmt, args);
#endif
if (err) {
-
- if (p > last - 50) {
-
- /* leave a space for an error code */
-
- p = last - 50;
- *p++ = '.';
- *p++ = '.';
- *p++ = '.';
- }
-
-#if (NGX_WIN32)
- p = ngx_snprintf(p, last - p, ((unsigned) err < 0x80000000)
- ? " (%d: " : " (%Xd: ", err);
-#else
- p = ngx_snprintf(p, last - p, " (%d: ", err);
-#endif
-
- p = ngx_strerror_r(err, p, last - p);
-
- if (p < last) {
- *p++ = ')';
- }
+ p = ngx_log_errno(p, last, err);
}
if (level != NGX_LOG_DEBUG && log->handler) {
@@ -174,7 +152,7 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
(void) ngx_sprintf(msg, "[%V]: ", &err_levels[level]);
- (void) ngx_write_fd(ngx_stderr, msg, p - msg);
+ (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
@@ -230,45 +208,53 @@ ngx_log_stderr(ngx_err_t err, const char *fmt, ...)
va_list args;
u_char errstr[NGX_MAX_ERROR_STR];
+ last = errstr + NGX_MAX_ERROR_STR;
+
va_start(args, fmt);
- p = ngx_vsnprintf(errstr, NGX_MAX_ERROR_STR, fmt, args);
+ p = ngx_vslprintf(errstr, last, fmt, args);
va_end(args);
- if (p > errstr + NGX_MAX_ERROR_STR - NGX_LINEFEED_SIZE) {
- p = errstr + NGX_MAX_ERROR_STR - NGX_LINEFEED_SIZE;
+ if (err) {
+ p = ngx_log_errno(p, last, err);
}
- if (err) {
+ if (p > last - NGX_LINEFEED_SIZE) {
+ p = last - NGX_LINEFEED_SIZE;
+ }
- last = errstr + NGX_MAX_ERROR_STR;
+ ngx_linefeed(p);
- if (p > last - 50) {
+ (void) ngx_write_console(ngx_stderr, errstr, p - errstr);
+}
- /* leave a space for an error code */
- p = last - 50;
- *p++ = '.';
- *p++ = '.';
- *p++ = '.';
- }
+u_char *
+ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err)
+{
+ if (buf > last - 50) {
+
+ /* leave a space for an error code */
+
+ buf = last - 50;
+ *buf++ = '.';
+ *buf++ = '.';
+ *buf++ = '.';
+ }
#if (NGX_WIN32)
- p = ngx_snprintf(p, last - p, ((unsigned) err < 0x80000000)
- ? " (%d: " : " (%Xd: ", err);
+ buf = ngx_slprintf(buf, last, ((unsigned) err < 0x80000000)
+ ? " (%d: " : " (%Xd: ", err);
#else
- p = ngx_snprintf(p, last - p, " (%d: ", err);
+ buf = ngx_slprintf(buf, last, " (%d: ", err);
#endif
- p = ngx_strerror_r(err, p, last - p);
+ buf = ngx_strerror_r(err, buf, last - buf);
- if (p < last) {
- *p++ = ')';
- }
+ if (buf < last) {
+ *buf++ = ')';
}
- ngx_linefeed(p);
-
- (void) ngx_write_fd(ngx_stderr, errstr, p - errstr);
+ return buf;
}
@@ -302,15 +288,16 @@ ngx_log_init(u_char *prefix)
#else
if (name[0] != '/') {
#endif
- plen = 0;
if (prefix) {
plen = ngx_strlen(prefix);
-#ifdef NGX_PREFIX
} else {
+#ifdef NGX_PREFIX
prefix = (u_char *) NGX_PREFIX;
plen = ngx_strlen(prefix);
+#else
+ plen = 0;
#endif
}
@@ -358,7 +345,7 @@ ngx_log_init(u_char *prefix)
ngx_log_t *
-ngx_log_create_errlog(ngx_cycle_t *cycle, ngx_str_t *name)
+ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name)
{
ngx_log_t *log;
@@ -377,7 +364,7 @@ ngx_log_create_errlog(ngx_cycle_t *cycle, ngx_str_t *name)
char *
-ngx_set_error_log_levels(ngx_conf_t *cf, ngx_log_t *log)
+ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log)
{
ngx_uint_t i, n, d;
ngx_str_t *value;
@@ -422,10 +409,7 @@ ngx_set_error_log_levels(ngx_conf_t *cf, ngx_log_t *log)
}
}
- if (log->log_level == 0) {
- log->log_level = NGX_LOG_ERR;
-
- } else if (log->log_level == NGX_LOG_DEBUG) {
+ if (log->log_level == NGX_LOG_DEBUG) {
log->log_level = NGX_LOG_DEBUG_ALL;
}
@@ -434,26 +418,35 @@ ngx_set_error_log_levels(ngx_conf_t *cf, ngx_log_t *log)
static char *
-ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_str_t *value;
+ ngx_str_t *value, name;
+
+ if (cf->cycle->new_log.file) {
+ return "is duplicate";
+ }
value = cf->args->elts;
- if (value[1].len == 6 && ngx_strcmp(value[1].data, "stderr") == 0) {
- cf->cycle->new_log->file->fd = ngx_stderr;
- cf->cycle->new_log->file->name.len = 0;
- cf->cycle->new_log->file->name.data = NULL;
+ if (ngx_strcmp(value[1].data, "stderr") == 0) {
+ name.len = 0;
+ name.data = NULL;
} else {
- cf->cycle->new_log->file->name = value[1];
+ name = value[1];
+ }
- if (ngx_conf_full_name(cf->cycle, &cf->cycle->new_log->file->name, 0)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
+ cf->cycle->new_log.file = ngx_conf_open_file(cf->cycle, &name);
+ if (cf->cycle->new_log.file == NULL) {
+ return NULL;
}
- return ngx_set_error_log_levels(cf, cf->cycle->new_log);
+ if (cf->args->nelts == 2) {
+ cf->cycle->new_log.log_level = NGX_LOG_ERR;
+ return NGX_CONF_OK;
+ }
+
+ cf->cycle->new_log.log_level = 0;
+
+ return ngx_log_set_levels(cf, &cf->cycle->new_log);
}
diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h
index 078578318..b736aa2eb 100644
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -196,10 +196,11 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
/*********************************/
ngx_log_t *ngx_log_init(u_char *prefix);
-ngx_log_t *ngx_log_create_errlog(ngx_cycle_t *cycle, ngx_str_t *name);
-char *ngx_set_error_log_levels(ngx_conf_t *cf, ngx_log_t *log);
+ngx_log_t *ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name);
+char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
void ngx_cdecl ngx_log_abort(ngx_err_t err, const char *fmt, ...);
void ngx_cdecl ngx_log_stderr(ngx_err_t err, const char *fmt, ...);
+u_char *ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err);
extern ngx_module_t ngx_errlog_module;
diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c
index 6deb0ce0b..173980fa8 100644
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -143,7 +143,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
if (of->test_only) {
- if (ngx_file_info(name->data, &fi) == -1) {
+ if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) {
of->err = ngx_errno;
of->failed = ngx_file_info_n;
return NGX_ERROR;
@@ -234,6 +234,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
} else {
of->err = file->err;
+ of->failed = ngx_open_file_n;
}
goto found;
@@ -463,7 +464,7 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
if (of->fd != NGX_INVALID_FILE) {
- if (ngx_file_info(name, &fi) == -1) {
+ if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) {
of->failed = ngx_file_info_n;
goto failed;
}
@@ -474,7 +475,7 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
} else if (of->test_dir) {
- if (ngx_file_info(name, &fi) == -1) {
+ if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) {
of->failed = ngx_file_info_n;
goto failed;
}
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index f58fb5ba7..2b53ee07e 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -131,14 +131,14 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr)
r->event->handler = ngx_resolver_resend_handler;
r->event->data = r;
- r->event->log = cf->cycle->new_log;
+ r->event->log = &cf->cycle->new_log;
r->ident = -1;
r->resend_timeout = 5;
r->expire = 30;
r->valid = 300;
- r->log = cf->cycle->new_log;
+ r->log = &cf->cycle->new_log;
r->log_level = NGX_LOG_ALERT;
if (addr) {
@@ -152,7 +152,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr)
uc->sockaddr = addr->sockaddr;
uc->socklen = addr->socklen;
uc->server = addr->name;
- uc->log = cf->cycle->new_log;
+ uc->log = &cf->cycle->new_log;
}
return r;
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 9b63891a8..d73cb8699 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -99,7 +99,7 @@ ngx_sprintf(u_char *buf, const char *fmt, ...)
va_list args;
va_start(args, fmt);
- p = ngx_vsnprintf(buf, /* STUB */ 65536, fmt, args);
+ p = ngx_vslprintf(buf, (void *) -1, fmt, args);
va_end(args);
return p;
@@ -113,7 +113,21 @@ ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...)
va_list args;
va_start(args, fmt);
- p = ngx_vsnprintf(buf, max, fmt, args);
+ p = ngx_vslprintf(buf, buf + max, fmt, args);
+ va_end(args);
+
+ return p;
+}
+
+
+u_char * ngx_cdecl
+ngx_slprintf(u_char *buf, u_char *last, const char *fmt, ...)
+{
+ u_char *p;
+ va_list args;
+
+ va_start(args, fmt);
+ p = ngx_vslprintf(buf, last, fmt, args);
va_end(args);
return p;
@@ -121,9 +135,9 @@ ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...)
u_char *
-ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
+ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
{
- u_char *p, zero, *last;
+ u_char *p, zero;
int d;
float f, scale;
size_t len, slen;
@@ -134,12 +148,6 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
ngx_str_t *v;
ngx_variable_value_t *vv;
- if (max == 0) {
- return buf;
- }
-
- last = buf + max;
-
while (*fmt && buf < last) {
/*
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index 0560bd8be..81e1ea169 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -140,7 +140,11 @@ u_char *ngx_cpystrn(u_char *dst, u_char *src, size_t n);
u_char *ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src);
u_char * ngx_cdecl ngx_sprintf(u_char *buf, const char *fmt, ...);
u_char * ngx_cdecl ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...);
-u_char *ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args);
+u_char * ngx_cdecl ngx_slprintf(u_char *buf, u_char *last, const char *fmt,
+ ...);
+u_char *ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args);
+#define ngx_vsnprintf(buf, max, fmt, args) \
+ ngx_vslprintf(buf, buf + (max), fmt, args)
ngx_int_t ngx_strcasecmp(u_char *s1, u_char *s2);
ngx_int_t ngx_strncasecmp(u_char *s1, u_char *s2, size_t n);
diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c
index a50088ba4..9be2c6ff3 100644
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -18,6 +18,7 @@ static ngx_int_t ngx_select_del_event(ngx_event_t *ev, ngx_int_t event,
ngx_uint_t flags);
static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags);
+static void ngx_select_repair_fd_sets(ngx_cycle_t *cycle);
static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
@@ -248,12 +249,12 @@ static ngx_int_t
ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags)
{
- int ready, nready;
- ngx_uint_t i, found;
- ngx_err_t err;
- ngx_event_t *ev, **queue;
- ngx_connection_t *c;
- struct timeval tv, *tp;
+ int ready, nready;
+ ngx_err_t err;
+ ngx_uint_t i, found;
+ ngx_event_t *ev, **queue;
+ struct timeval tv, *tp;
+ ngx_connection_t *c;
#if !(NGX_WIN32)
@@ -302,19 +303,23 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
work_read_fd_set = master_read_fd_set;
work_write_fd_set = master_write_fd_set;
-#if 1
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- /*
- * (void *) disables "dereferencing type-punned
- * pointer will break strict-aliasing rules
- */
- "select read fd_set: %08Xd",
- *(int *) (void *) &work_read_fd_set);
-#endif
-
#if (NGX_WIN32)
- ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
+ if (max_read || max_write) {
+ ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
+
+ } else {
+
+ /*
+ * Winsock select() requires that at least one descriptor set must be
+ * be non-null, and any non-null descriptor set must contain at least
+ * one handle to a socket. Otherwise select() returns WSAEINVAL.
+ */
+
+ ngx_msleep(timer);
+
+ ready = 0;
+ }
#else
@@ -339,6 +344,11 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
if (err) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
+
+ if (err == WSAENOTSOCK) {
+ ngx_select_repair_fd_sets(cycle);
+ }
+
return NGX_ERROR;
}
@@ -361,6 +371,11 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
}
ngx_log_error(level, cycle->log, err, "select() failed");
+
+ if (err == EBADF) {
+ ngx_select_repair_fd_sets(cycle);
+ }
+
return NGX_ERROR;
}
@@ -414,13 +429,101 @@ ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_mutex_unlock(ngx_posted_events_mutex);
if (ready != nready) {
- ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events");
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+ "select ready != events: %d:%d", ready, nready);
+
+ ngx_select_repair_fd_sets(cycle);
}
return NGX_OK;
}
+static void
+ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
+{
+ int n;
+ socklen_t len;
+ ngx_err_t err;
+ ngx_socket_t s;
+
+#if (NGX_WIN32)
+ u_int i;
+
+ for (i = 0; i < master_read_fd_set.fd_count; i++) {
+
+ s = master_read_fd_set.fd_array[i];
+ len = sizeof(int);
+
+ if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
+ err = ngx_socket_errno;
+
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
+ "invalid descriptor #%d in read fd_set", s);
+
+ FD_CLR(s, &master_read_fd_set);
+ }
+ }
+
+ for (i = 0; i < master_write_fd_set.fd_count; i++) {
+
+ s = master_write_fd_set.fd_array[i];
+ len = sizeof(int);
+
+ if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
+ err = ngx_socket_errno;
+
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
+ "invalid descriptor #%d in write fd_set", s);
+
+ FD_CLR(s, &master_write_fd_set);
+ }
+ }
+
+#else
+
+ for (s = 0; s <= max_fd; s++) {
+
+ if (FD_ISSET(s, &master_read_fd_set) == 0) {
+ continue;
+ }
+
+ len = sizeof(int);
+
+ if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
+ err = ngx_socket_errno;
+
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
+ "invalid descriptor #%d in read fd_set", s);
+
+ FD_CLR(s, &master_read_fd_set);
+ }
+ }
+
+ for (s = 0; s <= max_fd; s++) {
+
+ if (FD_ISSET(s, &master_write_fd_set) == 0) {
+ continue;
+ }
+
+ len = sizeof(int);
+
+ if (getsockopt(s, SOL_SOCKET, SO_TYPE, &n, &len) == -1) {
+ err = ngx_socket_errno;
+
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
+ "invalid descriptor #%d in write fd_set", s);
+
+ FD_CLR(s, &master_write_fd_set);
+ }
+ }
+
+ max_fd = -1;
+
+#endif
+}
+
+
static char *
ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
{
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 8d18ef648..e30c5636a 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -776,6 +776,10 @@ ngx_event_process_init(ngx_cycle_t *cycle)
rev->handler = ngx_event_acceptex;
+ if (ngx_use_accept_mutex) {
+ continue;
+ }
+
if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
return NGX_ERROR;
}
@@ -792,6 +796,10 @@ ngx_event_process_init(ngx_cycle_t *cycle)
} else {
rev->handler = ngx_event_accept;
+ if (ngx_use_accept_mutex) {
+ continue;
+ }
+
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
return NGX_ERROR;
}
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 1935d4ca9..23a4fbec4 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1306,7 +1306,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
last = errstr + NGX_MAX_CONF_ERRSTR;
va_start(args, fmt);
- p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args);
+ p = ngx_vslprintf(errstr, last - 1, fmt, args);
va_end(args);
p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index f506dde69..84a7672a4 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -221,7 +221,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
temp = &r->request_body->temp_file->file.name;
- if (ngx_file_info(path.data, &fi) == -1) {
+ if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
status = NGX_HTTP_CREATED;
} else {
@@ -326,7 +326,7 @@ ok:
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http delete filename: \"%s\"", path.data);
- if (ngx_file_info(path.data, &fi) == -1) {
+ if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
err = ngx_errno;
rc = (err == NGX_ENOTDIR) ? NGX_HTTP_CONFLICT : NGX_HTTP_NOT_FOUND;
@@ -678,7 +678,7 @@ overwrite_done:
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http copy to: \"%s\"", copy.path.data);
- if (ngx_file_info(copy.path.data, &fi) == -1) {
+ if (ngx_file_info(copy.path.data, &fi) == NGX_FILE_ERROR) {
err = ngx_errno;
if (err != NGX_ENOENT) {
@@ -712,7 +712,7 @@ overwrite_done:
dir = ngx_is_dir(&fi);
}
- if (ngx_file_info(path.data, &fi) == -1) {
+ if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
return ngx_http_dav_error(r->connection->log, ngx_errno,
NGX_HTTP_NOT_FOUND, ngx_file_info_n,
path.data);
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index a065616b9..066d604d1 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -183,6 +183,15 @@ static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = {
};
+static ngx_conf_bitmask_t ngx_http_fastcgi_ignore_headers_masks[] = {
+ { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
+ { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
+ { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
+ { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
+ { ngx_null_string, 0 }
+};
+
+
ngx_module_t ngx_http_fastcgi_module;
@@ -409,6 +418,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
NULL },
+ { ngx_string("fastcgi_ignore_headers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers),
+ &ngx_http_fastcgi_ignore_headers_masks },
+
{ ngx_string("fastcgi_catch_stderr"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_str_array_slot,
@@ -1817,6 +1833,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
* set by ngx_pcalloc():
*
* conf->upstream.bufs.num = 0;
+ * conf->upstream.ignore_headers = 0;
* conf->upstream.next_upstream = 0;
* conf->upstream.use_stale_cache = 0;
* conf->upstream.temp_path = NULL;
@@ -2012,6 +2029,11 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
+ ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
+ prev->upstream.ignore_headers,
+ NGX_CONF_BITMASK_SET);
+
+
ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
prev->upstream.next_upstream,
(NGX_CONF_BITMASK_SET
diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c
new file mode 100644
index 000000000..a5af1ac2e
--- /dev/null
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -0,0 +1,1026 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+#include "gd.h"
+
+
+#define NGX_HTTP_IMAGE_OFF 0
+#define NGX_HTTP_IMAGE_TEST 1
+#define NGX_HTTP_IMAGE_SIZE 2
+#define NGX_HTTP_IMAGE_RESIZE 3
+#define NGX_HTTP_IMAGE_CROP 4
+
+
+#define NGX_HTTP_IMAGE_START 0
+#define NGX_HTTP_IMAGE_READ 1
+#define NGX_HTTP_IMAGE_PROCESS 2
+#define NGX_HTTP_IMAGE_DONE 3
+
+
+#define NGX_HTTP_IMAGE_NONE 0
+#define NGX_HTTP_IMAGE_JPEG 1
+#define NGX_HTTP_IMAGE_GIF 2
+#define NGX_HTTP_IMAGE_PNG 3
+
+
+#define NGX_HTTP_IMAGE_BUFFERED 0x08
+
+
+typedef struct {
+ ngx_uint_t filter;
+ ngx_uint_t width;
+ ngx_uint_t height;
+
+ size_t buffer_size;
+} ngx_http_image_filter_conf_t;
+
+
+typedef struct {
+ u_char *image;
+ u_char *last;
+
+ size_t length;
+
+ ngx_uint_t width;
+ ngx_uint_t height;
+
+ ngx_uint_t phase;
+ ngx_uint_t type;
+} ngx_http_image_filter_ctx_t;
+
+
+static ngx_uint_t ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in);
+static ngx_int_t ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in);
+static ngx_buf_t *ngx_http_image_process(ngx_http_request_t *r);
+static ngx_buf_t *ngx_http_image_json(ngx_http_request_t *r,
+ ngx_http_image_filter_ctx_t *ctx);
+static ngx_buf_t *ngx_http_image_asis(ngx_http_request_t *r,
+ ngx_http_image_filter_ctx_t *ctx);
+static void ngx_http_image_length(ngx_http_request_t *r, ngx_buf_t *b);
+static ngx_int_t ngx_http_image_size(ngx_http_request_t *r,
+ ngx_http_image_filter_ctx_t *ctx);
+
+static ngx_buf_t *ngx_http_image_resize(ngx_http_request_t *r,
+ ngx_http_image_filter_ctx_t *ctx);
+static gdImagePtr ngx_http_image_source(ngx_http_request_t *r,
+ ngx_http_image_filter_ctx_t *ctx);
+static gdImagePtr ngx_http_image_new(ngx_http_request_t *r, int w, int h,
+ int colors);
+static u_char *ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type,
+ gdImagePtr img, int *size);
+static void ngx_http_image_cleanup(void *data);
+
+
+static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf);
+static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent,
+ void *child);
+static char *ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf);
+
+
+static ngx_command_t ngx_http_image_filter_commands[] = {
+
+ { ngx_string("image_filter"),
+ NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13,
+ ngx_http_image_filter,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("image_filter_buffer"),
+ 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_image_filter_conf_t, buffer_size),
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_http_module_t ngx_http_image_filter_module_ctx = {
+ NULL, /* preconfiguration */
+ ngx_http_image_filter_init, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_http_image_filter_create_conf, /* create location configuration */
+ ngx_http_image_filter_merge_conf /* merge location configuration */
+};
+
+
+ngx_module_t ngx_http_image_filter_module = {
+ NGX_MODULE_V1,
+ &ngx_http_image_filter_module_ctx, /* module context */
+ ngx_http_image_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_str_t ngx_http_image_types[] = {
+ ngx_string("image/jpeg"),
+ ngx_string("image/gif"),
+ ngx_string("image/png")
+};
+
+
+static ngx_int_t
+ngx_http_image_header_filter(ngx_http_request_t *r)
+{
+ off_t len;
+ ngx_http_image_filter_ctx_t *ctx;
+ ngx_http_image_filter_conf_t *conf;
+
+ if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
+
+ if (conf->filter == NGX_HTTP_IMAGE_OFF) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ if (r->headers_out.content_type.len
+ >= sizeof("multipart/x-mixed-replace") - 1
+ && ngx_strncasecmp(r->headers_out.content_type.data,
+ (u_char *) "multipart/x-mixed-replace",
+ sizeof("multipart/x-mixed-replace") - 1)
+ == 0)
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "image filter: multipart/x-mixed-replace response");
+
+ return NGX_ERROR;
+ }
+
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_image_filter_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_image_filter_module);
+
+ len = r->headers_out.content_length_n;
+
+ if (len != -1 && len > conf->buffer_size) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "image filter: too big response: %O", len);
+
+ return NGX_ERROR;
+ }
+
+ if (len == -1) {
+ ctx->length = conf->buffer_size;
+
+ } else {
+ ctx->length = (size_t) len;
+ }
+
+ if (r->headers_out.refresh) {
+ r->headers_out.refresh->hash = 0;
+ }
+
+ r->main_filter_need_in_memory = 1;
+ r->allow_ranges = 0;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ ngx_int_t rc;
+ ngx_str_t *ct;
+ ngx_chain_t out;
+ ngx_http_image_filter_ctx_t *ctx;
+ ngx_http_image_filter_conf_t *conf;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image filter");
+
+ if (in == NULL) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module);
+
+ if (ctx == NULL) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ switch (ctx->phase) {
+
+ case NGX_HTTP_IMAGE_START:
+
+ ctx->type = ngx_http_image_test(r, in);
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
+
+ if (ctx->type == NGX_HTTP_IMAGE_NONE) {
+
+ if (conf->filter == NGX_HTTP_IMAGE_SIZE) {
+ out.buf = ngx_http_image_json(r, NULL);
+
+ if (out.buf) {
+ out.next = NULL;
+ in = &out;
+
+ break;
+ }
+ }
+
+ return ngx_http_filter_finalize_request(r,
+ NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
+ }
+
+ /* override content type */
+
+ ct = &ngx_http_image_types[ctx->type - 1];
+ r->headers_out.content_type_len = ct->len;
+ r->headers_out.content_type = *ct;
+
+ if (conf->filter == NGX_HTTP_IMAGE_TEST) {
+ break;
+ }
+
+ ctx->phase = NGX_HTTP_IMAGE_READ;
+
+ /* fall through */
+
+ case NGX_HTTP_IMAGE_READ:
+
+ rc = ngx_http_image_read(r, in);
+
+ if (rc == NGX_AGAIN) {
+ return NGX_OK;
+ }
+
+ if (rc == NGX_ERROR) {
+ return ngx_http_filter_finalize_request(r,
+ NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
+ }
+
+ /* fall through */
+
+ case NGX_HTTP_IMAGE_PROCESS:
+
+ out.buf = ngx_http_image_process(r);
+
+ if (out.buf == NULL) {
+ return ngx_http_filter_finalize_request(r,
+ NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
+ }
+
+ out.next = NULL;
+ in = &out;
+
+ break;
+
+ default: /* NGX_HTTP_IMAGE_DONE */
+
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ ctx->phase = NGX_HTTP_IMAGE_DONE;
+
+ rc = ngx_http_next_header_filter(r);
+
+ if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+ return rc;
+ }
+
+ return ngx_http_next_body_filter(r, in);
+}
+
+
+static ngx_uint_t
+ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ u_char *p;
+
+ p = in->buf->pos;
+
+ if (in->buf->last - p < 16) {
+ return NGX_HTTP_IMAGE_NONE;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "image filter: \"%c%c\"", p[0], p[1]);
+
+ if (p[0] == 0xff && p[1] == 0xd8) {
+
+ /* JPEG */
+
+ return NGX_HTTP_IMAGE_JPEG;
+
+ } else if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F' && p[3] == '8'
+ && p[4] == '9' && p[5] == 'a')
+ {
+ /* GIF */
+
+ return NGX_HTTP_IMAGE_GIF;
+
+ } else if (p[0] == 0x89 && p[1] == 'P' && p[2] == 'N' && p[3] == 'G'
+ && p[4] == 0x0d && p[5] == 0x0a && p[6] == 0x1a && p[7] == 0x0a)
+ {
+ /* PNG */
+
+ return NGX_HTTP_IMAGE_PNG;
+ }
+
+ return NGX_HTTP_IMAGE_NONE;
+}
+
+
+static ngx_int_t
+ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ u_char *p;
+ size_t size, rest;
+ ngx_buf_t *b;
+ ngx_chain_t *cl;
+ ngx_http_image_filter_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module);
+
+ if (ctx->image == NULL) {
+ ctx->image = ngx_palloc(r->pool, ctx->length);
+ if (ctx->image == NULL) {
+ return NGX_ERROR;
+ }
+
+ ctx->last = ctx->image;
+ }
+
+ p = ctx->last;
+
+ for (cl = in; cl; cl = cl->next) {
+
+ b = cl->buf;
+ size = b->last - b->pos;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "image buf: %uz", size);
+
+ rest = ctx->image + ctx->length - p;
+ size = (rest < size) ? rest : size;
+
+ p = ngx_cpymem(p, b->pos, size);
+ b->pos += size;
+
+ if (b->last_buf) {
+ ctx->last = p;
+ return NGX_OK;
+ }
+ }
+
+ ctx->last = p;
+ r->connection->buffered |= NGX_HTTP_IMAGE_BUFFERED;
+
+ return NGX_AGAIN;
+}
+
+
+static ngx_buf_t *
+ngx_http_image_process(ngx_http_request_t *r)
+{
+ ngx_buf_t *b;
+ ngx_int_t rc;
+ ngx_http_image_filter_ctx_t *ctx;
+ ngx_http_image_filter_conf_t *conf;
+
+ r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module);
+
+ rc = ngx_http_image_size(r, ctx);
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
+
+ if (conf->filter == NGX_HTTP_IMAGE_SIZE) {
+
+ b = ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL);
+
+ } else if (rc == NGX_OK
+ && ctx->width <= conf->width
+ && ctx->height <= conf->height)
+ {
+ b = ngx_http_image_asis(r, ctx);
+
+ } else {
+ b = ngx_http_image_resize(r, ctx);
+ }
+
+ return b;
+}
+
+
+static ngx_buf_t *
+ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
+{
+ size_t len;
+ ngx_buf_t *b;
+
+ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
+ if (b == NULL) {
+ return NULL;
+ }
+
+ b->memory = 1;
+ b->last_buf = 1;
+
+ ngx_http_clean_header(r);
+
+ r->headers_out.status = NGX_HTTP_OK;
+ r->headers_out.content_type.len = sizeof("text/plain") - 1;
+ r->headers_out.content_type.data = (u_char *) "text/plain";
+
+ if (ctx == NULL) {
+ b->pos = (u_char *) "{}" CRLF;
+ b->last = b->pos + sizeof("{}" CRLF) - 1;
+
+ ngx_http_image_length(r, b);
+
+ return b;
+ }
+
+ len = sizeof("{ \"img\" : "
+ "{ \"width\": , \"height\": , \"type\": \"jpeg\" } }" CRLF) - 1
+ + 2 * NGX_SIZE_T_LEN;
+
+ b->pos = ngx_pnalloc(r->pool, len);
+ if (b->pos == NULL) {
+ return NULL;
+ }
+
+ b->last = ngx_sprintf(b->pos,
+ "{ \"img\" : "
+ "{ \"width\": %uz,"
+ " \"height\": %uz,"
+ " \"type\": \"%s\" } }" CRLF,
+ ctx->width, ctx->height,
+ ngx_http_image_types[ctx->type - 1].data + 6);
+
+ ngx_http_image_length(r, b);
+
+ return b;
+}
+
+
+static ngx_buf_t *
+ngx_http_image_asis(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
+{
+ ngx_buf_t *b;
+
+ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
+ if (b == NULL) {
+ return NULL;
+ }
+
+ b->pos = ctx->image;
+ b->last = ctx->last;
+ b->memory = 1;
+ b->last_buf = 1;
+
+ ngx_http_image_length(r, b);
+
+ return b;
+}
+
+
+static void
+ngx_http_image_length(ngx_http_request_t *r, ngx_buf_t *b)
+{
+ r->headers_out.content_length_n = b->last - b->pos;
+
+ if (r->headers_out.content_length) {
+ r->headers_out.content_length->hash = 0;
+ }
+
+ r->headers_out.content_length = NULL;
+}
+
+
+static ngx_int_t
+ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
+{
+ u_char *p, *last;
+ ngx_uint_t width, height;
+
+ p = ctx->image;
+
+ switch (ctx->type) {
+
+ case NGX_HTTP_IMAGE_JPEG:
+
+ p += 2;
+ last = ctx->image + ctx->length - 10;
+
+ while (p < last) {
+
+ if (p[0] == 0xff && p[1] != 0xff) {
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "JPEG: %02xd %02xd", *p, *(p + 1));
+
+ p++;
+
+ if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
+ || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+ {
+ goto found;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "JPEG: %02xd %02xd", p[1], p[2]);
+
+ p += p[1] * 256 + p[2];
+
+ continue;
+ }
+
+ p++;
+ }
+
+ return NGX_DECLINED;
+
+ found:
+
+ width = p[6] * 256 + p[7];
+ height = p[4] * 256 + p[5];
+
+ break;
+
+ case NGX_HTTP_IMAGE_GIF:
+
+ if (ctx->length < 10) {
+ return NGX_DECLINED;
+ }
+
+ width = p[7] * 256 + p[6];
+ height = p[9] * 256 + p[8];
+
+ break;
+
+ case NGX_HTTP_IMAGE_PNG:
+
+ if (ctx->length < 24) {
+ return NGX_DECLINED;
+ }
+
+ width = p[18] * 256 + p[19];
+ height = p[22] * 256 + p[23];
+
+ break;
+
+ default:
+
+ return NGX_DECLINED;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "image size: %d x %d", width, height);
+
+ ctx->width = width;
+ ctx->height = height;
+
+ return NGX_OK;
+}
+
+
+static ngx_buf_t *
+ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
+{
+ int sx, sy, dx, dy, ox, oy,
+ colors, transparent, size;
+ u_char *out;
+ ngx_buf_t *b;
+ ngx_uint_t resize;
+ gdImagePtr src, dst;
+ ngx_pool_cleanup_t *cln;
+ ngx_http_image_filter_conf_t *conf;
+
+ src = ngx_http_image_source(r, ctx);
+
+ if (src == NULL) {
+ return NULL;
+ }
+
+ sx = gdImageSX(src);
+ sy = gdImageSY(src);
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
+
+ if ((ngx_uint_t) sx <= conf->width && (ngx_uint_t) sy <= conf->height) {
+ gdImageDestroy(src);
+ return ngx_http_image_asis(r, ctx);
+ }
+
+ colors = gdImageColorsTotal(src);
+ transparent = gdImageGetTransparent(src);
+
+ dx = sx;
+ dy = sy;
+
+ if (conf->filter == NGX_HTTP_IMAGE_RESIZE) {
+
+ if ((ngx_uint_t) dx > conf->width) {
+ dy = dy * conf->width / dx;
+ dy = dy ? dy : 1;
+ dx = conf->width;
+ }
+
+ if ((ngx_uint_t) dy > conf->height) {
+ dx = dx * conf->height / dy;
+ dx = dx ? dx : 1;
+ dy = conf->height;
+ }
+
+ resize = 1;
+
+ } else { /* NGX_HTTP_IMAGE_CROP */
+
+ resize = 0;
+
+ if ((ngx_uint_t) (dx * 100 / dy) < conf->width * 100 / conf->height) {
+
+ if ((ngx_uint_t) dx > conf->width) {
+ dy = dy * conf->width / dx;
+ dy = dy ? dy : 1;
+ dx = conf->width;
+ resize = 1;
+ }
+
+ } else {
+ if ((ngx_uint_t) dy > conf->height) {
+ dx = dx * conf->height / dy;
+ dx = dx ? dx : 1;
+ dy = conf->height;
+ resize = 1;
+ }
+ }
+ }
+
+ if (resize) {
+ dst = ngx_http_image_new(r, dx, dy, colors);
+ if (dst == NULL) {
+ gdImageDestroy(src);
+ return NULL;
+ }
+
+ gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy);
+
+ gdImageDestroy(src);
+
+ } else {
+ dst = src;
+ }
+
+ if (conf->filter == NGX_HTTP_IMAGE_CROP) {
+
+ src = dst;
+
+ if ((ngx_uint_t) dx > conf->width) {
+ ox = dx - conf->width;
+
+ } else {
+ ox = 0;
+ }
+
+ if ((ngx_uint_t) dy > conf->height) {
+ oy = dy - conf->height;
+
+ } else {
+ oy = 0;
+ }
+
+ if (ox || oy) {
+
+ dst = ngx_http_image_new(r, dx - ox, dy - oy, colors);
+
+ if (dst == NULL) {
+ gdImageDestroy(src);
+ return NULL;
+ }
+
+ ox /= 2;
+ oy /= 2;
+
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "image crop: %d x %d @ %d x %d",
+ dx, dy, ox, oy);
+
+ gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy);
+
+ gdImageDestroy(src);
+ }
+ }
+
+ gdImageColorTransparent(dst, transparent);
+
+ out = ngx_http_image_out(r, ctx->type, dst, &size);
+
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "image: %d x %d %d", sx, sy, colors);
+
+ gdImageDestroy(dst);
+ ngx_pfree(r->pool, ctx->image);
+
+ if (out == NULL) {
+ return NULL;
+ }
+
+ cln = ngx_pool_cleanup_add(r->pool, 0);
+ if (cln == NULL) {
+ gdFree(out);
+ return NULL;
+ }
+
+ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
+ if (b == NULL) {
+ gdFree(out);
+ return NULL;
+ }
+
+ cln->handler = ngx_http_image_cleanup;
+ cln->data = out;
+
+ b->pos = out;
+ b->last = out + size;
+ b->memory = 1;
+ b->last_buf = 1;
+
+ ngx_http_image_length(r, b);
+
+ return b;
+}
+
+
+static gdImagePtr
+ngx_http_image_source(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
+{
+ char *failed;
+ gdImagePtr img;
+
+ img = NULL;
+
+ switch (ctx->type) {
+
+ case NGX_HTTP_IMAGE_JPEG:
+ img = gdImageCreateFromJpegPtr(ctx->length, ctx->image);
+ failed = "gdImageCreateFromJpegPtr() failed";
+ break;
+
+ case NGX_HTTP_IMAGE_GIF:
+ img = gdImageCreateFromGifPtr(ctx->length, ctx->image);
+ failed = "gdImageCreateFromGifPtr() failed";
+ break;
+
+ case NGX_HTTP_IMAGE_PNG:
+ img = gdImageCreateFromPngPtr(ctx->length, ctx->image);
+ failed = "gdImageCreateFromPngPtr() failed";
+ break;
+
+ default:
+ failed = "unknown image type";
+ break;
+ }
+
+ if (img == NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, failed);
+ }
+
+ return img;
+}
+
+
+static gdImagePtr
+ngx_http_image_new(ngx_http_request_t *r, int w, int h, int colors)
+{
+ gdImagePtr img;
+
+ if (colors == 0) {
+ img = gdImageCreateTrueColor(w, h);
+
+ if (img == NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "gdImageCreateTrueColor() failed");
+ return NULL;
+ }
+
+ } else {
+ img = gdImageCreate(w, h);
+
+ if (img == NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "gdImageCreate() failed");
+ return NULL;
+ }
+ }
+
+ return img;
+}
+
+
+static u_char *
+ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
+ int *size)
+{
+ char *failed;
+ u_char *out;
+
+ out = NULL;
+
+ switch (type) {
+
+ case NGX_HTTP_IMAGE_JPEG:
+ out = gdImageJpegPtr(img, size, /* default quality */ -1);
+ failed = "gdImageJpegPtr() failed";
+ break;
+
+ case NGX_HTTP_IMAGE_GIF:
+ out = gdImageGifPtr(img, size);
+ failed = "gdImageGifPtr() failed";
+ break;
+
+ case NGX_HTTP_IMAGE_PNG:
+ out = gdImagePngPtr(img, size);
+ failed = "gdImagePngPtr() failed";
+ break;
+
+ default:
+ failed = "unknown image type";
+ break;
+ }
+
+ if (out == NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, failed);
+ }
+
+ return out;
+}
+
+
+static void
+ngx_http_image_cleanup(void *data)
+{
+ gdFree(data);
+}
+
+
+static void *
+ngx_http_image_filter_create_conf(ngx_conf_t *cf)
+{
+ ngx_http_image_filter_conf_t *conf;
+
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_image_filter_conf_t));
+ if (conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ conf->filter = NGX_CONF_UNSET_UINT;
+ conf->buffer_size = NGX_CONF_UNSET_SIZE;
+
+ return conf;
+}
+
+
+static char *
+ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+ ngx_http_image_filter_conf_t *prev = parent;
+ ngx_http_image_filter_conf_t *conf = child;
+
+ if (conf->filter == NGX_CONF_UNSET_UINT) {
+
+ if (prev->filter == NGX_CONF_UNSET_UINT) {
+ conf->filter = NGX_HTTP_IMAGE_OFF;
+
+ } else {
+ conf->filter = prev->filter;
+ conf->width = prev->width;
+ conf->height = prev->height;
+ }
+ }
+
+ ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
+ 1 * 1024 * 1024);
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_image_filter_conf_t *imcf = conf;
+
+ ngx_str_t *value;
+ ngx_int_t n;
+ ngx_uint_t i;
+
+ value = cf->args->elts;
+
+ i = 1;
+
+ if (cf->args->nelts == 2) {
+ if (ngx_strcmp(value[i].data, "off") == 0) {
+ imcf->filter = NGX_HTTP_IMAGE_OFF;
+
+ } else if (ngx_strcmp(value[i].data, "test") == 0) {
+ imcf->filter = NGX_HTTP_IMAGE_TEST;
+
+ } else if (ngx_strcmp(value[i].data, "size") == 0) {
+ imcf->filter = NGX_HTTP_IMAGE_SIZE;
+
+ } else {
+ goto failed;
+ }
+
+ return NGX_CONF_OK;
+ }
+
+ if (ngx_strcmp(value[i].data, "resize") == 0) {
+ imcf->filter = NGX_HTTP_IMAGE_RESIZE;
+
+ } else if (ngx_strcmp(value[i].data, "crop") == 0) {
+ imcf->filter = NGX_HTTP_IMAGE_CROP;
+
+ } else {
+ goto failed;
+ }
+
+ i++;
+
+ if (value[i].len == 1 && value[i].data[0] == '-') {
+ imcf->width = (ngx_uint_t) -1;
+
+ } else {
+ n = ngx_atoi(value[i].data, value[i].len);
+ if (n == NGX_ERROR) {
+ goto failed;
+ }
+
+ imcf->width = (ngx_uint_t) n;
+ }
+
+ i++;
+
+ if (value[i].len == 1 && value[i].data[0] == '-') {
+ imcf->height = (ngx_uint_t) -1;
+
+ } else {
+ n = ngx_atoi(value[i].data, value[i].len);
+ if (n == NGX_ERROR) {
+ goto failed;
+ }
+
+ imcf->height = (ngx_uint_t) n;
+ }
+
+ return NGX_CONF_OK;
+
+failed:
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
+ &value[i]);
+
+ return NGX_CONF_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_image_filter_init(ngx_conf_t *cf)
+{
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
+ ngx_http_top_header_filter = ngx_http_image_header_filter;
+
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_image_body_filter;
+
+ return NGX_OK;
+}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 628b32d4a..b191fbcfe 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -172,6 +172,15 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
};
+static ngx_conf_bitmask_t ngx_http_proxy_ignore_headers_masks[] = {
+ { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
+ { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
+ { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
+ { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
+ { ngx_null_string, 0 }
+};
+
+
ngx_module_t ngx_http_proxy_module;
@@ -426,6 +435,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
NULL },
+ { ngx_string("proxy_ignore_headers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
+ &ngx_http_proxy_ignore_headers_masks },
+
#if (NGX_HTTP_SSL)
{ ngx_string("proxy_ssl_session_reuse"),
@@ -1867,6 +1883,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
* set by ngx_pcalloc():
*
* conf->upstream.bufs.num = 0;
+ * conf->upstream.ignore_headers = 0;
* conf->upstream.next_upstream = 0;
* conf->upstream.use_stale_cache = 0;
* conf->upstream.temp_path = NULL;
@@ -2072,6 +2089,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
+ ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
+ prev->upstream.ignore_headers,
+ NGX_CONF_BITMASK_SET);
+
+
ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
prev->upstream.next_upstream,
(NGX_CONF_BITMASK_SET
@@ -2675,10 +2697,26 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
- if (ngx_strcmp(value[1].data, "off") == 0) {
- plcf->redirect = 0;
- plcf->redirects = NULL;
- return NGX_CONF_OK;
+ if (cf->args->nelts == 2) {
+ if (ngx_strcmp(value[1].data, "off") == 0) {
+ plcf->redirect = 0;
+ plcf->redirects = NULL;
+ return NGX_CONF_OK;
+ }
+
+ if (ngx_strcmp(value[1].data, "false") == 0) {
+ ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
+ "invalid parameter \"false\", use \"off\" instead");
+ plcf->redirect = 0;
+ plcf->redirects = NULL;
+ return NGX_CONF_OK;
+ }
+
+ if (ngx_strcmp(value[1].data, "default") != 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter \"%V\"", &value[1]);
+ return NGX_CONF_ERROR;
+ }
}
if (plcf->redirects == NULL) {
@@ -2694,7 +2732,7 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "default") == 0) {
+ if (ngx_strcmp(value[1].data, "default") == 0) {
if (plcf->url.data == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"proxy_rewrite_location default\" must go "
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
index 0762ee529..4759308c2 100644
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -64,7 +64,6 @@ typedef struct {
static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r,
ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_xslt_filter_internal_error(ngx_http_request_t *r);
static ngx_int_t ngx_http_xslt_add_chunk(ngx_http_request_t *r,
ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b);
@@ -320,14 +319,15 @@ ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
ctx->done = 1;
if (b == NULL) {
- return ngx_http_xslt_filter_internal_error(r);
+ return ngx_http_filter_finalize_request(r,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
}
cln = ngx_pool_cleanup_add(r->pool, 0);
if (cln == NULL) {
ngx_free(b->pos);
- return ngx_http_special_response_handler(r,
+ return ngx_http_filter_finalize_request(r,
NGX_HTTP_INTERNAL_SERVER_ERROR);
}
@@ -360,22 +360,6 @@ ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
static ngx_int_t
-ngx_http_xslt_filter_internal_error(ngx_http_request_t *r)
-{
- ngx_int_t rc;
-
- /* clear the modules contexts */
- ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
-
- rc = ngx_http_special_response_handler(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-
- /* NGX_ERROR resets any pending data */
-
- return (rc == NGX_OK) ? NGX_ERROR : rc;
-}
-
-
-static ngx_int_t
ngx_http_xslt_add_chunk(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
ngx_buf_t *b)
{
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 80af8f71e..47bc83e24 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.7.53';
+our $VERSION = '0.7.54';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 5cd0ee1f8..5e487e75c 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1746,7 +1746,7 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
- ls->log = *clcf->err_log;
+ ls->logp = clcf->error_log;
ls->log.data = &ls->addr_text;
ls->log.handler = ngx_accept_log_error;
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index 89de976df..2c442be9f 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -103,6 +103,9 @@ ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
ngx_int_t ngx_http_send_header(ngx_http_request_t *r);
ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r,
ngx_int_t error);
+ngx_int_t ngx_http_filter_finalize_request(ngx_http_request_t *r,
+ ngx_int_t error);
+void ngx_http_clean_header(ngx_http_request_t *r);
time_t ngx_http_parse_time(u_char *value, size_t len);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 825c8395c..4b300dfd5 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1292,10 +1292,10 @@ ngx_http_update_location_config(ngx_http_request_t *r)
}
if (r == r->main) {
- r->connection->log->file = clcf->err_log->file;
+ r->connection->log->file = clcf->error_log->file;
if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
- r->connection->log->log_level = clcf->err_log->log_level;
+ r->connection->log->log_level = clcf->error_log->log_level;
}
}
@@ -2929,7 +2929,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
* lcf->post_action = { 0, NULL };
* lcf->types = NULL;
* lcf->default_type = { 0, NULL };
- * lcf->err_log = NULL;
+ * lcf->error_log = NULL;
* lcf->error_pages = NULL;
* lcf->try_files = NULL;
* lcf->client_body_path = NULL;
@@ -3109,11 +3109,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
}
- if (conf->err_log == NULL) {
- if (prev->err_log) {
- conf->err_log = prev->err_log;
+ if (conf->error_log == NULL) {
+ if (prev->error_log) {
+ conf->error_log = prev->error_log;
} else {
- conf->err_log = cf->cycle->new_log;
+ conf->error_log = &cf->cycle->new_log;
}
}
@@ -4104,14 +4104,23 @@ ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value;
+ if (lcf->error_log) {
+ return "is duplicate";
+ }
+
value = cf->args->elts;
- lcf->err_log = ngx_log_create_errlog(cf->cycle, &value[1]);
- if (lcf->err_log == NULL) {
+ lcf->error_log = ngx_log_create(cf->cycle, &value[1]);
+ if (lcf->error_log == NULL) {
return NGX_CONF_ERROR;
}
- return ngx_set_error_log_levels(cf, lcf->err_log);
+ if (cf->args->nelts == 2) {
+ lcf->error_log->log_level = NGX_LOG_ERR;
+ return NGX_CONF_OK;
+ }
+
+ return ngx_log_set_levels(cf, lcf->error_log);
}
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 546ebbb56..2c4e45acd 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -377,7 +377,7 @@ struct ngx_http_core_loc_conf_s {
ngx_flag_t open_file_cache_errors;
ngx_flag_t open_file_cache_events;
- ngx_log_t *err_log;
+ ngx_log_t *error_log;
ngx_uint_t types_hash_max_size;
ngx_uint_t types_hash_bucket_size;
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index 21ee3bbd2..332fceb8a 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -357,6 +357,9 @@ ngx_http_header_filter(ngx_http_request_t *r)
else
#endif
port = (port == 80) ? 0 : port;
+
+ } else {
+ port = 0;
}
if (port) {
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index d06c6dd3f..9cdd92ddd 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -420,9 +420,9 @@ ngx_http_init_request(ngx_event_t *rev)
#endif
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- c->log->file = clcf->err_log->file;
+ c->log->file = clcf->error_log->file;
if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
- c->log->log_level = clcf->err_log->log_level;
+ c->log->log_level = clcf->error_log->log_level;
}
if (c->buffer == NULL) {
@@ -1704,10 +1704,10 @@ found:
r->loc_conf = cscf->ctx->loc_conf;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- r->connection->log->file = clcf->err_log->file;
+ r->connection->log->file = clcf->error_log->file;
if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
- r->connection->log->log_level = clcf->err_log->log_level;
+ r->connection->log->log_level = clcf->error_log->log_level;
}
return NGX_OK;
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 007fac3d5..7d3fd43e9 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -445,6 +445,40 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
}
+ngx_int_t
+ngx_http_filter_finalize_request(ngx_http_request_t *r, ngx_int_t error)
+{
+ ngx_int_t rc;
+
+ ngx_http_clean_header(r);
+
+ /* clear the modules contexts */
+ ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
+
+ rc = ngx_http_special_response_handler(r, error);
+
+ /* NGX_ERROR resets any pending data */
+
+ return (rc == NGX_OK) ? NGX_ERROR : rc;
+}
+
+
+void
+ngx_http_clean_header(ngx_http_request_t *r)
+{
+ ngx_memzero(&r->headers_out.status,
+ sizeof(ngx_http_headers_out_t)
+ - offsetof(ngx_http_headers_out_t, status));
+
+ r->headers_out.headers.part.nelts = 0;
+ r->headers_out.headers.part.next = NULL;
+ r->headers_out.headers.last = &r->headers_out.headers.part;
+
+ r->headers_out.content_length_n = -1;
+ r->headers_out.last_modified_time = -1;
+}
+
+
static ngx_int_t
ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
{
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 2a49270eb..2cf45625d 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -1623,8 +1623,9 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
- if (u->headers_in.x_accel_redirect) {
-
+ if (u->headers_in.x_accel_redirect
+ && !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT))
+ {
ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
part = &u->headers_in.headers.part;
@@ -2845,10 +2846,12 @@ static ngx_int_t
ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset)
{
- ngx_array_t *pa;
- ngx_table_elt_t **ph;
+ ngx_array_t *pa;
+ ngx_table_elt_t **ph;
+ ngx_http_upstream_t *u;
- pa = &r->upstream->headers_in.cache_control;
+ u = r->upstream;
+ pa = &u->headers_in.cache_control;
if (pa->elts == NULL) {
if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
@@ -2869,6 +2872,10 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
u_char *p, *last;
ngx_int_t n;
+ if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL) {
+ return NGX_OK;
+ }
+
if (r->cache == NULL) {
return NGX_OK;
}
@@ -2882,7 +2889,7 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
if (ngx_strlcasestrn(h->value.data, last, (u_char *) "no-cache", 8 - 1)
!= NULL)
{
- r->upstream->cacheable = 0;
+ u->cacheable = 0;
return NGX_OK;
}
@@ -2904,12 +2911,12 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
continue;
}
- r->upstream->cacheable = 0;
+ u->cacheable = 0;
return NGX_OK;
}
if (n == 0) {
- r->upstream->cacheable = 0;
+ u->cacheable = 0;
return NGX_OK;
}
@@ -2925,12 +2932,19 @@ static ngx_int_t
ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
- r->upstream->headers_in.expires = h;
+ ngx_http_upstream_t *u;
+
+ u = r->upstream;
+ u->headers_in.expires = h;
#if (NGX_HTTP_CACHE)
{
time_t expires;
+ if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_EXPIRES) {
+ return NGX_OK;
+ }
+
if (r->cache == NULL) {
return NGX_OK;
}
@@ -2942,7 +2956,7 @@ ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
expires = ngx_http_parse_time(h->value.data, h->value.len);
if (expires == NGX_ERROR || expires < ngx_time()) {
- r->upstream->cacheable = 0;
+ u->cacheable = 0;
return NGX_OK;
}
@@ -2958,7 +2972,10 @@ static ngx_int_t
ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset)
{
- r->upstream->headers_in.x_accel_expires = h;
+ ngx_http_upstream_t *u;
+
+ u = r->upstream;
+ u->headers_in.x_accel_expires = h;
#if (NGX_HTTP_CACHE)
{
@@ -2966,6 +2983,10 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
size_t len;
ngx_int_t n;
+ if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES) {
+ return NGX_OK;
+ }
+
if (r->cache == NULL) {
return NGX_OK;
}
@@ -2978,7 +2999,7 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
switch (n) {
case 0:
- r->upstream->cacheable = 0;
+ u->cacheable = 0;
case NGX_ERROR:
return NGX_OK;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 748e06444..95b396ee6 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -38,6 +38,12 @@
#define NGX_HTTP_UPSTREAM_INVALID_HEADER 40
+#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT 0x00000002
+#define NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES 0x00000004
+#define NGX_HTTP_UPSTREAM_IGN_EXPIRES 0x00000008
+#define NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL 0x00000010
+
+
typedef struct {
ngx_msec_t bl_time;
ngx_uint_t bl_state;
@@ -128,6 +134,7 @@ typedef struct {
ngx_bufs_t bufs;
+ ngx_uint_t ignore_headers;
ngx_uint_t next_upstream;
ngx_uint_t store_access;
ngx_flag_t buffering;
diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c
index aa77364de..1d6b78bdd 100644
--- a/src/mail/ngx_mail.c
+++ b/src/mail/ngx_mail.c
@@ -313,11 +313,10 @@ ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ls->handler = ngx_mail_init_connection;
ls->pool_size = 256;
- /* STUB */
- ls->log = *cf->cycle->new_log;
+ /* TODO: error_log directive */
+ ls->logp = &cf->cycle->new_log;
ls->log.data = &ls->addr_text;
ls->log.handler = ngx_accept_log_error;
- /**/
imip = ngx_palloc(cf->pool, sizeof(ngx_mail_in_port_t));
if (imip == NULL) {
diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h
index 8608e173d..cf5c3ed91 100644
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -113,6 +113,10 @@ ngx_write_fd(ngx_fd_t fd, void *buf, size_t n)
#define ngx_write_fd_n "write()"
+
+#define ngx_write_console ngx_write_fd
+
+
#define ngx_linefeed(p) *p++ = LF;
#define NGX_LINEFEED_SIZE 1