summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES23
-rw-r--r--CHANGES.ru23
-rw-r--r--auto/lib/perl/conf7
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_connection.c12
-rw-r--r--src/core/ngx_palloc.c10
-rw-r--r--src/core/ngx_slab.c29
-rw-r--r--src/core/ngx_slab.h2
-rw-r--r--src/event/ngx_event_openssl.c227
-rw-r--r--src/event/ngx_event_openssl.h3
-rw-r--r--src/event/ngx_event_pipe.c15
-rw-r--r--src/http/modules/ngx_http_addition_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c2
-rw-r--r--src/http/modules/ngx_http_gunzip_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_gzip_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_not_modified_filter_module.c52
-rw-r--r--src/http/modules/ngx_http_proxy_module.c2
-rw-r--r--src/http/modules/ngx_http_scgi_module.c2
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c5
-rw-r--r--src/http/modules/ngx_http_ssl_module.c37
-rw-r--r--src/http/modules/ngx_http_ssl_module.h2
-rw-r--r--src/http/modules/ngx_http_sub_filter_module.c5
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c2
-rw-r--r--src/http/modules/ngx_http_xslt_filter_module.c6
-rw-r--r--src/http/ngx_http.c4
-rw-r--r--src/http/ngx_http_cache.h8
-rw-r--r--src/http/ngx_http_core_module.c40
-rw-r--r--src/http/ngx_http_core_module.h1
-rw-r--r--src/http/ngx_http_file_cache.c45
-rw-r--r--src/http/ngx_http_request.h1
-rw-r--r--src/http/ngx_http_upstream.c149
-rw-r--r--src/http/ngx_http_upstream.h5
-rw-r--r--src/mail/ngx_mail_ssl_module.c37
-rw-r--r--src/mail/ngx_mail_ssl_module.h2
-rw-r--r--src/os/unix/ngx_darwin_sendfile_chain.c2
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c2
36 files changed, 636 insertions, 136 deletions
diff --git a/CHANGES b/CHANGES
index 7a308e4e2..a4837bd6c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,27 @@
+Changes with nginx 1.7.3 08 Jul 2014
+
+ *) Feature: weak entity tags are now preserved on response
+ modifications, and strong ones are changed to weak.
+
+ *) Feature: cache revalidation now uses If-None-Match header if
+ possible.
+
+ *) Feature: the "ssl_password_file" directive.
+
+ *) Bugfix: the If-None-Match request header line was ignored if there
+ was no Last-Modified header in a response returned from cache.
+
+ *) Bugfix: "peer closed connection in SSL handshake" messages were
+ logged at "info" level instead of "error" while connecting to
+ backends.
+
+ *) Bugfix: in the ngx_http_dav_module module in nginx/Windows.
+
+ *) Bugfix: SPDY connections might be closed prematurely if caching was
+ used.
+
+
Changes with nginx 1.7.2 17 Jun 2014
*) Feature: the "hash" directive inside the "upstream" block.
diff --git a/CHANGES.ru b/CHANGES.ru
index 67ac3f5df..f87375fc5 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,27 @@
+Изменения в nginx 1.7.3 08.07.2014
+
+ *) Добавление: weak entity tags теперь не удаляются при изменениях
+ ответа, а strong entity tags преобразуются в weak.
+
+ *) Добавление: ревалидация элементов кэша теперь, если это возможно,
+ использует заголовок If-None-Match.
+
+ *) Добавление: директива ssl_password_file.
+
+ *) Исправление: при возврате ответа из кэша заголовок запроса
+ If-None-Match игнорировался, если в ответе не было заголовка
+ Last-Modified.
+
+ *) Исправление: сообщения "peer closed connection in SSL handshake" при
+ соединении с бэкендами логгировались на уровне info вместо error.
+
+ *) Исправление: в модуле ngx_http_dav_module в nginx/Windows.
+
+ *) Исправление: SPDY-соединения могли неожиданно закрываться, если
+ использовалось кэширование.
+
+
Изменения в nginx 1.7.2 17.06.2014
*) Добавление: директива hash в блоке upstream.
diff --git a/auto/lib/perl/conf b/auto/lib/perl/conf
index 91009f15e..2a1a3fe3c 100644
--- a/auto/lib/perl/conf
+++ b/auto/lib/perl/conf
@@ -41,6 +41,8 @@ if test -n "$NGX_PERL_VER"; then
ngx_perl_ldopts=`$NGX_PERL -MExtUtils::Embed -e ldopts`
ngx_perl_dlext=`$NGX_PERL -MConfig -e 'print $Config{dlext}'`
+ ngx_perl_libdir="src/http/modules/perl/blib/arch/auto"
+ ngx_perl_module="$ngx_perl_libdir/nginx/nginx.$ngx_perl_dlext"
if $NGX_PERL -V:usemultiplicity | grep define > /dev/null; then
have=NGX_HAVE_PERL_MULTIPLICITY . auto/have
@@ -54,11 +56,12 @@ if test -n "$NGX_PERL_VER"; then
if [ "$NGX_SYSTEM" = "Darwin" ]; then
# OS X system perl wants to link universal binaries
- ngx_perl_ldopts=`echo $ngx_perl_ldopts | sed -e 's/-arch x86_64 -arch i386//'`
+ ngx_perl_ldopts=`echo $ngx_perl_ldopts \
+ | sed -e 's/-arch x86_64 -arch i386//'`
fi
CORE_LINK="$CORE_LINK $ngx_perl_ldopts"
- LINK_DEPS="$LINK_DEPS $NGX_OBJS/src/http/modules/perl/blib/arch/auto/nginx/nginx.$ngx_perl_dlext"
+ LINK_DEPS="$LINK_DEPS $NGX_OBJS/$ngx_perl_module"
if test -n "$NGX_PERL_MODULES"; then
have=NGX_PERL_MODULES value="(u_char *) \"$NGX_PERL_MODULES\""
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 81e351c2a..8d134487a 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1007002
-#define NGINX_VERSION "1.7.2"
+#define nginx_version 1007003
+#define NGINX_VERSION "1.7.3"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 6b6e3b3a5..4c42ffc0d 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -411,13 +411,11 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
err = ngx_socket_errno;
- if (err == NGX_EADDRINUSE && ngx_test_config) {
- continue;
+ if (err != NGX_EADDRINUSE || !ngx_test_config) {
+ ngx_log_error(NGX_LOG_EMERG, log, err,
+ "bind() to %V failed", &ls[i].addr_text);
}
- ngx_log_error(NGX_LOG_EMERG, log, err,
- "bind() to %V failed", &ls[i].addr_text);
-
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
@@ -428,7 +426,9 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
return NGX_ERROR;
}
- failed = 1;
+ if (!ngx_test_config) {
+ failed = 1;
+ }
continue;
}
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 1f70f9eee..ef4a64771 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -181,7 +181,7 @@ ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
u_char *m;
size_t psize;
- ngx_pool_t *p, *new, *current;
+ ngx_pool_t *p, *new;
psize = (size_t) (pool->d.end - (u_char *) pool);
@@ -200,18 +200,14 @@ ngx_palloc_block(ngx_pool_t *pool, size_t size)
m = ngx_align_ptr(m, NGX_ALIGNMENT);
new->d.last = m + size;
- current = pool->current;
-
- for (p = current; p->d.next; p = p->d.next) {
+ for (p = pool->current; p->d.next; p = p->d.next) {
if (p->d.failed++ > 4) {
- current = p->d.next;
+ pool->current = p->d.next;
}
}
p->d.next = new;
- pool->current = current ? current : new;
-
return m;
}
diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c
index be3e54084..24f2ff16a 100644
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -398,6 +398,35 @@ done:
}
+void *
+ngx_slab_calloc(ngx_slab_pool_t *pool, size_t size)
+{
+ void *p;
+
+ ngx_shmtx_lock(&pool->mutex);
+
+ p = ngx_slab_calloc_locked(pool, size);
+
+ ngx_shmtx_unlock(&pool->mutex);
+
+ return p;
+}
+
+
+void *
+ngx_slab_calloc_locked(ngx_slab_pool_t *pool, size_t size)
+{
+ void *p;
+
+ p = ngx_slab_alloc_locked(pool, size);
+ if (p) {
+ ngx_memzero(p, size);
+ }
+
+ return p;
+}
+
+
void
ngx_slab_free(ngx_slab_pool_t *pool, void *p)
{
diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h
index 1ee65d531..2922a80c7 100644
--- a/src/core/ngx_slab.h
+++ b/src/core/ngx_slab.h
@@ -50,6 +50,8 @@ typedef struct {
void ngx_slab_init(ngx_slab_pool_t *pool);
void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size);
void *ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size);
+void *ngx_slab_calloc(ngx_slab_pool_t *pool, size_t size);
+void *ngx_slab_calloc_locked(ngx_slab_pool_t *pool, size_t size);
void ngx_slab_free(ngx_slab_pool_t *pool, void *p);
void ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p);
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 0c5ecda98..50691ade7 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -10,14 +10,20 @@
#include <ngx_event.h>
+#define NGX_SSL_PASSWORD_BUFFER_SIZE 4096
+
+
typedef struct {
ngx_uint_t engine; /* unsigned engine:1; */
} ngx_openssl_conf_t;
+static int ngx_ssl_password_callback(char *buf, int size, int rwflag,
+ void *userdata);
static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
int ret);
+static void ngx_ssl_passwords_cleanup(void *data);
static void ngx_ssl_handshake_handler(ngx_event_t *ev);
static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
static void ngx_ssl_write_handler(ngx_event_t *wev);
@@ -257,11 +263,13 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
ngx_int_t
ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
- ngx_str_t *key)
+ ngx_str_t *key, ngx_array_t *passwords)
{
- BIO *bio;
- X509 *x509;
- u_long n;
+ BIO *bio;
+ X509 *x509;
+ u_long n;
+ ngx_str_t *pwd;
+ ngx_uint_t tries;
if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
return NGX_ERROR;
@@ -348,19 +356,76 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
return NGX_ERROR;
}
- if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
- SSL_FILETYPE_PEM)
- == 0)
- {
+ if (passwords) {
+ tries = passwords->nelts;
+ pwd = passwords->elts;
+
+ SSL_CTX_set_default_passwd_cb(ssl->ctx, ngx_ssl_password_callback);
+ SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, pwd);
+
+ } else {
+ tries = 1;
+#if (NGX_SUPPRESS_WARN)
+ pwd = NULL;
+#endif
+ }
+
+ for ( ;; ) {
+
+ if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key->data,
+ SSL_FILETYPE_PEM)
+ != 0)
+ {
+ break;
+ }
+
+ if (--tries) {
+ n = ERR_peek_error();
+
+ if (ERR_GET_LIB(n) == ERR_LIB_EVP
+ && ERR_GET_REASON(n) == EVP_R_BAD_DECRYPT)
+ {
+ ERR_clear_error();
+ SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ++pwd);
+ continue;
+ }
+ }
+
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_use_PrivateKey_file(\"%s\") failed", key->data);
return NGX_ERROR;
}
+ SSL_CTX_set_default_passwd_cb(ssl->ctx, NULL);
+
return NGX_OK;
}
+static int
+ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata)
+{
+ ngx_str_t *pwd = userdata;
+
+ if (rwflag) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+ "ngx_ssl_password_callback() is called for encryption");
+ return 0;
+ }
+
+ if (pwd->len > (size_t) size) {
+ ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
+ "password is truncated to %d bytes", size);
+ } else {
+ size = pwd->len;
+ }
+
+ ngx_memcpy(buf, pwd->data, size);
+
+ return size;
+}
+
+
ngx_int_t
ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
ngx_int_t depth)
@@ -597,6 +662,148 @@ ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
}
+ngx_array_t *
+ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file)
+{
+ u_char *p, *last, *end;
+ size_t len;
+ ssize_t n;
+ ngx_fd_t fd;
+ ngx_str_t *pwd;
+ ngx_array_t *passwords;
+ ngx_pool_cleanup_t *cln;
+ u_char buf[NGX_SSL_PASSWORD_BUFFER_SIZE];
+
+ if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
+ return NULL;
+ }
+
+ cln = ngx_pool_cleanup_add(cf->temp_pool, 0);
+ passwords = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t));
+
+ if (cln == NULL || passwords == NULL) {
+ return NULL;
+ }
+
+ cln->handler = ngx_ssl_passwords_cleanup;
+ cln->data = passwords;
+
+ fd = ngx_open_file(file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+ if (fd == NGX_INVALID_FILE) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
+ ngx_open_file_n " \"%s\" failed", file->data);
+ return NULL;
+ }
+
+ len = 0;
+ last = buf;
+
+ do {
+ n = ngx_read_fd(fd, last, NGX_SSL_PASSWORD_BUFFER_SIZE - len);
+
+ if (n == -1) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
+ ngx_read_fd_n " \"%s\" failed", file->data);
+ passwords = NULL;
+ goto cleanup;
+ }
+
+ end = last + n;
+
+ if (len && n == 0) {
+ *end++ = LF;
+ }
+
+ p = buf;
+
+ for ( ;; ) {
+ last = ngx_strlchr(last, end, LF);
+
+ if (last == NULL) {
+ break;
+ }
+
+ len = last++ - p;
+
+ if (len && p[len - 1] == CR) {
+ len--;
+ }
+
+ if (len) {
+ pwd = ngx_array_push(passwords);
+ if (pwd == NULL) {
+ passwords = NULL;
+ goto cleanup;
+ }
+
+ pwd->len = len;
+ pwd->data = ngx_pnalloc(cf->temp_pool, len);
+
+ if (pwd->data == NULL) {
+ passwords->nelts--;
+ passwords = NULL;
+ goto cleanup;
+ }
+
+ ngx_memcpy(pwd->data, p, len);
+ }
+
+ p = last;
+ }
+
+ len = end - p;
+
+ if (len == NGX_SSL_PASSWORD_BUFFER_SIZE) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "too long line in \"%s\"", file->data);
+ passwords = NULL;
+ goto cleanup;
+ }
+
+ ngx_memmove(buf, p, len);
+ last = buf + len;
+
+ } while (n != 0);
+
+ if (passwords->nelts == 0) {
+ pwd = ngx_array_push(passwords);
+ if (pwd == NULL) {
+ passwords = NULL;
+ goto cleanup;
+ }
+
+ ngx_memzero(pwd, sizeof(ngx_str_t));
+ }
+
+cleanup:
+
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+ ngx_conf_log_error(NGX_LOG_ALERT, cf, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", file->data);
+ }
+
+ ngx_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE);
+
+ return passwords;
+}
+
+
+static void
+ngx_ssl_passwords_cleanup(void *data)
+{
+ ngx_array_t *passwords = data;
+
+ ngx_str_t *pwd;
+ ngx_uint_t i;
+
+ pwd = passwords->elts;
+
+ for (i = 0; i < passwords->nelts; i++) {
+ ngx_memzero(pwd[i].data, pwd[i].len);
+ }
+}
+
+
ngx_int_t
ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
{
@@ -905,8 +1112,8 @@ ngx_ssl_handshake(ngx_connection_t *c)
c->read->eof = 1;
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
- ngx_log_error(NGX_LOG_INFO, c->log, err,
- "peer closed connection in SSL handshake");
+ ngx_connection_error(c, err,
+ "peer closed connection in SSL handshake");
return NGX_ERROR;
}
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index d632eb274..0194602f6 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -112,7 +112,7 @@ typedef struct {
ngx_int_t ngx_ssl_init(ngx_log_t *log);
ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data);
ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
- ngx_str_t *cert, ngx_str_t *key);
+ ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords);
ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_str_t *cert, ngx_int_t depth);
ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
@@ -124,6 +124,7 @@ ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
int key_length);
+ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file);
ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file);
ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name);
ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx,
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index eed807d61..64fb07bde 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -439,7 +439,11 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
}
}
- if (p->cacheable && p->in) {
+ if (p->cacheable && (p->in || p->buf_to_file)) {
+
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
+ "pipe write chain");
+
if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) {
return NGX_ABORT;
}
@@ -515,15 +519,6 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
p->in = NULL;
}
- if (p->cacheable && p->buf_to_file) {
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
- "pipe write chain");
-
- if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) {
- return NGX_ABORT;
- }
- }
-
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
"pipe write downstream done");
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
index f598ceab3..db4970bf1 100644
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -121,7 +121,7 @@ ngx_http_addition_header_filter(ngx_http_request_t *r)
ngx_http_clear_content_length(r);
ngx_http_clear_accept_ranges(r);
- ngx_http_clear_etag(r);
+ ngx_http_weak_etag(r);
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 80cd1a220..8016f5b75 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -573,7 +573,7 @@ static ngx_keyval_t ngx_http_fastcgi_cache_headers[] = {
{ ngx_string("HTTP_IF_MODIFIED_SINCE"),
ngx_string("$upstream_cache_last_modified") },
{ ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
- { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
+ { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
{ ngx_string("HTTP_IF_MATCH"), ngx_string("") },
{ ngx_string("HTTP_RANGE"), ngx_string("") },
{ ngx_string("HTTP_IF_RANGE"), ngx_string("") },
diff --git a/src/http/modules/ngx_http_gunzip_filter_module.c b/src/http/modules/ngx_http_gunzip_filter_module.c
index adadc9da6..70ec0aace 100644
--- a/src/http/modules/ngx_http_gunzip_filter_module.c
+++ b/src/http/modules/ngx_http_gunzip_filter_module.c
@@ -165,7 +165,7 @@ ngx_http_gunzip_header_filter(ngx_http_request_t *r)
ngx_http_clear_content_length(r);
ngx_http_clear_accept_ranges(r);
- ngx_http_clear_etag(r);
+ ngx_http_weak_etag(r);
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index ea1f1d0b9..c57a4a3c7 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -306,7 +306,7 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
ngx_http_clear_content_length(r);
ngx_http_clear_accept_ranges(r);
- ngx_http_clear_etag(r);
+ ngx_http_weak_etag(r);
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_not_modified_filter_module.c b/src/http/modules/ngx_http_not_modified_filter_module.c
index 7f1ab6236..acc94ded3 100644
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -13,7 +13,7 @@
static ngx_uint_t ngx_http_test_if_unmodified(ngx_http_request_t *r);
static ngx_uint_t ngx_http_test_if_modified(ngx_http_request_t *r);
static ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
- ngx_table_elt_t *header);
+ ngx_table_elt_t *header, ngx_uint_t weak);
static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
@@ -56,7 +56,7 @@ ngx_http_not_modified_header_filter(ngx_http_request_t *r)
{
if (r->headers_out.status != NGX_HTTP_OK
|| r != r->main
- || r->headers_out.last_modified_time == -1)
+ || r->disable_not_modified)
{
return ngx_http_next_header_filter(r);
}
@@ -69,7 +69,7 @@ ngx_http_not_modified_header_filter(ngx_http_request_t *r)
}
if (r->headers_in.if_match
- && !ngx_http_test_if_match(r, r->headers_in.if_match))
+ && !ngx_http_test_if_match(r, r->headers_in.if_match, 0))
{
return ngx_http_filter_finalize_request(r, NULL,
NGX_HTTP_PRECONDITION_FAILED);
@@ -84,7 +84,7 @@ ngx_http_not_modified_header_filter(ngx_http_request_t *r)
}
if (r->headers_in.if_none_match
- && !ngx_http_test_if_match(r, r->headers_in.if_none_match))
+ && !ngx_http_test_if_match(r, r->headers_in.if_none_match, 1))
{
return ngx_http_next_header_filter(r);
}
@@ -114,11 +114,15 @@ ngx_http_test_if_unmodified(ngx_http_request_t *r)
{
time_t iums;
+ if (r->headers_out.last_modified_time == (time_t) -1) {
+ return 0;
+ }
+
iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data,
r->headers_in.if_unmodified_since->value.len);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http iums:%d lm:%d", iums, r->headers_out.last_modified_time);
+ "http iums:%T lm:%T", iums, r->headers_out.last_modified_time);
if (iums >= r->headers_out.last_modified_time) {
return 1;
@@ -134,6 +138,10 @@ ngx_http_test_if_modified(ngx_http_request_t *r)
time_t ims;
ngx_http_core_loc_conf_t *clcf;
+ if (r->headers_out.last_modified_time == (time_t) -1) {
+ return 1;
+ }
+
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
@@ -144,7 +152,7 @@ ngx_http_test_if_modified(ngx_http_request_t *r)
r->headers_in.if_modified_since->value.len);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ims:%d lm:%d", ims, r->headers_out.last_modified_time);
+ "http ims:%T lm:%T", ims, r->headers_out.last_modified_time);
if (ims == r->headers_out.last_modified_time) {
return 0;
@@ -161,10 +169,11 @@ ngx_http_test_if_modified(ngx_http_request_t *r)
static ngx_uint_t
-ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
+ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header,
+ ngx_uint_t weak)
{
u_char *start, *end, ch;
- ngx_str_t *etag, *list;
+ ngx_str_t etag, *list;
list = &header->value;
@@ -176,25 +185,42 @@ ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
return 0;
}
- etag = &r->headers_out.etag->value;
+ etag = r->headers_out.etag->value;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http im:\"%V\" etag:%V", list, etag);
+ "http im:\"%V\" etag:%V", list, &etag);
+
+ if (weak
+ && etag.len > 2
+ && etag.data[0] == 'W'
+ && etag.data[1] == '/')
+ {
+ etag.len -= 2;
+ etag.data += 2;
+ }
start = list->data;
end = list->data + list->len;
while (start < end) {
- if (etag->len > (size_t) (end - start)) {
+ if (weak
+ && end - start > 2
+ && start[0] == 'W'
+ && start[1] == '/')
+ {
+ start += 2;
+ }
+
+ if (etag.len > (size_t) (end - start)) {
return 0;
}
- if (ngx_strncmp(start, etag->data, etag->len) != 0) {
+ if (ngx_strncmp(start, etag.data, etag.len) != 0) {
goto skip;
}
- start += etag->len;
+ start += etag.len;
while (start < end) {
ch = *start;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 61af3dfd3..52c63e138 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -677,7 +677,7 @@ static ngx_keyval_t ngx_http_proxy_cache_headers[] = {
{ ngx_string("If-Modified-Since"),
ngx_string("$upstream_cache_last_modified") },
{ ngx_string("If-Unmodified-Since"), ngx_string("") },
- { ngx_string("If-None-Match"), ngx_string("") },
+ { ngx_string("If-None-Match"), ngx_string("$upstream_cache_etag") },
{ ngx_string("If-Match"), ngx_string("") },
{ ngx_string("Range"), ngx_string("") },
{ ngx_string("If-Range"), ngx_string("") },
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 884cb500a..d3a8f11b6 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -379,7 +379,7 @@ static ngx_keyval_t ngx_http_scgi_cache_headers[] = {
{ ngx_string("HTTP_IF_MODIFIED_SINCE"),
ngx_string("$upstream_cache_last_modified") },
{ ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
- { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
+ { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
{ ngx_string("HTTP_IF_MATCH"), ngx_string("") },
{ ngx_string("HTTP_RANGE"), ngx_string("") },
{ ngx_string("HTTP_IF_RANGE"), ngx_string("") },
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index aeb1376b7..8236320c2 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -369,10 +369,13 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
if (r == r->main) {
ngx_http_clear_content_length(r);
ngx_http_clear_accept_ranges(r);
- ngx_http_clear_etag(r);
if (!slcf->last_modified) {
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
+
+ } else {
+ ngx_http_weak_etag(r);
}
}
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index 730204cbb..4c69091d6 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -43,6 +43,8 @@ static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -91,6 +93,13 @@ static ngx_command_t ngx_http_ssl_commands[] = {
offsetof(ngx_http_ssl_srv_conf_t, certificate_key),
NULL },
+ { ngx_string("ssl_password_file"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_http_ssl_password_file,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("ssl_dhparam"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
@@ -514,6 +523,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
sscf->buffer_size = NGX_CONF_UNSET_SIZE;
sscf->verify = NGX_CONF_UNSET_UINT;
sscf->verify_depth = NGX_CONF_UNSET_UINT;
+ sscf->passwords = NGX_CONF_UNSET_PTR;
sscf->builtin_session_cache = NGX_CONF_UNSET;
sscf->session_timeout = NGX_CONF_UNSET;
sscf->session_tickets = NGX_CONF_UNSET;
@@ -563,6 +573,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, "");
+ ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
+
ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
@@ -652,7 +664,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
cln->data = &conf->ssl;
if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
- &conf->certificate_key)
+ &conf->certificate_key, conf->passwords)
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -782,6 +794,29 @@ ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
+ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_ssl_srv_conf_t *sscf = conf;
+
+ ngx_str_t *value;
+
+ if (sscf->passwords != NGX_CONF_UNSET_PTR) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ sscf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
+
+ if (sscf->passwords == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_ssl_srv_conf_t *sscf = conf;
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
index ec2c62f6f..8e69e9e4d 100644
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -42,6 +42,8 @@ typedef struct {
ngx_str_t ciphers;
+ ngx_array_t *passwords;
+
ngx_shm_zone_t *shm_zone;
ngx_flag_t session_tickets;
diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c
index 3ba59d627..5e6e038bf 100644
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -175,10 +175,13 @@ ngx_http_sub_header_filter(ngx_http_request_t *r)
if (r == r->main) {
ngx_http_clear_content_length(r);
- ngx_http_clear_etag(r);
if (!slcf->last_modified) {
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
+
+ } else {
+ ngx_http_weak_etag(r);
}
}
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 1d515cdf5..588b13547 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -507,7 +507,7 @@ static ngx_keyval_t ngx_http_uwsgi_cache_headers[] = {
{ ngx_string("HTTP_IF_MODIFIED_SINCE"),
ngx_string("$upstream_cache_last_modified") },
{ ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
- { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
+ { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
{ ngx_string("HTTP_IF_MATCH"), ngx_string("") },
{ ngx_string("HTTP_RANGE"), ngx_string("") },
{ ngx_string("HTTP_IF_RANGE"), ngx_string("") },
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
index 9e85693bc..315081e47 100644
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -337,12 +337,14 @@ ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
r->headers_out.content_length = NULL;
}
- ngx_http_clear_etag(r);
-
conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
if (!conf->last_modified) {
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
+
+ } else {
+ ngx_http_weak_etag(r);
}
}
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index ce5adb737..31577f9a2 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -742,7 +742,7 @@ ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
if (named) {
clcfp = ngx_palloc(cf->pool,
- (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
+ (n + 1) * sizeof(ngx_http_core_loc_conf_t *));
if (clcfp == NULL) {
return NGX_ERROR;
}
@@ -768,7 +768,7 @@ ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
if (regex) {
clcfp = ngx_palloc(cf->pool,
- (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
+ (r + 1) * sizeof(ngx_http_core_loc_conf_t *));
if (clcfp == NULL) {
return NGX_ERROR;
}
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index 193a35322..1cfd9fe84 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -24,6 +24,9 @@
#define NGX_HTTP_CACHE_SCARCE 8
#define NGX_HTTP_CACHE_KEY_LEN 16
+#define NGX_HTTP_CACHE_ETAG_LEN 42
+
+#define NGX_HTTP_CACHE_VERSION 2
typedef struct {
@@ -67,6 +70,8 @@ struct ngx_http_cache_s {
time_t last_modified;
time_t date;
+ ngx_str_t etag;
+
size_t header_start;
size_t body_start;
off_t length;
@@ -97,6 +102,7 @@ struct ngx_http_cache_s {
typedef struct {
+ ngx_uint_t version;
time_t valid_sec;
time_t last_modified;
time_t date;
@@ -104,6 +110,8 @@ typedef struct {
u_short valid_msec;
u_short header_start;
u_short body_start;
+ u_char etag_len;
+ u_char etag[NGX_HTTP_CACHE_ETAG_LEN];
} ngx_http_file_cache_header_t;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index fb02dd465..2947ad32a 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1851,6 +1851,46 @@ ngx_http_set_etag(ngx_http_request_t *r)
}
+void
+ngx_http_weak_etag(ngx_http_request_t *r)
+{
+ size_t len;
+ u_char *p;
+ ngx_table_elt_t *etag;
+
+ etag = r->headers_out.etag;
+
+ if (etag == NULL) {
+ return;
+ }
+
+ if (etag->value.len > 2
+ && etag->value.data[0] == 'W'
+ && etag->value.data[1] == '/')
+ {
+ return;
+ }
+
+ if (etag->value.len < 1 || etag->value.data[0] != '"') {
+ r->headers_out.etag->hash = 0;
+ r->headers_out.etag = NULL;
+ return;
+ }
+
+ p = ngx_pnalloc(r->pool, etag->value.len + 2);
+ if (p == NULL) {
+ r->headers_out.etag->hash = 0;
+ r->headers_out.etag = NULL;
+ return;
+ }
+
+ len = ngx_sprintf(p, "W/%V", &etag->value) - p;
+
+ etag->value.data = p;
+ etag->value.len = len;
+}
+
+
ngx_int_t
ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
ngx_str_t *ct, ngx_http_complex_value_t *cv)
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 799d2fe0d..285120de7 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -501,6 +501,7 @@ void *ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash);
ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
void ngx_http_set_exten(ngx_http_request_t *r);
ngx_int_t ngx_http_set_etag(ngx_http_request_t *r);
+void ngx_http_weak_etag(ngx_http_request_t *r);
ngx_int_t ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
ngx_str_t *ct, ngx_http_complex_value_t *cv);
u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index 49abdb400..71e6e36c2 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -498,6 +498,12 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c)
h = (ngx_http_file_cache_header_t *) c->buf->pos;
+ if (h->version != NGX_HTTP_CACHE_VERSION) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "cache file \"%s\" version mismatch", c->file.name.data);
+ return NGX_DECLINED;
+ }
+
if (h->crc32 != c->crc32) {
ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
"cache file \"%s\" has md5 collision", c->file.name.data);
@@ -519,6 +525,8 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c)
c->valid_msec = h->valid_msec;
c->header_start = h->header_start;
c->body_start = h->body_start;
+ c->etag.len = h->etag_len;
+ c->etag.data = h->etag;
r->cached = 1;
@@ -678,8 +686,8 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
goto done;
}
- fcn = ngx_slab_alloc_locked(cache->shpool,
- sizeof(ngx_http_file_cache_node_t));
+ fcn = ngx_slab_calloc_locked(cache->shpool,
+ sizeof(ngx_http_file_cache_node_t));
if (fcn == NULL) {
ngx_shmtx_unlock(&cache->shpool->mutex);
@@ -687,8 +695,8 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
ngx_shmtx_lock(&cache->shpool->mutex);
- fcn = ngx_slab_alloc_locked(cache->shpool,
- sizeof(ngx_http_file_cache_node_t));
+ fcn = ngx_slab_calloc_locked(cache->shpool,
+ sizeof(ngx_http_file_cache_node_t));
if (fcn == NULL) {
rc = NGX_ERROR;
goto failed;
@@ -704,8 +712,6 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
fcn->uses = 1;
fcn->count = 1;
- fcn->updating = 0;
- fcn->deleting = 0;
renew:
@@ -877,6 +883,7 @@ ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf)
ngx_memzero(h, sizeof(ngx_http_file_cache_header_t));
+ h->version = NGX_HTTP_CACHE_VERSION;
h->valid_sec = c->valid_sec;
h->last_modified = c->last_modified;
h->date = c->date;
@@ -885,6 +892,11 @@ ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf)
h->header_start = (u_short) c->header_start;
h->body_start = (u_short) c->body_start;
+ if (c->etag.len <= NGX_HTTP_CACHE_ETAG_LEN) {
+ h->etag_len = (u_char) c->etag.len;
+ ngx_memcpy(h->etag, c->etag.data, c->etag.len);
+ }
+
p = buf + sizeof(ngx_http_file_cache_header_t);
p = ngx_cpymem(p, ngx_http_file_cache_key, sizeof(ngx_http_file_cache_key));
@@ -1044,7 +1056,8 @@ ngx_http_file_cache_update_header(ngx_http_request_t *r)
goto done;
}
- if (h.last_modified != c->last_modified
+ if (h.version != NGX_HTTP_CACHE_VERSION
+ || h.last_modified != c->last_modified
|| h.crc32 != c->crc32
|| h.header_start != c->header_start
|| h.body_start != c->body_start)
@@ -1062,6 +1075,7 @@ ngx_http_file_cache_update_header(ngx_http_request_t *r)
ngx_memzero(&h, sizeof(ngx_http_file_cache_header_t));
+ h.version = NGX_HTTP_CACHE_VERSION;
h.valid_sec = c->valid_sec;
h.last_modified = c->last_modified;
h.date = c->date;
@@ -1070,6 +1084,11 @@ ngx_http_file_cache_update_header(ngx_http_request_t *r)
h.header_start = (u_short) c->header_start;
h.body_start = (u_short) c->body_start;
+ if (c->etag.len <= NGX_HTTP_CACHE_ETAG_LEN) {
+ h.etag_len = (u_char) c->etag.len;
+ ngx_memcpy(h.etag, c->etag.data, c->etag.len);
+ }
+
(void) ngx_write_file(&file, (u_char *) &h,
sizeof(ngx_http_file_cache_header_t), 0);
@@ -1618,8 +1637,8 @@ ngx_http_file_cache_add(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
if (fcn == NULL) {
- fcn = ngx_slab_alloc_locked(cache->shpool,
- sizeof(ngx_http_file_cache_node_t));
+ fcn = ngx_slab_calloc_locked(cache->shpool,
+ sizeof(ngx_http_file_cache_node_t));
if (fcn == NULL) {
ngx_shmtx_unlock(&cache->shpool->mutex);
return NGX_ERROR;
@@ -1633,15 +1652,7 @@ ngx_http_file_cache_add(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
fcn->uses = 1;
- fcn->count = 0;
- fcn->valid_msec = 0;
- fcn->error = 0;
fcn->exists = 1;
- fcn->updating = 0;
- fcn->deleting = 0;
- fcn->uniq = 0;
- fcn->valid_sec = 0;
- fcn->body_start = 0;
fcn->fs_size = c->fs_size;
cache->sh->size += c->fs_size;
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 0d3a79915..f6ea6fb56 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -528,6 +528,7 @@ struct ngx_http_request_s {
unsigned filter_need_temporary:1;
unsigned allow_ranges:1;
unsigned single_range:1;
+ unsigned disable_not_modified:1;
#if (NGX_STAT_STUB)
unsigned stat_reading:1;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 8b6d3f69f..012969170 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -19,6 +19,8 @@ static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_upstream_cache_etag(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
#endif
static void ngx_http_upstream_init_request(ngx_http_request_t *r);
@@ -87,6 +89,8 @@ static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t
@@ -174,8 +178,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
ngx_http_upstream_copy_content_type, 0, 1 },
{ ngx_string("Content-Length"),
- ngx_http_upstream_process_content_length,
- offsetof(ngx_http_upstream_headers_in_t, content_length),
+ ngx_http_upstream_process_content_length, 0,
ngx_http_upstream_ignore_header_line, 0, 0 },
{ ngx_string("Date"),
@@ -185,8 +188,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
offsetof(ngx_http_headers_out_t, date), 0 },
{ ngx_string("Last-Modified"),
- ngx_http_upstream_process_header_line,
- offsetof(ngx_http_upstream_headers_in_t, last_modified),
+ ngx_http_upstream_process_last_modified, 0,
ngx_http_upstream_copy_last_modified, 0, 0 },
{ ngx_string("ETag"),
@@ -367,6 +369,10 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = {
ngx_http_upstream_cache_last_modified, 0,
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
+ { ngx_string("upstream_cache_etag"), NULL,
+ ngx_http_upstream_cache_etag, 0,
+ NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
+
#endif
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
@@ -1668,13 +1674,6 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
}
- ngx_add_timer(c->read, u->conf->read_timeout);
-
- if (c->read->ready) {
- ngx_http_upstream_process_header(r, u);
- return;
- }
-
u->write_event_handler = ngx_http_upstream_dummy_handler;
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
@@ -1682,6 +1681,13 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
+
+ ngx_add_timer(c->read, u->conf->read_timeout);
+
+ if (c->read->ready) {
+ ngx_http_upstream_process_header(r, u);
+ return;
+ }
}
@@ -2238,6 +2244,8 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
r->headers_out.content_length_n = u->headers_in.content_length_n;
+ r->disable_not_modified = !u->cacheable;
+
u->length = -1;
return NGX_OK;
@@ -2349,21 +2357,17 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (r->header_only) {
- if (u->cacheable || u->store) {
-
- if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
- ngx_connection_error(c, ngx_socket_errno,
- ngx_shutdown_socket_n " failed");
- }
-
- r->read_event_handler = ngx_http_request_empty_handler;
- r->write_event_handler = ngx_http_request_empty_handler;
- c->error = 1;
+ if (!u->buffering) {
+ ngx_http_upstream_finalize_request(r, u, rc);
+ return;
+ }
- } else {
+ if (!u->cacheable && !u->store) {
ngx_http_upstream_finalize_request(r, u, rc);
return;
}
+
+ u->pipe->downstream_error = 1;
}
if (r->request_body && r->request_body->temp_file) {
@@ -2492,15 +2496,18 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
if (valid) {
- r->cache->last_modified = r->headers_out.last_modified_time;
+ r->cache->last_modified = u->headers_in.last_modified_time;
r->cache->date = now;
r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
+ if (u->headers_in.etag) {
+ r->cache->etag = u->headers_in.etag->value;
+ }
+
ngx_http_file_cache_set_header(r, u->buffer.start);
} else {
u->cacheable = 0;
- r->headers_out.last_modified_time = -1;
}
}
@@ -3730,6 +3737,29 @@ ngx_http_upstream_process_content_length(ngx_http_request_t *r,
static ngx_int_t
+ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset)
+{
+ ngx_http_upstream_t *u;
+
+ u = r->upstream;
+
+ u->headers_in.last_modified = h;
+
+#if (NGX_HTTP_CACHE)
+
+ if (u->cacheable) {
+ u->headers_in.last_modified_time = ngx_http_parse_time(h->value.data,
+ h->value.len);
+ }
+
+#endif
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
@@ -4185,8 +4215,8 @@ ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
#if (NGX_HTTP_CACHE)
if (r->upstream->cacheable) {
- r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
- h->value.len);
+ r->headers_out.last_modified_time =
+ r->upstream->headers_in.last_modified_time;
}
#endif
@@ -4764,6 +4794,29 @@ ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
return NGX_OK;
}
+
+static ngx_int_t
+ngx_http_upstream_cache_etag(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ if (r->upstream == NULL
+ || !r->upstream->conf->cache_revalidate
+ || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED
+ || r->cache->etag.len == 0)
+ {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->len = r->cache->etag.len;
+ v->data = r->cache->etag.data;
+
+ return NGX_OK;
+}
+
#endif
@@ -4851,6 +4904,12 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
}
}
+ uscf->servers = ngx_array_create(cf->pool, 4,
+ sizeof(ngx_http_upstream_server_t));
+ if (uscf->servers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
/* parse inside upstream{} */
@@ -4866,7 +4925,7 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
return rv;
}
- if (uscf->servers == NULL) {
+ if (uscf->servers->nelts == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"no servers are inside upstream");
return NGX_CONF_ERROR;
@@ -4888,14 +4947,6 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_uint_t i;
ngx_http_upstream_server_t *us;
- if (uscf->servers == NULL) {
- uscf->servers = ngx_array_create(cf->pool, 4,
- sizeof(ngx_http_upstream_server_t));
- if (uscf->servers == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
us = ngx_array_push(uscf->servers);
if (us == NULL) {
return NGX_CONF_ERROR;
@@ -4905,20 +4956,6 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
- ngx_memzero(&u, sizeof(ngx_url_t));
-
- u.url = value[1];
- u.default_port = 80;
-
- if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
- if (u.err) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%s in upstream \"%V\"", u.err, &u.url);
- }
-
- return NGX_CONF_ERROR;
- }
-
weight = 1;
max_fails = 1;
fail_timeout = 10;
@@ -4998,6 +5035,20 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
goto invalid;
}
+ ngx_memzero(&u, sizeof(ngx_url_t));
+
+ u.url = value[1];
+ u.default_port = 80;
+
+ if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
+ if (u.err) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "%s in upstream \"%V\"", u.err, &u.url);
+ }
+
+ return NGX_CONF_ERROR;
+ }
+
us->name = u.url;
us->addrs = u.addrs;
us->naddrs = u.naddrs;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 3128ccef0..dafb5a319 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -246,11 +246,12 @@ typedef struct {
ngx_table_elt_t *content_encoding;
#endif
- off_t content_length_n;
-
ngx_array_t cache_control;
ngx_array_t cookies;
+ off_t content_length_n;
+ time_t last_modified_time;
+
unsigned connection_close:1;
unsigned chunked:1;
} ngx_http_upstream_headers_in_t;
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c
index fe88f48e4..f864d9910 100644
--- a/src/mail/ngx_mail_ssl_module.c
+++ b/src/mail/ngx_mail_ssl_module.c
@@ -21,6 +21,8 @@ static char *ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -74,6 +76,13 @@ static ngx_command_t ngx_mail_ssl_commands[] = {
offsetof(ngx_mail_ssl_conf_t, certificate_key),
NULL },
+ { ngx_string("ssl_password_file"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_mail_ssl_password_file,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("ssl_dhparam"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
@@ -195,6 +204,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)
scf->enable = NGX_CONF_UNSET;
scf->starttls = NGX_CONF_UNSET_UINT;
+ scf->passwords = NGX_CONF_UNSET_PTR;
scf->prefer_server_ciphers = NGX_CONF_UNSET;
scf->builtin_session_cache = NGX_CONF_UNSET;
scf->session_timeout = NGX_CONF_UNSET;
@@ -231,6 +241,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, "");
+ ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
+
ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
@@ -302,7 +314,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
cln->data = &conf->ssl;
if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
- &conf->certificate_key)
+ &conf->certificate_key, conf->passwords)
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -422,6 +434,29 @@ ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
+ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_mail_ssl_conf_t *scf = conf;
+
+ ngx_str_t *value;
+
+ if (scf->passwords != NGX_CONF_UNSET_PTR) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
+
+ if (scf->passwords == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_mail_ssl_conf_t *scf = conf;
diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h
index bef0e515a..987d029ef 100644
--- a/src/mail/ngx_mail_ssl_module.h
+++ b/src/mail/ngx_mail_ssl_module.h
@@ -39,6 +39,8 @@ typedef struct {
ngx_str_t ciphers;
+ ngx_array_t *passwords;
+
ngx_shm_zone_t *shm_zone;
ngx_flag_t session_tickets;
diff --git a/src/os/unix/ngx_darwin_sendfile_chain.c b/src/os/unix/ngx_darwin_sendfile_chain.c
index 76c4a3a4d..ee44e1d58 100644
--- a/src/os/unix/ngx_darwin_sendfile_chain.c
+++ b/src/os/unix/ngx_darwin_sendfile_chain.c
@@ -13,7 +13,7 @@
/*
* It seems that Darwin 9.4 (Mac OS X 1.5) sendfile() has the same
* old bug as early FreeBSD sendfile() syscall:
- * http://www.freebsd.org/cgi/query-pr.cgi?pr=33771
+ * http://bugs.freebsd.org/33771
*
* Besides sendfile() has another bug: if one calls sendfile()
* with both a header and a trailer, then sendfile() ignores a file part
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 11cec8226..6491e928f 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -265,7 +265,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
/*
* the "nbytes bug" of the old sendfile() syscall:
- * http://www.freebsd.org/cgi/query-pr.cgi?pr=33771
+ * http://bugs.freebsd.org/33771
*/
if (!ngx_freebsd_sendfile_nbytes_bug) {