summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornginx <nginx@nginx.org>2012-12-25 14:47:11 +0000
committerJon Kolb <jon@b0g.us>2012-12-25 14:47:11 +0000
commit1c2503c4d9bc36b37e14c26ceb01558f6ca9949f (patch)
tree70c8c4fdff89d5e4ffda28874c551cc5efca06b3
parenta79aeb7ca33d55f3bed89062b1bdfe24ee9a46cb (diff)
downloadnginx-1c2503c4d9bc36b37e14c26ceb01558f6ca9949f.tar.gz
Changes with nginx 1.3.10 25 Dec 2012v1.3.10
*) Change: domain names specified in configuration file are now resolved to IPv6 addresses as well as IPv4 ones. *) Change: now if the "include" directive with mask is used on Unix systems, included files are sorted in alphabetical order. *) Change: the "add_header" directive adds headers to 201 responses. *) Feature: the "geo" directive now supports IPv6 addresses in CIDR notation. *) Feature: the "flush" and "gzip" parameters of the "access_log" directive. *) Feature: variables support in the "auth_basic" directive. *) Bugfix: nginx could not be built with the ngx_http_perl_module in some cases. *) Bugfix: a segmentation fault might occur in a worker process if the ngx_http_xslt_module was used. *) Bugfix: nginx could not be built on MacOSX in some cases. Thanks to Piotr Sikora. *) Bugfix: the "limit_rate" directive with high rates might result in truncated responses on 32-bit platforms. Thanks to Alexey Antropov. *) Bugfix: a segmentation fault might occur in a worker process if the "if" directive was used. Thanks to Piotr Sikora. *) Bugfix: a "100 Continue" response was issued with "413 Request Entity Too Large" responses. *) Bugfix: the "image_filter", "image_filter_jpeg_quality" and "image_filter_sharpen" directives might be inherited incorrectly. Thanks to Ian Babrou. *) Bugfix: "crypt_r() failed" errors might appear if the "auth_basic" directive was used on Linux. *) Bugfix: in backup servers handling. Thanks to Thomas Chen. *) Bugfix: proxied HEAD requests might return incorrect response if the "gzip" directive was used. Merry Christmas!
-rw-r--r--CHANGES52
-rw-r--r--CHANGES.ru53
-rw-r--r--auto/lib/pcre/conf1
-rw-r--r--auto/lib/perl/make4
-rw-r--r--auto/lib/zlib/conf5
-rwxr-xr-xauto/unix14
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_conf_file.c22
-rw-r--r--src/core/ngx_conf_file.h11
-rw-r--r--src/core/ngx_cycle.c21
-rw-r--r--src/core/ngx_file.c8
-rw-r--r--src/core/ngx_inet.c275
-rw-r--r--src/core/ngx_inet.h4
-rw-r--r--src/core/ngx_radix_tree.c207
-rw-r--r--src/core/ngx_radix_tree.h9
-rw-r--r--src/http/modules/ngx_http_auth_basic_module.c87
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c2
-rw-r--r--src/http/modules/ngx_http_geo_module.c361
-rw-r--r--src/http/modules/ngx_http_gzip_filter_module.c6
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c51
-rw-r--r--src/http/modules/ngx_http_image_filter_module.c40
-rw-r--r--src/http/modules/ngx_http_log_module.c418
-rw-r--r--src/http/modules/ngx_http_map_module.c7
-rw-r--r--src/http/modules/ngx_http_proxy_module.c7
-rw-r--r--src/http/modules/ngx_http_scgi_module.c2
-rw-r--r--src/http/modules/ngx_http_split_clients_module.c2
-rw-r--r--src/http/modules/ngx_http_sub_filter_module.c4
-rw-r--r--src/http/modules/ngx_http_upstream_least_conn_module.c4
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c2
-rw-r--r--src/http/modules/ngx_http_xslt_filter_module.c4
-rw-r--r--src/http/modules/perl/Makefile.PL17
-rw-r--r--src/http/modules/perl/nginx.pm4
-rw-r--r--src/http/ngx_http_core_module.c3
-rw-r--r--src/http/ngx_http_script.c10
-rw-r--r--src/http/ngx_http_upstream.c9
-rw-r--r--src/http/ngx_http_upstream_round_robin.c4
-rw-r--r--src/http/ngx_http_variables.c12
-rw-r--r--src/http/ngx_http_write_filter_module.c2
-rw-r--r--src/mail/ngx_mail_auth_http_module.c1
-rw-r--r--src/os/unix/ngx_files.c2
-rw-r--r--src/os/unix/ngx_user.c27
41 files changed, 1383 insertions, 395 deletions
diff --git a/CHANGES b/CHANGES
index 013350ba7..242d1441c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,56 @@
+Changes with nginx 1.3.10 25 Dec 2012
+
+ *) Change: domain names specified in configuration file are now resolved
+ to IPv6 addresses as well as IPv4 ones.
+
+ *) Change: now if the "include" directive with mask is used on Unix
+ systems, included files are sorted in alphabetical order.
+
+ *) Change: the "add_header" directive adds headers to 201 responses.
+
+ *) Feature: the "geo" directive now supports IPv6 addresses in CIDR
+ notation.
+
+ *) Feature: the "flush" and "gzip" parameters of the "access_log"
+ directive.
+
+ *) Feature: variables support in the "auth_basic" directive.
+
+ *) Bugfix: nginx could not be built with the ngx_http_perl_module in
+ some cases.
+
+ *) Bugfix: a segmentation fault might occur in a worker process if the
+ ngx_http_xslt_module was used.
+
+ *) Bugfix: nginx could not be built on MacOSX in some cases.
+ Thanks to Piotr Sikora.
+
+ *) Bugfix: the "limit_rate" directive with high rates might result in
+ truncated responses on 32-bit platforms.
+ Thanks to Alexey Antropov.
+
+ *) Bugfix: a segmentation fault might occur in a worker process if the
+ "if" directive was used.
+ Thanks to Piotr Sikora.
+
+ *) Bugfix: a "100 Continue" response was issued with "413 Request Entity
+ Too Large" responses.
+
+ *) Bugfix: the "image_filter", "image_filter_jpeg_quality" and
+ "image_filter_sharpen" directives might be inherited incorrectly.
+ Thanks to Ian Babrou.
+
+ *) Bugfix: "crypt_r() failed" errors might appear if the "auth_basic"
+ directive was used on Linux.
+
+ *) Bugfix: in backup servers handling.
+ Thanks to Thomas Chen.
+
+ *) Bugfix: proxied HEAD requests might return incorrect response if the
+ "gzip" directive was used.
+
+
Changes with nginx 1.3.9 27 Nov 2012
*) Feature: support for chunked transfer encoding while reading client
diff --git a/CHANGES.ru b/CHANGES.ru
index 568cea2e7..f24e5f81f 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,57 @@
+Изменения в nginx 1.3.10 25.12.2012
+
+ *) Изменение: для указанных в конфигурационном файле доменных имён
+ теперь используются не только IPv4, но и IPv6 адреса.
+
+ *) Изменение: теперь при использовании директивы include с маской на
+ Unix-системах включаемые файлы сортируются в алфавитном порядке.
+
+ *) Изменение: директива add_header добавляет строки в ответы с кодом
+ 201.
+
+ *) Добавление: директива geo теперь поддерживает IPv6 адреса в формате
+ CIDR.
+
+ *) Добавление: параметры flush и gzip в директиве access_log.
+
+ *) Добавление: директива auth_basic поддерживает переменные.
+
+ *) Исправление: nginx в некоторых случаях не собирался с модулем
+ ngx_http_perl_module.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если использовался модуль ngx_http_xslt_module.
+
+ *) Исправление: nginx мог не собираться на MacOSX.
+ Спасибо Piotr Sikora.
+
+ *) Исправление: при использовании директивы limit_rate с большими
+ значениями скорости на 32-битных системах ответ мог возвращаться не
+ целиком.
+ Спасибо Алексею Антропову.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если использовалась директива if.
+ Спасибо Piotr Sikora.
+
+ *) Исправление: ответ "100 Continue" выдавался вместе с ответом "413
+ Request Entity Too Large".
+
+ *) Исправление: директивы image_filter, image_filter_jpeg_quality и
+ image_filter_sharpen могли наследоваться некорректно.
+ Спасибо Ивану Боброву.
+
+ *) Исправление: при использовании директивы auth_basic под Linux могли
+ возникать ошибки "crypt_r() failed".
+
+ *) Исправление: в обработке backup-серверов.
+ Спасибо Thomas Chen.
+
+ *) Исправление: при проксировании HEAD-запросов мог возвращаться
+ некорректный ответ, если использовалась директива gzip.
+
+
Изменения в nginx 1.3.9 27.11.2012
*) Добавление: поддержка chunked transfer encoding при получении тела
diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf
index 6a8c326c4..345860053 100644
--- a/auto/lib/pcre/conf
+++ b/auto/lib/pcre/conf
@@ -172,6 +172,7 @@ else
ngx_feature="PCRE JIT support"
ngx_feature_name="NGX_HAVE_PCRE_JIT"
ngx_feature_test="int jit = 0;
+ pcre_free_study(NULL);
pcre_config(PCRE_CONFIG_JIT, &jit);
if (jit != 1) return 1;"
. auto/feature
diff --git a/auto/lib/perl/make b/auto/lib/perl/make
index 5f13bb29c..6fe95af0e 100644
--- a/auto/lib/perl/make
+++ b/auto/lib/perl/make
@@ -26,9 +26,7 @@ $NGX_OBJS/src/http/modules/perl/Makefile: \
cd $NGX_OBJS/src/http/modules/perl \
&& NGX_PM_CFLAGS="\$(NGX_PM_CFLAGS) -g $NGX_CC_OPT" \
- NGX_PCRE=$PCRE \
- NGX_OBJS=$NGX_OBJS \
- NGX_OPENSSL=$OPENSSL \
+ NGX_INCS="$CORE_INCS $NGX_OBJS $HTTP_INCS" \
$NGX_PERL Makefile.PL \
LIB=$NGX_PERL_MODULES \
INSTALLSITEMAN3DIR=$NGX_PERL_MODULES_MAN
diff --git a/auto/lib/zlib/conf b/auto/lib/zlib/conf
index cefc874b2..26db642ac 100644
--- a/auto/lib/zlib/conf
+++ b/auto/lib/zlib/conf
@@ -9,11 +9,13 @@ if [ $ZLIB != NONE ]; then
case "$NGX_CC_NAME" in
msvc* | owc* | bcc)
+ have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/zlib.lib"
CORE_LIBS="$CORE_LIBS $ZLIB/zlib.lib"
;;
icc*)
+ have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/libz.a"
# to allow -ipo optimization we link with the *.o but not library
@@ -30,6 +32,7 @@ if [ $ZLIB != NONE ]; then
;;
*)
+ have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/libz.a"
CORE_LIBS="$CORE_LIBS $ZLIB/libz.a"
#CORE_LIBS="$CORE_LIBS -L $ZLIB -lz"
@@ -45,7 +48,7 @@ else
# FreeBSD, Solaris, Linux
ngx_feature="zlib library"
- ngx_feature_name=
+ ngx_feature_name="NGX_ZLIB"
ngx_feature_run=no
ngx_feature_incs="#include <zlib.h>"
ngx_feature_path=
diff --git a/auto/unix b/auto/unix
index b0a0e4c88..cd4209e7b 100755
--- a/auto/unix
+++ b/auto/unix
@@ -778,3 +778,17 @@ ngx_feature_test="struct stat sb;
openat(AT_FDCWD, \".\", O_RDONLY|O_NOFOLLOW);
fstatat(AT_FDCWD, \".\", &sb, AT_SYMLINK_NOFOLLOW);"
. auto/feature
+
+
+ngx_feature="getaddrinfo()"
+ngx_feature_name="NGX_HAVE_GETADDRINFO"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test='struct addrinfo *res;
+ if (getaddrinfo("localhost", NULL, NULL, &res) != 0) return 1;
+ freeaddrinfo(res)'
+. auto/feature
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 58a4b1d16..0d5cc0987 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1003009
-#define NGINX_VERSION "1.3.9"
+#define nginx_version 1003010
+#define NGINX_VERSION "1.3.10"
#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 6da2dae80..0eb6388cb 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -945,7 +945,7 @@ ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
file->name = *name;
}
- file->buffer = NULL;
+ file->flush = NULL;
return file;
}
@@ -954,7 +954,6 @@ ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
static void
ngx_conf_flush_files(ngx_cycle_t *cycle)
{
- ssize_t n, len;
ngx_uint_t i;
ngx_list_part_t *part;
ngx_open_file_t *file;
@@ -975,23 +974,8 @@ ngx_conf_flush_files(ngx_cycle_t *cycle)
i = 0;
}
- len = file[i].pos - file[i].buffer;
-
- if (file[i].buffer == NULL || len == 0) {
- continue;
- }
-
- n = ngx_write_fd(file[i].fd, file[i].buffer, len);
-
- if (n == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- ngx_write_fd_n " to \"%s\" failed",
- file[i].name.data);
-
- } else if (n != len) {
- ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
- ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
- file[i].name.data, n, len);
+ if (file[i].flush) {
+ file[i].flush(&file[i], cycle->log);
}
}
}
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index 64a9e8fc8..237e6ecea 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -91,17 +91,8 @@ struct ngx_open_file_s {
ngx_fd_t fd;
ngx_str_t name;
- u_char *buffer;
- u_char *pos;
- u_char *last;
-
-#if 0
- /* e.g. append mode, error_log */
- ngx_uint_t flags;
- /* e.g. reopen db file */
- ngx_uint_t (*handler)(void *data, ngx_open_file_t *file);
+ void (*flush)(ngx_open_file_t *file, ngx_log_t *log);
void *data;
-#endif
};
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index e8b155921..dc4dc8993 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -1115,7 +1115,6 @@ ngx_test_lockfile(u_char *file, ngx_log_t *log)
void
ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
{
- ssize_t n, len;
ngx_fd_t fd;
ngx_uint_t i;
ngx_list_part_t *part;
@@ -1139,24 +1138,8 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
continue;
}
- len = file[i].pos - file[i].buffer;
-
- if (file[i].buffer && len != 0) {
-
- n = ngx_write_fd(file[i].fd, file[i].buffer, len);
-
- if (n == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- ngx_write_fd_n " to \"%s\" failed",
- file[i].name.data);
-
- } else if (n != len) {
- ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
- ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
- file[i].name.data, n, len);
- }
-
- file[i].pos = file[i].buffer;
+ if (file[i].flush) {
+ file[i].flush(&file[i], cycle->log);
}
fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND,
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index f13fb4952..35f5f8dc3 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -732,14 +732,14 @@ ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf)
n = ngx_read_fd(fd, buf, len);
- if (n == NGX_FILE_ERROR) {
+ if (n == -1) {
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
ngx_read_fd_n " \"%s\" failed", from);
goto failed;
}
if ((size_t) n != len) {
- ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
ngx_read_fd_n " has read only %z of %uz from %s",
n, size, from);
goto failed;
@@ -747,14 +747,14 @@ ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf)
n = ngx_write_fd(nfd, buf, len);
- if (n == NGX_FILE_ERROR) {
+ if (n == -1) {
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
ngx_write_fd_n " \"%s\" failed", to);
goto failed;
}
if ((size_t) n != len) {
- ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
ngx_write_fd_n " has written only %z of %uz to %s",
n, size, to);
goto failed;
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index 3db0136e5..9aec68964 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -465,7 +465,7 @@ ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
* prevent MSVC8 warning:
* potentially uninitialized local variable 'inaddr6' used
*/
- ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
+ ngx_memzero(&inaddr6, sizeof(struct in6_addr));
#endif
inaddr = ngx_inet_addr(text, len);
@@ -611,11 +611,13 @@ ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
static ngx_int_t
ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
{
- u_char *p, *host, *port, *last, *uri, *args;
- size_t len;
- ngx_int_t n;
- struct hostent *h;
- struct sockaddr_in *sin;
+ u_char *p, *host, *port, *last, *uri, *args;
+ size_t len;
+ ngx_int_t n;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+#endif
u->socklen = sizeof(struct sockaddr_in);
sin = (struct sockaddr_in *) &u->sockaddr;
@@ -705,6 +707,11 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
}
u->no_port = 1;
+
+ if (!u->no_resolve) {
+ u->port = u->default_port;
+ sin->sin_port = htons(u->default_port);
+ }
}
len = last - host;
@@ -714,59 +721,88 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR;
}
- if (len == 1 && *host == '*') {
- len = 0;
- }
-
u->host.len = len;
u->host.data = host;
- if (u->no_resolve) {
+ if (u->listen && len == 1 && *host == '*') {
+ sin->sin_addr.s_addr = INADDR_ANY;
+ u->wildcard = 1;
return NGX_OK;
}
- if (len) {
- sin->sin_addr.s_addr = ngx_inet_addr(host, len);
+ sin->sin_addr.s_addr = ngx_inet_addr(host, len);
- if (sin->sin_addr.s_addr == INADDR_NONE) {
- p = ngx_alloc(++len, pool->log);
- if (p == NULL) {
- return NGX_ERROR;
- }
+ if (sin->sin_addr.s_addr != INADDR_NONE) {
- (void) ngx_cpystrn(p, host, len);
-
- h = gethostbyname((const char *) p);
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ u->wildcard = 1;
+ }
- ngx_free(p);
+ u->naddrs = 1;
- if (h == NULL || h->h_addr_list[0] == NULL) {
- u->err = "host not found";
- return NGX_ERROR;
- }
+ u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
+ if (u->addrs == NULL) {
+ return NGX_ERROR;
+ }
- sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
+ sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
+ if (sin == NULL) {
+ return NGX_ERROR;
}
- if (sin->sin_addr.s_addr == INADDR_ANY) {
- u->wildcard = 1;
+ ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in));
+
+ u->addrs[0].sockaddr = (struct sockaddr *) sin;
+ u->addrs[0].socklen = sizeof(struct sockaddr_in);
+
+ p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
+ if (p == NULL) {
+ return NGX_ERROR;
}
- } else {
- sin->sin_addr.s_addr = INADDR_ANY;
- u->wildcard = 1;
- }
+ u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
+ &u->host, u->port) - p;
+ u->addrs[0].name.data = p;
- if (u->no_port) {
- u->port = u->default_port;
- sin->sin_port = htons(u->default_port);
+ return NGX_OK;
}
- if (u->listen) {
+ if (u->no_resolve) {
return NGX_OK;
}
- return ngx_inet_resolve_host(pool, u);
+ if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ u->family = u->addrs[0].sockaddr->sa_family;
+ u->socklen = u->addrs[0].socklen;
+ ngx_memcpy(u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);
+
+ switch (u->family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) &u->sockaddr;
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ u->wildcard = 1;
+ }
+
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) &u->sockaddr;
+
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ u->wildcard = 1;
+ }
+
+ break;
+ }
+
+ return NGX_OK;
}
@@ -832,6 +868,11 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
} else {
u->no_port = 1;
+
+ if (!u->no_resolve) {
+ u->port = u->default_port;
+ sin6->sin6_port = htons(u->default_port);
+ }
}
}
@@ -854,11 +895,6 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
u->wildcard = 1;
}
- if (u->no_port) {
- u->port = u->default_port;
- sin6->sin6_port = htons(u->default_port);
- }
-
u->family = AF_INET6;
u->naddrs = 1;
@@ -898,6 +934,150 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
}
+#if (NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6)
+
+ngx_int_t
+ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
+{
+ u_char *p, *host;
+ size_t len;
+ in_port_t port;
+ ngx_uint_t i;
+ struct addrinfo hints, *res, *rp;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ port = htons(u->port);
+
+ host = ngx_alloc(u->host.len + 1, pool->log);
+ if (host == NULL) {
+ return NGX_ERROR;
+ }
+
+ (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
+
+ ngx_memzero(&hints, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
+ u->err = "host not found";
+ ngx_free(host);
+ return NGX_ERROR;
+ }
+
+ ngx_free(host);
+
+ for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) {
+
+ switch (rp->ai_family) {
+
+ case AF_INET:
+ case AF_INET6:
+ break;
+
+ default:
+ continue;
+ }
+
+ i++;
+ }
+
+ if (i == 0) {
+ u->err = "host not found";
+ goto failed;
+ }
+
+ /* MP: ngx_shared_palloc() */
+
+ u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
+ if (u->addrs == NULL) {
+ goto failed;
+ }
+
+ u->naddrs = i;
+
+ i = 0;
+
+ /* AF_INET addresses first */
+
+ for (rp = res; rp != NULL; rp = rp->ai_next) {
+
+ if (rp->ai_family != AF_INET) {
+ continue;
+ }
+
+ sin = ngx_pcalloc(pool, rp->ai_addrlen);
+ if (sin == NULL) {
+ goto failed;
+ }
+
+ ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen);
+
+ sin->sin_port = port;
+
+ u->addrs[i].sockaddr = (struct sockaddr *) sin;
+ u->addrs[i].socklen = rp->ai_addrlen;
+
+ len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
+
+ p = ngx_pnalloc(pool, len);
+ if (p == NULL) {
+ goto failed;
+ }
+
+ len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
+
+ u->addrs[i].name.len = len;
+ u->addrs[i].name.data = p;
+
+ i++;
+ }
+
+ for (rp = res; rp != NULL; rp = rp->ai_next) {
+
+ if (rp->ai_family != AF_INET6) {
+ continue;
+ }
+
+ sin6 = ngx_pcalloc(pool, rp->ai_addrlen);
+ if (sin6 == NULL) {
+ goto failed;
+ }
+
+ ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen);
+
+ sin6->sin6_port = port;
+
+ u->addrs[i].sockaddr = (struct sockaddr *) sin6;
+ u->addrs[i].socklen = rp->ai_addrlen;
+
+ len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
+
+ p = ngx_pnalloc(pool, len);
+ if (p == NULL) {
+ goto failed;
+ }
+
+ len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, 1);
+
+ u->addrs[i].name.len = len;
+ u->addrs[i].name.data = p;
+
+ i++;
+ }
+
+ freeaddrinfo(res);
+ return NGX_OK;
+
+failed:
+
+ freeaddrinfo(res);
+ return NGX_ERROR;
+}
+
+#else /* !NGX_HAVE_GETADDRINFO || !NGX_HAVE_INET6 */
+
ngx_int_t
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
{
@@ -932,12 +1112,7 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR;
}
- if (u->one_addr == 0) {
- for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
-
- } else {
- i = 1;
- }
+ for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
/* MP: ngx_shared_palloc() */
@@ -1010,3 +1185,5 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
return NGX_OK;
}
+
+#endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h
index c5a3d7677..6a5a3687d 100644
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -30,7 +30,7 @@
#if (NGX_HAVE_UNIX_DOMAIN)
#define NGX_SOCKADDR_STRLEN (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN)
#else
-#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1)
+#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1)
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
@@ -87,7 +87,7 @@ typedef struct {
unsigned listen:1;
unsigned uri_part:1;
unsigned no_resolve:1;
- unsigned one_addr:1;
+ unsigned one_addr:1; /* compatibility */
unsigned no_port:1;
unsigned wildcard:1;
diff --git a/src/core/ngx_radix_tree.c b/src/core/ngx_radix_tree.c
index 5b35d1e49..c1d873749 100644
--- a/src/core/ngx_radix_tree.c
+++ b/src/core/ngx_radix_tree.c
@@ -9,7 +9,7 @@
#include <ngx_core.h>
-static void *ngx_radix_alloc(ngx_radix_tree_t *tree);
+static ngx_radix_node_t *ngx_radix_alloc(ngx_radix_tree_t *tree);
ngx_radix_tree_t *
@@ -263,13 +263,210 @@ ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
}
-static void *
+#if (NGX_HAVE_INET6)
+
+ngx_int_t
+ngx_radix128tree_insert(ngx_radix_tree_t *tree, u_char *key, u_char *mask,
+ uintptr_t value)
+{
+ u_char bit;
+ ngx_uint_t i;
+ ngx_radix_node_t *node, *next;
+
+ i = 0;
+ bit = 0x80;
+
+ node = tree->root;
+ next = tree->root;
+
+ while (bit & mask[i]) {
+ if (key[i] & bit) {
+ next = node->right;
+
+ } else {
+ next = node->left;
+ }
+
+ if (next == NULL) {
+ break;
+ }
+
+ bit >>= 1;
+ node = next;
+
+ if (bit == 0) {
+ if (++i == 16) {
+ break;
+ }
+
+ bit = 0x80;
+ }
+ }
+
+ if (next) {
+ if (node->value != NGX_RADIX_NO_VALUE) {
+ return NGX_BUSY;
+ }
+
+ node->value = value;
+ return NGX_OK;
+ }
+
+ while (bit & mask[i]) {
+ next = ngx_radix_alloc(tree);
+ if (next == NULL) {
+ return NGX_ERROR;
+ }
+
+ next->right = NULL;
+ next->left = NULL;
+ next->parent = node;
+ next->value = NGX_RADIX_NO_VALUE;
+
+ if (key[i] & bit) {
+ node->right = next;
+
+ } else {
+ node->left = next;
+ }
+
+ bit >>= 1;
+ node = next;
+
+ if (bit == 0) {
+ if (++i == 16) {
+ break;
+ }
+
+ bit = 0x80;
+ }
+ }
+
+ node->value = value;
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_radix128tree_delete(ngx_radix_tree_t *tree, u_char *key, u_char *mask)
+{
+ u_char bit;
+ ngx_uint_t i;
+ ngx_radix_node_t *node;
+
+ i = 0;
+ bit = 0x80;
+ node = tree->root;
+
+ while (node && (bit & mask[i])) {
+ if (key[i] & bit) {
+ node = node->right;
+
+ } else {
+ node = node->left;
+ }
+
+ bit >>= 1;
+
+ if (bit == 0) {
+ if (++i == 16) {
+ break;
+ }
+
+ bit = 0x80;
+ }
+ }
+
+ if (node == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (node->right || node->left) {
+ if (node->value != NGX_RADIX_NO_VALUE) {
+ node->value = NGX_RADIX_NO_VALUE;
+ return NGX_OK;
+ }
+
+ return NGX_ERROR;
+ }
+
+ for ( ;; ) {
+ if (node->parent->right == node) {
+ node->parent->right = NULL;
+
+ } else {
+ node->parent->left = NULL;
+ }
+
+ node->right = tree->free;
+ tree->free = node;
+
+ node = node->parent;
+
+ if (node->right || node->left) {
+ break;
+ }
+
+ if (node->value != NGX_RADIX_NO_VALUE) {
+ break;
+ }
+
+ if (node->parent == NULL) {
+ break;
+ }
+ }
+
+ return NGX_OK;
+}
+
+
+uintptr_t
+ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key)
+{
+ u_char bit;
+ uintptr_t value;
+ ngx_uint_t i;
+ ngx_radix_node_t *node;
+
+ i = 0;
+ bit = 0x80;
+ value = NGX_RADIX_NO_VALUE;
+ node = tree->root;
+
+ while (node) {
+ if (node->value != NGX_RADIX_NO_VALUE) {
+ value = node->value;
+ }
+
+ if (key[i] & bit) {
+ node = node->right;
+
+ } else {
+ node = node->left;
+ }
+
+ bit >>= 1;
+
+ if (bit == 0) {
+ i++;
+ bit = 0x80;
+ }
+ }
+
+ return value;
+}
+
+#endif
+
+
+static ngx_radix_node_t *
ngx_radix_alloc(ngx_radix_tree_t *tree)
{
- char *p;
+ ngx_radix_node_t *p;
if (tree->free) {
- p = (char *) tree->free;
+ p = tree->free;
tree->free = tree->free->right;
return p;
}
@@ -283,7 +480,7 @@ ngx_radix_alloc(ngx_radix_tree_t *tree)
tree->size = ngx_pagesize;
}
- p = tree->start;
+ p = (ngx_radix_node_t *) tree->start;
tree->start += sizeof(ngx_radix_node_t);
tree->size -= sizeof(ngx_radix_node_t);
diff --git a/src/core/ngx_radix_tree.h b/src/core/ngx_radix_tree.h
index 65ee69b26..4fe06e014 100644
--- a/src/core/ngx_radix_tree.h
+++ b/src/core/ngx_radix_tree.h
@@ -36,11 +36,20 @@ typedef struct {
ngx_radix_tree_t *ngx_radix_tree_create(ngx_pool_t *pool,
ngx_int_t preallocate);
+
ngx_int_t ngx_radix32tree_insert(ngx_radix_tree_t *tree,
uint32_t key, uint32_t mask, uintptr_t value);
ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree,
uint32_t key, uint32_t mask);
uintptr_t ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key);
+#if (NGX_HAVE_INET6)
+ngx_int_t ngx_radix128tree_insert(ngx_radix_tree_t *tree,
+ u_char *key, u_char *mask, uintptr_t value);
+ngx_int_t ngx_radix128tree_delete(ngx_radix_tree_t *tree,
+ u_char *key, u_char *mask);
+uintptr_t ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key);
+#endif
+
#endif /* _NGX_RADIX_TREE_H_INCLUDED_ */
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c
index ec3b1cf95..e8709e5e9 100644
--- a/src/http/modules/ngx_http_auth_basic_module.c
+++ b/src/http/modules/ngx_http_auth_basic_module.c
@@ -20,8 +20,8 @@ typedef struct {
typedef struct {
- ngx_str_t realm;
- ngx_http_complex_value_t user_file;
+ ngx_http_complex_value_t *realm;
+ ngx_http_complex_value_t user_file;
} ngx_http_auth_basic_loc_conf_t;
@@ -35,22 +35,19 @@ static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_http_auth_basic_init(ngx_conf_t *cf);
-static char *ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data);
static char *ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-static ngx_conf_post_handler_pt ngx_http_auth_basic_p = ngx_http_auth_basic;
-
static ngx_command_t ngx_http_auth_basic_commands[] = {
{ ngx_string("auth_basic"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
+ ngx_http_set_complex_value_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_auth_basic_loc_conf_t, realm),
- &ngx_http_auth_basic_p },
+ NULL },
{ ngx_string("auth_basic_user_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
@@ -103,7 +100,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_fd_t fd;
ngx_int_t rc;
ngx_err_t err;
- ngx_str_t pwd, user_file;
+ ngx_str_t pwd, realm, user_file;
ngx_uint_t i, level, login, left, passwd;
ngx_file_t file;
ngx_http_auth_basic_ctx_t *ctx;
@@ -117,7 +114,15 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module);
- if (alcf->realm.len == 0 || alcf->user_file.value.len == 0) {
+ if (alcf->realm == NULL || alcf->user_file.value.data == NULL) {
+ return NGX_DECLINED;
+ }
+
+ if (ngx_http_complex_value(r, alcf->realm, &realm) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (realm.len == 3 && ngx_strncmp(realm.data, "off", 3) == 0) {
return NGX_DECLINED;
}
@@ -125,7 +130,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
if (ctx) {
return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd,
- &alcf->realm);
+ &realm);
}
rc = ngx_http_auth_basic_user(r);
@@ -135,7 +140,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"no user/password was provided for basic authentication");
- return ngx_http_auth_basic_set_realm(r, &alcf->realm);
+ return ngx_http_auth_basic_set_realm(r, &realm);
}
if (rc == NGX_ERROR) {
@@ -233,7 +238,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
pwd.data = &buf[passwd];
return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd,
- &alcf->realm);
+ &realm);
}
break;
@@ -271,14 +276,14 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
- return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &alcf->realm);
+ return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &realm);
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"user \"%V\" was not found in \"%V\"",
&r->headers_in.user, &user_file);
- return ngx_http_auth_basic_set_realm(r, &alcf->realm);
+ return ngx_http_auth_basic_set_realm(r, &realm);
}
@@ -344,14 +349,29 @@ ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
static ngx_int_t
ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
{
+ size_t len;
+ u_char *basic, *p;
+
r->headers_out.www_authenticate = ngx_list_push(&r->headers_out.headers);
if (r->headers_out.www_authenticate == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ len = sizeof("Basic realm=\"\"") - 1 + realm->len;
+
+ basic = ngx_pnalloc(r->pool, len);
+ if (basic == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1);
+ p = ngx_cpymem(p, realm->data, realm->len);
+ *p = '"';
+
r->headers_out.www_authenticate->hash = 1;
ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate");
- r->headers_out.www_authenticate->value = *realm;
+ r->headers_out.www_authenticate->value.data = basic;
+ r->headers_out.www_authenticate->value.len = len;
return NGX_HTTP_UNAUTHORIZED;
}
@@ -386,11 +406,11 @@ ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_auth_basic_loc_conf_t *prev = parent;
ngx_http_auth_basic_loc_conf_t *conf = child;
- if (conf->realm.data == NULL) {
+ if (conf->realm == NULL) {
conf->realm = prev->realm;
}
- if (conf->user_file.value.len == 0) {
+ if (conf->user_file.value.data == NULL) {
conf->user_file = prev->user_file;
}
@@ -418,37 +438,6 @@ ngx_http_auth_basic_init(ngx_conf_t *cf)
static char *
-ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data)
-{
- ngx_str_t *realm = data;
-
- size_t len;
- u_char *basic, *p;
-
- if (ngx_strcmp(realm->data, "off") == 0) {
- ngx_str_set(realm, "");
- return NGX_CONF_OK;
- }
-
- len = sizeof("Basic realm=\"") - 1 + realm->len + 1;
-
- basic = ngx_pnalloc(cf->pool, len);
- if (basic == NULL) {
- return NGX_CONF_ERROR;
- }
-
- p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1);
- p = ngx_cpymem(p, realm->data, realm->len);
- *p = '"';
-
- realm->len = len;
- realm->data = basic;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_auth_basic_loc_conf_t *alcf = conf;
@@ -456,7 +445,7 @@ ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value;
ngx_http_compile_complex_value_t ccv;
- if (alcf->user_file.value.len) {
+ if (alcf->user_file.value.data) {
return "is duplicate";
}
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index e8ff24cac..f1917e25d 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -3014,7 +3014,7 @@ ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
- if (flcf->cache_key.value.len) {
+ if (flcf->cache_key.value.data) {
return "is duplicate";
}
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index fce87a8cb..4bad08d4f 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -18,6 +18,14 @@ typedef struct {
typedef struct {
+ ngx_radix_tree_t *tree;
+#if (NGX_HAVE_INET6)
+ ngx_radix_tree_t *tree6;
+#endif
+} ngx_http_geo_trees_t;
+
+
+typedef struct {
ngx_http_geo_range_t **low;
ngx_http_variable_value_t *default_value;
} ngx_http_geo_high_ranges_t;
@@ -35,6 +43,9 @@ typedef struct {
ngx_str_t *net;
ngx_http_geo_high_ranges_t high;
ngx_radix_tree_t *tree;
+#if (NGX_HAVE_INET6)
+ ngx_radix_tree_t *tree6;
+#endif
ngx_rbtree_t rbtree;
ngx_rbtree_node_t sentinel;
ngx_array_t *proxies;
@@ -57,7 +68,7 @@ typedef struct {
typedef struct {
union {
- ngx_radix_tree_t *tree;
+ ngx_http_geo_trees_t trees;
ngx_http_geo_high_ranges_t high;
} u;
@@ -68,8 +79,8 @@ typedef struct {
} ngx_http_geo_ctx_t;
-static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
- ngx_http_geo_ctx_t *ctx);
+static ngx_int_t ngx_http_geo_addr(ngx_http_request_t *r,
+ ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r,
ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
@@ -155,7 +166,7 @@ static ngx_http_geo_header_t ngx_http_geo_header = {
};
-/* AF_INET only */
+/* geo range is AF_INET only */
static ngx_int_t
ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
@@ -163,10 +174,56 @@ ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
{
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
+ in_addr_t inaddr;
+ ngx_addr_t addr;
+ struct sockaddr_in *sin;
ngx_http_variable_value_t *vv;
+#if (NGX_HAVE_INET6)
+ u_char *p;
+ struct in6_addr *inaddr6;
+#endif
+
+ if (ngx_http_geo_addr(r, ctx, &addr) != NGX_OK) {
+ vv = (ngx_http_variable_value_t *)
+ ngx_radix32tree_find(ctx->u.trees.tree, INADDR_NONE);
+ goto done;
+ }
+
+ switch (addr.sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
+ p = inaddr6->s6_addr;
+
+ if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
+ inaddr = p[12] << 24;
+ inaddr += p[13] << 16;
+ inaddr += p[14] << 8;
+ inaddr += p[15];
+
+ vv = (ngx_http_variable_value_t *)
+ ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
+
+ } else {
+ vv = (ngx_http_variable_value_t *)
+ ngx_radix128tree_find(ctx->u.trees.tree6, p);
+ }
+
+ break;
+#endif
- vv = (ngx_http_variable_value_t *)
- ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx));
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) addr.sockaddr;
+ inaddr = ntohl(sin->sin_addr.s_addr);
+
+ vv = (ngx_http_variable_value_t *)
+ ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
+
+ break;
+ }
+
+done:
*v = *vv;
@@ -183,25 +240,65 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
{
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
- in_addr_t addr;
+ in_addr_t inaddr;
+ ngx_addr_t addr;
ngx_uint_t n;
+ struct sockaddr_in *sin;
ngx_http_geo_range_t *range;
+#if (NGX_HAVE_INET6)
+ u_char *p;
+ struct in6_addr *inaddr6;
+#endif
*v = *ctx->u.high.default_value;
- addr = ngx_http_geo_addr(r, ctx);
+ if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) {
- range = ctx->u.high.low[addr >> 16];
+ switch (addr.sockaddr->sa_family) {
- if (range) {
- n = addr & 0xffff;
- do {
- if (n >= (ngx_uint_t) range->start && n <= (ngx_uint_t) range->end)
- {
- *v = *range->value;
- break;
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
+
+ if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
+ p = inaddr6->s6_addr;
+
+ inaddr = p[12] << 24;
+ inaddr += p[13] << 16;
+ inaddr += p[14] << 8;
+ inaddr += p[15];
+
+ } else {
+ inaddr = INADDR_NONE;
}
- } while ((++range)->value);
+
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) addr.sockaddr;
+ inaddr = ntohl(sin->sin_addr.s_addr);
+ break;
+ }
+
+ } else {
+ inaddr = INADDR_NONE;
+ }
+
+ if (ctx->u.high.low) {
+ range = ctx->u.high.low[inaddr >> 16];
+
+ if (range) {
+ n = inaddr & 0xffff;
+ do {
+ if (n >= (ngx_uint_t) range->start
+ && n <= (ngx_uint_t) range->end)
+ {
+ *v = *range->value;
+ break;
+ }
+ } while ((++range)->value);
+ }
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -211,54 +308,25 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
}
-static in_addr_t
-ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
+static ngx_int_t
+ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
+ ngx_addr_t *addr)
{
- ngx_addr_t addr;
- ngx_table_elt_t *xfwd;
- struct sockaddr_in *sin;
+ ngx_table_elt_t *xfwd;
- if (ngx_http_geo_real_addr(r, ctx, &addr) != NGX_OK) {
- return INADDR_NONE;
+ if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
+ return NGX_ERROR;
}
xfwd = r->headers_in.x_forwarded_for;
if (xfwd != NULL && ctx->proxies != NULL) {
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
+ (void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data,
xfwd->value.len, ctx->proxies,
ctx->proxy_recursive);
}
-#if (NGX_HAVE_INET6)
-
- if (addr.sockaddr->sa_family == AF_INET6) {
- u_char *p;
- in_addr_t inaddr;
- struct in6_addr *inaddr6;
-
- inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
-
- if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
- p = inaddr6->s6_addr;
-
- inaddr = p[12] << 24;
- inaddr += p[13] << 16;
- inaddr += p[14] << 8;
- inaddr += p[15];
-
- return inaddr;
- }
- }
-
-#endif
-
- if (addr.sockaddr->sa_family != AF_INET) {
- return INADDR_NONE;
- }
-
- sin = (struct sockaddr_in *) addr.sockaddr;
- return ntohl(sin->sin_addr.s_addr);
+ return NGX_OK;
}
@@ -303,7 +371,6 @@ static char *
ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
- void **p;
size_t len;
ngx_str_t *value, name;
ngx_uint_t i;
@@ -313,6 +380,9 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_variable_t *var;
ngx_http_geo_ctx_t *geo;
ngx_http_geo_conf_ctx_t ctx;
+#if (NGX_HAVE_INET6)
+ static struct in6_addr zero;
+#endif
value = cf->args->elts;
@@ -322,6 +392,13 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
name = value[1];
+
+ if (name.data[0] != '$') {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid variable name \"%V\"", &name);
+ return NGX_CONF_ERROR;
+ }
+
name.len--;
name.data++;
@@ -333,6 +410,13 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
name = value[2];
+
+ if (name.data[0] != '$') {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid variable name \"%V\"", &name);
+ return NGX_CONF_ERROR;
+ }
+
name.len--;
name.data++;
@@ -378,9 +462,9 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
geo->proxies = ctx.proxies;
geo->proxy_recursive = ctx.proxy_recursive;
- if (ctx.high.low) {
+ if (ctx.ranges) {
- if (!ctx.binary_include) {
+ if (ctx.high.low && !ctx.binary_include) {
for (i = 0; i < 0x10000; i++) {
a = (ngx_array_t *) ctx.high.low[i];
@@ -395,8 +479,8 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- p = (void **) ngx_cpymem(ctx.high.low[i], a->elts, len);
- *p = NULL;
+ ngx_memcpy(ctx.high.low[i], a->elts, len);
+ ctx.high.low[i][a->nelts].value = NULL;
ctx.data_size += len + sizeof(void *);
}
@@ -429,7 +513,18 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
- geo->u.tree = ctx.tree;
+ geo->u.trees.tree = ctx.tree;
+
+#if (NGX_HAVE_INET6)
+ if (ctx.tree6 == NULL) {
+ ctx.tree6 = ngx_radix_tree_create(cf->pool, -1);
+ if (ctx.tree6 == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ geo->u.trees.tree6 = ctx.tree6;
+#endif
var->get_handler = ngx_http_geo_cidr_variable;
var->data = (uintptr_t) geo;
@@ -437,16 +532,23 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_destroy_pool(ctx.temp_pool);
ngx_destroy_pool(pool);
- if (ngx_radix32tree_find(ctx.tree, 0) != NGX_RADIX_NO_VALUE) {
- return rv;
- }
-
if (ngx_radix32tree_insert(ctx.tree, 0, 0,
(uintptr_t) &ngx_http_variable_null_value)
== NGX_ERROR)
{
return NGX_CONF_ERROR;
}
+
+ /* NGX_BUSY is okay (default was set explicitly) */
+
+#if (NGX_HAVE_INET6)
+ if (ngx_radix128tree_insert(ctx.tree6, zero.s6_addr, zero.s6_addr,
+ (uintptr_t) &ngx_http_variable_null_value)
+ == NGX_ERROR)
+ {
+ return NGX_CONF_ERROR;
+ }
+#endif
}
return rv;
@@ -469,7 +571,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
if (ngx_strcmp(value[0].data, "ranges") == 0) {
- if (ctx->tree) {
+ if (ctx->tree
+#if (NGX_HAVE_INET6)
+ || ctx->tree6
+#endif
+ )
+ {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the \"ranges\" directive must be "
"the first directive inside \"geo\" block");
@@ -920,8 +1027,17 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
}
}
+#if (NGX_HAVE_INET6)
+ if (ctx->tree6 == NULL) {
+ ctx->tree6 = ngx_radix_tree_create(ctx->pool, -1);
+ if (ctx->tree6 == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+#endif
+
if (ngx_strcmp(value[0].data, "default") == 0) {
- /* cidr.family = AF_INET; */
+ cidr.family = AF_INET;
cidr.u.in.addr = 0;
cidr.u.in.mask = 0;
net = &value[0];
@@ -940,20 +1056,29 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
return NGX_CONF_ERROR;
}
- if (cidr.family != AF_INET) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"geo\" supports IPv4 only");
- return NGX_CONF_ERROR;
+ if (cidr.family == AF_INET) {
+ cidr.u.in.addr = ntohl(cidr.u.in.addr);
+ cidr.u.in.mask = ntohl(cidr.u.in.mask);
}
- cidr.u.in.addr = ntohl(cidr.u.in.addr);
- cidr.u.in.mask = ntohl(cidr.u.in.mask);
-
if (del) {
- if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
- cidr.u.in.mask)
- != NGX_OK)
- {
+ switch (cidr.family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ rc = ngx_radix128tree_delete(ctx->tree6,
+ cidr.u.in6.addr.s6_addr,
+ cidr.u.in6.mask.s6_addr);
+ break;
+#endif
+
+ default: /* AF_INET */
+ rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
+ cidr.u.in.mask);
+ break;
+ }
+
+ if (rc != NGX_OK) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"no network \"%V\" to delete", net);
}
@@ -968,32 +1093,78 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
return NGX_CONF_ERROR;
}
- for (i = 2; i; i--) {
- rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask,
- (uintptr_t) val);
- if (rc == NGX_OK) {
- return NGX_CONF_OK;
- }
+ switch (cidr.family) {
- if (rc == NGX_ERROR) {
- return NGX_CONF_ERROR;
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ for (i = 2; i; i--) {
+ rc = ngx_radix128tree_insert(ctx->tree6, cidr.u.in6.addr.s6_addr,
+ cidr.u.in6.mask.s6_addr,
+ (uintptr_t) val);
+
+ if (rc == NGX_OK) {
+ return NGX_CONF_OK;
+ }
+
+ if (rc == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
+ /* rc == NGX_BUSY */
+
+ old = (ngx_http_variable_value_t *)
+ ngx_radix128tree_find(ctx->tree6,
+ cidr.u.in6.addr.s6_addr);
+
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
+ net, val, old);
+
+ rc = ngx_radix128tree_delete(ctx->tree6,
+ cidr.u.in6.addr.s6_addr,
+ cidr.u.in6.mask.s6_addr);
+
+ if (rc == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
+ return NGX_CONF_ERROR;
+ }
}
- /* rc == NGX_BUSY */
+ break;
+#endif
- old = (ngx_http_variable_value_t *)
- ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask);
+ default: /* AF_INET */
+ for (i = 2; i; i--) {
+ rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr,
+ cidr.u.in.mask, (uintptr_t) val);
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
- net, val, old);
+ if (rc == NGX_OK) {
+ return NGX_CONF_OK;
+ }
+
+ if (rc == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
- rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask);
+ /* rc == NGX_BUSY */
- if (rc == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
- return NGX_CONF_ERROR;
+ old = (ngx_http_variable_value_t *)
+ ngx_radix32tree_find(ctx->tree, cidr.u.in.addr);
+
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
+ net, val, old);
+
+ rc = ngx_radix32tree_delete(ctx->tree,
+ cidr.u.in.addr, cidr.u.in.mask);
+
+ if (rc == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
+ return NGX_CONF_ERROR;
+ }
}
+
+ break;
}
return NGX_CONF_ERROR;
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 09994d9b2..2f39543af 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -321,7 +321,7 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
- if (ctx == NULL || ctx->done) {
+ if (ctx == NULL || ctx->done || r->header_only) {
return ngx_http_next_body_filter(r, in);
}
@@ -498,6 +498,10 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
wbits--;
memlevel--;
}
+
+ if (memlevel < 1) {
+ memlevel = 1;
+ }
}
ctx->wbits = wbits;
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index 5b85e59cd..0dfe8101e 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -74,7 +74,9 @@ static ngx_http_set_header_t ngx_http_set_headers[] = {
{ ngx_string("Cache-Control"), 0, ngx_http_add_cache_control },
- { ngx_string("Last-Modified"), 0, ngx_http_set_last_modified },
+ { ngx_string("Last-Modified"),
+ offsetof(ngx_http_headers_out_t, last_modified),
+ ngx_http_set_last_modified },
{ ngx_string("ETag"),
offsetof(ngx_http_headers_out_t, etag),
@@ -153,6 +155,7 @@ ngx_http_headers_filter(ngx_http_request_t *r)
if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL)
|| r != r->main
|| (r->headers_out.status != NGX_HTTP_OK
+ && r->headers_out.status != NGX_HTTP_CREATED
&& r->headers_out.status != NGX_HTTP_NO_CONTENT
&& r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT
&& r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY
@@ -372,27 +375,12 @@ static ngx_int_t
ngx_http_set_last_modified(ngx_http_request_t *r, ngx_http_header_val_t *hv,
ngx_str_t *value)
{
- ngx_table_elt_t *h;
-
- ngx_http_clear_last_modified(r);
-
- if (value->len == 0) {
- return NGX_OK;
- }
-
- r->headers_out.last_modified_time = ngx_http_parse_time(value->data,
- value->len);
-
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
+ if (ngx_http_set_response_header(r, hv, value) != NGX_OK) {
return NGX_ERROR;
}
- r->headers_out.last_modified = h;
-
- h->hash = 1;
- h->key = hv->key;
- h->value = *value;
+ r->headers_out.last_modified_time =
+ (value->len) ? ngx_http_parse_time(value->data, value->len) : -1;
return NGX_OK;
}
@@ -406,21 +394,26 @@ ngx_http_set_response_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
- if (*old) {
- (*old)->hash = 0;
- *old = NULL;
- }
-
if (value->len == 0) {
+ if (*old) {
+ (*old)->hash = 0;
+ *old = NULL;
+ }
+
return NGX_OK;
}
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
+ if (*old) {
+ h = *old;
- *old = h;
+ } else {
+ h = ngx_list_push(&r->headers_out.headers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
+
+ *old = h;
+ }
h->hash = 1;
h->key = hv->key;
diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c
index c853c33d0..1550aeecb 100644
--- a/src/http/modules/ngx_http_image_filter_module.c
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -1169,10 +1169,22 @@ ngx_http_image_filter_create_conf(ngx_conf_t *cf)
return NULL;
}
+ /*
+ * set by ngx_pcalloc():
+ *
+ * conf->width = 0;
+ * conf->height = 0;
+ * conf->angle = 0;
+ * conf->wcv = NULL;
+ * conf->hcv = NULL;
+ * conf->acv = NULL;
+ * conf->jqcv = NULL;
+ * conf->shcv = NULL;
+ */
+
conf->filter = NGX_CONF_UNSET_UINT;
conf->jpeg_quality = NGX_CONF_UNSET_UINT;
conf->sharpen = NGX_CONF_UNSET_UINT;
- conf->angle = NGX_CONF_UNSET_UINT;
conf->transparency = NGX_CONF_UNSET;
conf->buffer_size = NGX_CONF_UNSET_SIZE;
@@ -1195,27 +1207,29 @@ ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
conf->filter = prev->filter;
conf->width = prev->width;
conf->height = prev->height;
+ conf->angle = prev->angle;
conf->wcv = prev->wcv;
conf->hcv = prev->hcv;
+ conf->acv = prev->acv;
}
}
- /* 75 is libjpeg default quality */
- ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
-
- if (conf->jqcv == NULL) {
- conf->jqcv = prev->jqcv;
- }
+ if (conf->jpeg_quality == NGX_CONF_UNSET_UINT) {
- ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0);
+ /* 75 is libjpeg default quality */
+ ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
- if (conf->shcv == NULL) {
- conf->shcv = prev->shcv;
+ if (conf->jqcv == NULL) {
+ conf->jqcv = prev->jqcv;
+ }
}
- ngx_conf_merge_uint_value(conf->angle, prev->angle, 0);
- if (conf->acv == NULL) {
- conf->acv = prev->acv;
+ if (conf->sharpen == NGX_CONF_UNSET_UINT) {
+ ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0);
+
+ if (conf->shcv == NULL) {
+ conf->shcv = prev->shcv;
+ }
}
ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index 0962c8475..aa6a3fcee 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -9,6 +9,10 @@
#include <ngx_core.h>
#include <ngx_http.h>
+#if (NGX_ZLIB)
+#include <zlib.h>
+#endif
+
typedef struct ngx_http_log_op_s ngx_http_log_op_t;
@@ -41,6 +45,17 @@ typedef struct {
typedef struct {
+ u_char *start;
+ u_char *pos;
+ u_char *last;
+
+ ngx_event_t *event;
+ ngx_msec_t flush;
+ ngx_int_t gzip;
+} ngx_http_log_buf_t;
+
+
+typedef struct {
ngx_array_t *lengths;
ngx_array_t *values;
} ngx_http_log_script_t;
@@ -78,6 +93,17 @@ static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
+#if (NGX_ZLIB)
+static ssize_t ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len,
+ ngx_int_t level, ngx_log_t *log);
+
+static void *ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size);
+static void ngx_http_log_gzip_free(void *opaque, void *address);
+#endif
+
+static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
+static void ngx_http_log_flush_handler(ngx_event_t *ev);
+
static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op);
static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
@@ -132,7 +158,7 @@ static ngx_command_t ngx_http_log_commands[] = {
{ ngx_string("access_log"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123,
+ |NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,
ngx_http_log_set_log,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -216,8 +242,8 @@ ngx_http_log_handler(ngx_http_request_t *r)
size_t len;
ngx_uint_t i, l;
ngx_http_log_t *log;
- ngx_open_file_t *file;
ngx_http_log_op_t *op;
+ ngx_http_log_buf_t *buffer;
ngx_http_log_loc_conf_t *lcf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -258,21 +284,25 @@ ngx_http_log_handler(ngx_http_request_t *r)
len += NGX_LINEFEED_SIZE;
- file = log[l].file;
+ buffer = log[l].file ? log[l].file->data : NULL;
- if (file && file->buffer) {
+ if (buffer) {
- if (len > (size_t) (file->last - file->pos)) {
+ if (len > (size_t) (buffer->last - buffer->pos)) {
- ngx_http_log_write(r, &log[l], file->buffer,
- file->pos - file->buffer);
+ ngx_http_log_write(r, &log[l], buffer->start,
+ buffer->pos - buffer->start);
- file->pos = file->buffer;
+ buffer->pos = buffer->start;
}
- if (len <= (size_t) (file->last - file->pos)) {
+ if (len <= (size_t) (buffer->last - buffer->pos)) {
- p = file->pos;
+ p = buffer->pos;
+
+ if (buffer->event && p == buffer->start) {
+ ngx_add_timer(buffer->event, buffer->flush);
+ }
for (i = 0; i < log[l].format->ops->nelts; i++) {
p = op[i].run(r, p, &op[i]);
@@ -280,10 +310,14 @@ ngx_http_log_handler(ngx_http_request_t *r)
ngx_linefeed(p);
- file->pos = p;
+ buffer->pos = p;
continue;
}
+
+ if (buffer->event && buffer->event->timer_set) {
+ ngx_del_timer(buffer->event);
+ }
}
line = ngx_pnalloc(r->pool, len);
@@ -310,14 +344,29 @@ static void
ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
size_t len)
{
- u_char *name;
- time_t now;
- ssize_t n;
- ngx_err_t err;
+ u_char *name;
+ time_t now;
+ ssize_t n;
+ ngx_err_t err;
+#if (NGX_ZLIB)
+ ngx_http_log_buf_t *buffer;
+#endif
if (log->script == NULL) {
name = log->file->name.data;
+
+#if (NGX_ZLIB)
+ buffer = log->file->data;
+
+ if (buffer && buffer->gzip) {
+ n = ngx_http_log_gzip(log->file->fd, buf, len, buffer->gzip,
+ r->connection->log);
+ } else {
+ n = ngx_write_fd(log->file->fd, buf, len);
+ }
+#else
n = ngx_write_fd(log->file->fd, buf, len);
+#endif
} else {
name = NULL;
@@ -465,6 +514,194 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
}
+#if (NGX_ZLIB)
+
+static ssize_t
+ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len, ngx_int_t level,
+ ngx_log_t *log)
+{
+ int rc, wbits, memlevel;
+ u_char *out;
+ size_t size;
+ ssize_t n;
+ z_stream zstream;
+ ngx_err_t err;
+ ngx_pool_t *pool;
+
+ wbits = MAX_WBITS;
+ memlevel = MAX_MEM_LEVEL - 1;
+
+ while ((ssize_t) len < ((1 << (wbits - 1)) - 262)) {
+ wbits--;
+ memlevel--;
+ }
+
+ /*
+ * This is a formula from deflateBound() for conservative upper bound of
+ * compressed data plus 18 bytes of gzip wrapper.
+ */
+
+ size = len + ((len + 7) >> 3) + ((len + 63) >> 6) + 5 + 18;
+
+ ngx_memzero(&zstream, sizeof(z_stream));
+
+ pool = ngx_create_pool(256, log);
+ if (pool == NULL) {
+ /* simulate successful logging */
+ return len;
+ }
+
+ pool->log = log;
+
+ zstream.zalloc = ngx_http_log_gzip_alloc;
+ zstream.zfree = ngx_http_log_gzip_free;
+ zstream.opaque = pool;
+
+ out = ngx_pnalloc(pool, size);
+ if (out == NULL) {
+ goto done;
+ }
+
+ zstream.next_in = buf;
+ zstream.avail_in = len;
+ zstream.next_out = out;
+ zstream.avail_out = size;
+
+ rc = deflateInit2(&zstream, (int) level, Z_DEFLATED, wbits + 16, memlevel,
+ Z_DEFAULT_STRATEGY);
+
+ if (rc != Z_OK) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateInit2() failed: %d", rc);
+ goto done;
+ }
+
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0,
+ "deflate in: ni:%p no:%p ai:%ud ao:%ud",
+ zstream.next_in, zstream.next_out,
+ zstream.avail_in, zstream.avail_out);
+
+ rc = deflate(&zstream, Z_FINISH);
+
+ if (rc != Z_STREAM_END) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "deflate(Z_FINISH) failed: %d", rc);
+ goto done;
+ }
+
+ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, log, 0,
+ "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
+ zstream.next_in, zstream.next_out,
+ zstream.avail_in, zstream.avail_out,
+ rc);
+
+ size -= zstream.avail_out;
+
+ rc = deflateEnd(&zstream);
+
+ if (rc != Z_OK) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateEnd() failed: %d", rc);
+ goto done;
+ }
+
+ n = ngx_write_fd(fd, out, size);
+
+ if (n != (ssize_t) size) {
+ err = (n == -1) ? ngx_errno : 0;
+
+ ngx_destroy_pool(pool);
+
+ ngx_set_errno(err);
+ return -1;
+ }
+
+done:
+
+ ngx_destroy_pool(pool);
+
+ /* simulate successful logging */
+ return len;
+}
+
+
+static void *
+ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size)
+{
+ ngx_pool_t *pool = opaque;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pool->log, 0,
+ "gzip alloc: n:%ud s:%ud", items, size);
+
+ return ngx_palloc(pool, items * size);
+}
+
+
+static void
+ngx_http_log_gzip_free(void *opaque, void *address)
+{
+#if 0
+ ngx_pool_t *pool = opaque;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0, "gzip free: %p", address);
+#endif
+}
+
+#endif
+
+
+static void
+ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log)
+{
+ size_t len;
+ ssize_t n;
+ ngx_http_log_buf_t *buffer;
+
+ buffer = file->data;
+
+ len = buffer->pos - buffer->start;
+
+ if (len == 0) {
+ return;
+ }
+
+#if (NGX_ZLIB)
+ if (buffer->gzip) {
+ n = ngx_http_log_gzip(file->fd, buffer->start, len, buffer->gzip, log);
+ } else {
+ n = ngx_write_fd(file->fd, buffer->start, len);
+ }
+#else
+ n = ngx_write_fd(file->fd, buffer->start, len);
+#endif
+
+ if (n == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_write_fd_n " to \"%s\" failed",
+ file->name.data);
+
+ } else if ((size_t) n != len) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
+ file->name.data, n, len);
+ }
+
+ buffer->pos = buffer->start;
+
+ if (buffer->event && buffer->event->timer_set) {
+ ngx_del_timer(buffer->event);
+ }
+}
+
+
+static void
+ngx_http_log_flush_handler(ngx_event_t *ev)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+ "http log buffer flush handler");
+
+ ngx_http_log_flush(ev->data, ev->log);
+}
+
+
static u_char *
ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op)
@@ -848,10 +1085,13 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_log_loc_conf_t *llcf = conf;
- ssize_t buf;
+ ssize_t size;
+ ngx_int_t gzip;
ngx_uint_t i, n;
- ngx_str_t *value, name;
+ ngx_msec_t flush;
+ ngx_str_t *value, name, s;
ngx_http_log_t *log;
+ ngx_http_log_buf_t *buffer;
ngx_http_log_fmt_t *fmt;
ngx_http_log_main_conf_t *lmcf;
ngx_http_script_compile_t sc;
@@ -936,54 +1176,152 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
&& ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
{
log->format = &fmt[i];
- goto buffer;
+ break;
}
}
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "unknown log format \"%V\"", &name);
- return NGX_CONF_ERROR;
+ if (log->format == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "unknown log format \"%V\"", &name);
+ return NGX_CONF_ERROR;
+ }
+
+ size = 0;
+ flush = 0;
+ gzip = 0;
+
+ for (i = 3; i < cf->args->nelts; i++) {
+
+ if (ngx_strncmp(value[i].data, "buffer=", 7) == 0) {
+ s.len = value[i].len - 7;
+ s.data = value[i].data + 7;
+
+ size = ngx_parse_size(&s);
+
+ if (size == NGX_ERROR || size == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid buffer size \"%V\"", &s);
+ return NGX_CONF_ERROR;
+ }
-buffer:
+ continue;
+ }
+
+ if (ngx_strncmp(value[i].data, "flush=", 6) == 0) {
+ s.len = value[i].len - 6;
+ s.data = value[i].data + 6;
+
+ flush = ngx_parse_time(&s, 0);
+
+ if (flush == (ngx_msec_t) NGX_ERROR || flush == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid flush time \"%V\"", &s);
+ return NGX_CONF_ERROR;
+ }
- if (cf->args->nelts == 4) {
- if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) {
+ continue;
+ }
+
+ if (ngx_strncmp(value[i].data, "gzip", 4) == 0
+ && (value[i].len == 4 || value[i].data[4] == '='))
+ {
+#if (NGX_ZLIB)
+ if (size == 0) {
+ size = 64 * 1024;
+ }
+
+ if (value[i].len == 4) {
+ gzip = Z_BEST_SPEED;
+ continue;
+ }
+
+ s.len = value[i].len - 5;
+ s.data = value[i].data + 5;
+
+ gzip = ngx_atoi(s.data, s.len);
+
+ if (gzip < 1 || gzip > 9) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid compression level \"%V\"", &s);
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+
+#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[3]);
+ "nginx was built without zlib support");
return NGX_CONF_ERROR;
+#endif
}
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter \"%V\"", &value[i]);
+ return NGX_CONF_ERROR;
+ }
+
+ if (flush && size == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "no buffer is defined for access_log \"%V\"",
+ &value[1]);
+ return NGX_CONF_ERROR;
+ }
+
+ if (size) {
+
if (log->script) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"buffered logs cannot have variables in name");
return NGX_CONF_ERROR;
}
- name.len = value[3].len - 7;
- name.data = value[3].data + 7;
+ if (log->file->data) {
+ buffer = log->file->data;
+
+ if (buffer->last - buffer->start != size
+ || buffer->flush != flush
+ || buffer->gzip != gzip)
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "access_log \"%V\" already defined "
+ "with conflicting parameters",
+ &value[1]);
+ return NGX_CONF_ERROR;
+ }
- buf = ngx_parse_size(&name);
+ return NGX_CONF_OK;
+ }
- if (buf == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid buffer value \"%V\"", &name);
+ buffer = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_buf_t));
+ if (buffer == NULL) {
return NGX_CONF_ERROR;
}
- if (log->file->buffer && log->file->last - log->file->pos != buf) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "access_log \"%V\" already defined "
- "with different buffer size", &value[1]);
+ buffer->start = ngx_pnalloc(cf->pool, size);
+ if (buffer->start == NULL) {
return NGX_CONF_ERROR;
}
- log->file->buffer = ngx_palloc(cf->pool, buf);
- if (log->file->buffer == NULL) {
- return NGX_CONF_ERROR;
+ buffer->pos = buffer->start;
+ buffer->last = buffer->start + size;
+
+ if (flush) {
+ buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
+ if (buffer->event == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ buffer->event->data = log->file;
+ buffer->event->handler = ngx_http_log_flush_handler;
+ buffer->event->log = &cf->cycle->new_log;
+
+ buffer->flush = flush;
}
- log->file->pos = log->file->buffer;
- log->file->last = log->file->buffer + buf;
+ buffer->gzip = gzip;
+
+ log->file->flush = ngx_http_log_flush;
+ log->file->data = buffer;
}
return NGX_CONF_OK;
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index 371737b2e..f5ee7673f 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -209,6 +209,13 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
name = value[2];
+
+ if (name.data[0] != '$') {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid variable name \"%V\"", &name);
+ return NGX_CONF_ERROR;
+ }
+
name.len--;
name.data++;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index b1b8f46da..12a54c734 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -837,7 +837,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r)
return NGX_ERROR;
}
- if (plcf->cache_key.value.len) {
+ if (plcf->cache_key.value.data) {
if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) {
return NGX_ERROR;
@@ -1614,7 +1614,8 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
p->upstream_done = 1;
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
- "upstream sent too much data");
+ "upstream sent more data than specified in "
+ "\"Content-Length\" header");
}
return NGX_OK;
@@ -3651,7 +3652,7 @@ ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
- if (plcf->cache_key.value.len) {
+ if (plcf->cache_key.value.data) {
return "is duplicate";
}
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 2c825fa3a..5a3af92f9 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -1771,7 +1771,7 @@ ngx_http_scgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
- if (scf->cache_key.value.len) {
+ if (scf->cache_key.value.data) {
return "is duplicate";
}
diff --git a/src/http/modules/ngx_http_split_clients_module.c b/src/http/modules/ngx_http_split_clients_module.c
index 33a2fe73e..992f6de7c 100644
--- a/src/http/modules/ngx_http_split_clients_module.c
+++ b/src/http/modules/ngx_http_split_clients_module.c
@@ -139,7 +139,7 @@ ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
name = value[2];
- if (name.len < 2 || name.data[0] != '$') {
+ if (name.data[0] != '$') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid variable name \"%V\"", &name);
return NGX_CONF_ERROR;
diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c
index 989adf5ad..6ba57dfff 100644
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -628,7 +628,7 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value;
ngx_http_compile_complex_value_t ccv;
- if (slcf->match.len) {
+ if (slcf->match.data) {
return "is duplicate";
}
@@ -688,7 +688,7 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->once, prev->once, 1);
ngx_conf_merge_str_value(conf->match, prev->match, "");
- if (conf->value.value.len == 0) {
+ if (conf->value.value.data == NULL) {
conf->value = prev->value;
}
diff --git a/src/http/modules/ngx_http_upstream_least_conn_module.c b/src/http/modules/ngx_http_upstream_least_conn_module.c
index 21156ae1a..bd2f1bc9e 100644
--- a/src/http/modules/ngx_http_upstream_least_conn_module.c
+++ b/src/http/modules/ngx_http_upstream_least_conn_module.c
@@ -313,7 +313,9 @@ failed:
lcp->rrp.peers = peers->next;
pc->tries = lcp->rrp.peers->number;
- n = lcp->rrp.peers->number / (8 * sizeof(uintptr_t)) + 1;
+ n = (lcp->rrp.peers->number + (8 * sizeof(uintptr_t) - 1))
+ / (8 * sizeof(uintptr_t));
+
for (i = 0; i < n; i++) {
lcp->rrp.tried[i] = 0;
}
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index ef8994c52..0c6414c6f 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -1807,7 +1807,7 @@ ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
- if (uwcf->cache_key.value.len) {
+ if (uwcf->cache_key.value.data) {
return "is duplicate";
}
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
index 94d1c86cc..a6ae1ce02 100644
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -307,7 +307,7 @@ 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_filter_finalize_request(r, NULL,
+ return ngx_http_filter_finalize_request(r, &ngx_http_xslt_filter_module,
NGX_HTTP_INTERNAL_SERVER_ERROR);
}
@@ -315,7 +315,7 @@ ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
if (cln == NULL) {
ngx_free(b->pos);
- return ngx_http_filter_finalize_request(r, NULL,
+ return ngx_http_filter_finalize_request(r, &ngx_http_xslt_filter_module,
NGX_HTTP_INTERNAL_SERVER_ERROR);
}
diff --git a/src/http/modules/perl/Makefile.PL b/src/http/modules/perl/Makefile.PL
index cfb38c190..78a1e516b 100644
--- a/src/http/modules/perl/Makefile.PL
+++ b/src/http/modules/perl/Makefile.PL
@@ -16,20 +16,9 @@ WriteMakefile(
CCFLAGS => "$ENV{NGX_PM_CFLAGS}",
OPTIMIZE => '-O',
- INC => "-I ../../../../../src/core " .
- "-I ../../../../../src/event " .
- "-I ../../../../../src/os/unix " .
- "-I ../../../../../src/http " .
- "-I ../../../../../src/http/modules " .
- "-I ../../../../../src/http/modules/perl " .
- "-I ../../../../../$ENV{NGX_OBJS} " .
- ($ENV{NGX_PCRE} =~ /^(YES|NO)/ ? "" :
- ($ENV{NGX_PCRE} =~ m#^/# ? "-I $ENV{NGX_PCRE} " :
- "-I ../../../../../$ENV{NGX_PCRE} ")) .
- ($ENV{NGX_OPENSSL} =~ /^(YES|NO)/ ? "" :
- ($ENV{NGX_OPENSSL} =~ m#^/# ?
- "-I $ENV{NGX_OPENSSL}/.openssl/include " :
- "-I ../../../../../$ENV{NGX_OPENSSL}/.openssl/include ")),
+ INC => join(" ", map {
+ m#^/# ? "-I $_" : "-I ../../../../../$_"
+ } (split /\s+/, $ENV{NGX_INCS})),
depend => {
'nginx.c' =>
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 73989c8c3..04f1a968d 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -50,7 +50,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.3.9';
+our $VERSION = '1.3.10';
require XSLoader;
XSLoader::load('nginx', $VERSION);
@@ -123,7 +123,7 @@ This module provides a Perl interface to the nginx HTTP server API.
=head1 SEE ALSO
-http://sysoev.ru/nginx/docs/http/ngx_http_perl_module.html
+http://nginx.org/en/docs/http/ngx_http_perl_module.html
=head1 AUTHOR
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index faecaddc4..27f082ee7 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1001,6 +1001,7 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r,
"client intended to send too large body: %O bytes",
r->headers_in.content_length_n);
+ r->expect_tested = 1;
(void) ngx_http_discard_request_body(r);
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
return NGX_OK;
@@ -4593,7 +4594,7 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_null(&args);
- if (cv.lengths == NULL && uri.data[0] == '/') {
+ if (cv.lengths == NULL && uri.len && uri.data[0] == '/') {
p = (u_char *) ngx_strchr(uri.data, '?');
if (p) {
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index e214519fc..54d019589 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -114,11 +114,6 @@ ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
v = ccv->value;
- if (v->len == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, ccv->cf, 0, "empty parameter");
- return NGX_ERROR;
- }
-
nv = 0;
nc = 0;
@@ -133,8 +128,9 @@ ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
}
}
- if (v->data[0] != '$' && (ccv->conf_prefix || ccv->root_prefix)) {
-
+ if ((v->len == 0 || v->data[0] != '$')
+ && (ccv->conf_prefix || ccv->root_prefix))
+ {
if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
return NGX_ERROR;
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 703017f54..3436c6b1d 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -636,6 +636,14 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
found:
+ if (uscf == NULL) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "no upstream configuration");
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
if (uscf->peer.init(r, uscf) != NGX_OK) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -3091,6 +3099,7 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
r->connection->log->action = "sending to client";
if (rc == 0
+ && !r->header_only
#if (NGX_HTTP_CACHE)
&& !r->cached
#endif
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c
index 4b78cffd8..61dce69cb 100644
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -474,7 +474,9 @@ failed:
rrp->peers = peers->next;
pc->tries = rrp->peers->number;
- n = rrp->peers->number / (8 * sizeof(uintptr_t)) + 1;
+ n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
+ / (8 * sizeof(uintptr_t));
+
for (i = 0; i < n; i++) {
rrp->tried[i] = 0;
}
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index db41964f5..d9f2e9894 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -330,6 +330,12 @@ ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
ngx_http_variable_t *v;
ngx_http_core_main_conf_t *cmcf;
+ if (name->len == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid variable name \"$\"");
+ return NULL;
+ }
+
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
key = cmcf->variables_keys->keys.elts;
@@ -393,6 +399,12 @@ ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
ngx_http_variable_t *v;
ngx_http_core_main_conf_t *cmcf;
+ if (name->len == 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid variable name \"$\"");
+ return NGX_ERROR;
+ }
+
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
v = cmcf->variables.elts;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index fd44bc659..5594c7faa 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -207,7 +207,7 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
if (r->limit_rate) {
- limit = r->limit_rate * (ngx_time() - r->start_sec + 1)
+ limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1)
- (c->sent - clcf->limit_rate_after);
if (limit <= 0) {
diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c
index d2bd4ad61..a8bdc728a 100644
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -1388,7 +1388,6 @@ ngx_mail_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
u.url = value[1];
u.default_port = 80;
u.uri_part = 1;
- u.one_addr = 1;
if (ngx_strncmp(u.url.data, "http://", 7) == 0) {
u.url.len -= 7;
diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c
index 4fdf884fc..c3ae47fdb 100644
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -363,7 +363,7 @@ ngx_open_glob(ngx_glob_t *gl)
{
int n;
- n = glob((char *) gl->pattern, GLOB_NOSORT, NULL, &gl->pglob);
+ n = glob((char *) gl->pattern, 0, NULL, &gl->pglob);
if (n == 0) {
return NGX_OK;
diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c
index 27f990e83..7a71203cb 100644
--- a/src/os/unix/ngx_user.c
+++ b/src/os/unix/ngx_user.c
@@ -28,30 +28,27 @@ ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
{
char *value;
size_t len;
- ngx_err_t err;
struct crypt_data cd;
- ngx_set_errno(0);
-
cd.initialized = 0;
/* work around the glibc bug */
cd.current_salt[0] = ~salt[0];
value = crypt_r((char *) key, (char *) salt, &cd);
- err = ngx_errno;
-
- if (err == 0) {
+ if (value) {
len = ngx_strlen(value) + 1;
*encrypted = ngx_pnalloc(pool, len);
- if (*encrypted) {
- ngx_memcpy(*encrypted, value, len);
- return NGX_OK;
+ if (*encrypted == NULL) {
+ return NGX_ERROR;
}
+
+ ngx_memcpy(*encrypted, value, len);
+ return NGX_OK;
}
- ngx_log_error(NGX_LOG_CRIT, pool->log, err, "crypt_r() failed");
+ ngx_log_error(NGX_LOG_CRIT, pool->log, ngx_errno, "crypt_r() failed");
return NGX_ERROR;
}
@@ -75,18 +72,20 @@ ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
#endif
- ngx_set_errno(0);
-
value = crypt((char *) key, (char *) salt);
if (value) {
len = ngx_strlen(value) + 1;
*encrypted = ngx_pnalloc(pool, len);
- if (*encrypted) {
- ngx_memcpy(*encrypted, value, len);
+ if (*encrypted == NULL) {
+#if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
+ ngx_mutex_unlock(ngx_crypt_mutex);
+#endif
+ return NGX_ERROR;
}
+ ngx_memcpy(*encrypted, value, len);
#if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
ngx_mutex_unlock(ngx_crypt_mutex);
#endif