summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNGINX team <nginx@nginx.org>2012-07-10 12:36:09 +0000
committerJon Kolb <jon@b0g.us>2012-07-10 12:36:09 +0000
commit2c96fd00bd0883a74d888dae3c90112cf6f02395 (patch)
tree9668cb3edce5c2832e7b3ff5f15c33e4e141a5ba
parent71bb11df293f3584871a0f7a620f5aae36bf7b66 (diff)
downloadnginx-2c96fd00bd0883a74d888dae3c90112cf6f02395.tar.gz
Changes with nginx 1.3.3 10 Jul 2012v1.3.3
*) Feature: entity tags support and the "etag" directive. *) Bugfix: trailing dot in a source value was not ignored if the "map" directive was used with the "hostnames" parameter. *) Bugfix: incorrect location might be used to process a request if a URI was changed via a "rewrite" directive before an internal redirect to a named location.
-rw-r--r--CHANGES14
-rw-r--r--CHANGES.ru12
-rw-r--r--auto/install2
-rw-r--r--auto/lib/libatomic/make2
-rw-r--r--auto/lib/perl/make2
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_shmtx.c6
-rw-r--r--src/core/ngx_shmtx.h2
-rw-r--r--src/http/modules/ngx_http_addition_filter_module.c1
-rw-r--r--src/http/modules/ngx_http_flv_module.c4
-rw-r--r--src/http/modules/ngx_http_gzip_filter_module.c1
-rw-r--r--src/http/modules/ngx_http_gzip_static_module.c4
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c68
-rw-r--r--src/http/modules/ngx_http_map_module.c9
-rw-r--r--src/http/modules/ngx_http_mp4_module.c4
-rw-r--r--src/http/modules/ngx_http_not_modified_filter_module.c155
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c40
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c1
-rw-r--r--src/http/modules/ngx_http_static_module.c4
-rw-r--r--src/http/modules/ngx_http_sub_filter_module.c1
-rw-r--r--src/http/modules/ngx_http_xslt_filter_module.c1
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_core_module.c46
-rw-r--r--src/http/ngx_http_core_module.h9
-rw-r--r--src/http/ngx_http_request.c19
-rw-r--r--src/http/ngx_http_request.h2
-rw-r--r--src/http/ngx_http_special_response.c2
-rw-r--r--src/os/unix/ngx_files.c12
28 files changed, 341 insertions, 88 deletions
diff --git a/CHANGES b/CHANGES
index 28cfec81c..23f4f25bb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,16 @@
+Changes with nginx 1.3.3 10 Jul 2012
+
+ *) Feature: entity tags support and the "etag" directive.
+
+ *) Bugfix: trailing dot in a source value was not ignored if the "map"
+ directive was used with the "hostnames" parameter.
+
+ *) Bugfix: incorrect location might be used to process a request if a
+ URI was changed via a "rewrite" directive before an internal redirect
+ to a named location.
+
+
Changes with nginx 1.3.2 26 Jun 2012
*) Change: the "single" parameter of the "keepalive" directive is now
@@ -41,7 +53,7 @@ Changes with nginx 1.3.1 05 Jun 2012
directives, and the "server" directive inside the "upstream" block,
now support IPv6 addresses.
- *) Feature: the "resolver" directive now support IPv6 addresses and an
+ *) Feature: the "resolver" directive now supports IPv6 addresses and an
optional port specification.
*) Feature: the "least_conn" directive inside the "upstream" block.
diff --git a/CHANGES.ru b/CHANGES.ru
index 0869fc498..beef2f87a 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,16 @@
+Изменения в nginx 1.3.3 10.07.2012
+
+ *) Добавление: поддержка entity tags и директива etag.
+
+ *) Исправление: при использовании директивы map с параметром hostnames
+ не игнорировалась конечная точка в исходном значении.
+
+ *) Исправление: для обработки запроса мог использоваться неверный
+ location, если переход в именованный location происходил после
+ изменения URI с помощью директивы rewrite.
+
+
Изменения в nginx 1.3.2 26.06.2012
*) Изменение: параметр single директивы keepalive теперь игнорируется.
diff --git a/auto/install b/auto/install
index c2c0ade59..6ef0da9df 100644
--- a/auto/install
+++ b/auto/install
@@ -8,7 +8,7 @@ if [ $USE_PERL = YES ]; then
cat << END >> $NGX_MAKEFILE
install_perl_modules:
- cd $NGX_OBJS/src/http/modules/perl && make install
+ cd $NGX_OBJS/src/http/modules/perl && \${MAKE} install
END
NGX_INSTALL_PERL_MODULES=install_perl_modules
diff --git a/auto/lib/libatomic/make b/auto/lib/libatomic/make
index b84267b63..f3cd83281 100644
--- a/auto/lib/libatomic/make
+++ b/auto/lib/libatomic/make
@@ -6,7 +6,7 @@
cat << END >> $NGX_MAKEFILE
$NGX_LIBATOMIC/src/libatomic_ops.a: $NGX_LIBATOMIC/Makefile
- cd $NGX_LIBATOMIC && make
+ cd $NGX_LIBATOMIC && \${MAKE}
$NGX_LIBATOMIC/Makefile: $NGX_MAKEFILE
cd $NGX_LIBATOMIC && ./configure
diff --git a/auto/lib/perl/make b/auto/lib/perl/make
index b4df01dd9..248be9e3f 100644
--- a/auto/lib/perl/make
+++ b/auto/lib/perl/make
@@ -12,7 +12,7 @@ $NGX_OBJS/src/http/modules/perl/blib/arch/auto/nginx/nginx.so: \
$NGX_OBJS/src/http/modules/perl/Makefile
cp -p src/http/modules/perl/nginx.* $NGX_OBJS/src/http/modules/perl/
- cd $NGX_OBJS/src/http/modules/perl && make
+ cd $NGX_OBJS/src/http/modules/perl && \${MAKE}
rm -rf $NGX_OBJS/install_perl
diff --git a/src/core/nginx.h b/src/core/nginx.h
index a0a8141a7..52f901d8e 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1003002
-#define NGINX_VERSION "1.3.2"
+#define nginx_version 1003003
+#define NGINX_VERSION "1.3.3"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_shmtx.c b/src/core/ngx_shmtx.c
index 085294a91..6cf7af58a 100644
--- a/src/core/ngx_shmtx.c
+++ b/src/core/ngx_shmtx.c
@@ -44,7 +44,7 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
void
-ngx_shmtx_destory(ngx_shmtx_t *mtx)
+ngx_shmtx_destroy(ngx_shmtx_t *mtx)
{
#if (NGX_HAVE_POSIX_SEM)
@@ -208,7 +208,7 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
return NGX_OK;
}
- ngx_shmtx_destory(mtx);
+ ngx_shmtx_destroy(mtx);
}
mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN,
@@ -232,7 +232,7 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
void
-ngx_shmtx_destory(ngx_shmtx_t *mtx)
+ngx_shmtx_destroy(ngx_shmtx_t *mtx)
{
if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
diff --git a/src/core/ngx_shmtx.h b/src/core/ngx_shmtx.h
index 830b6f5b1..91e11bebb 100644
--- a/src/core/ngx_shmtx.h
+++ b/src/core/ngx_shmtx.h
@@ -39,7 +39,7 @@ typedef struct {
ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr,
u_char *name);
-void ngx_shmtx_destory(ngx_shmtx_t *mtx);
+void ngx_shmtx_destroy(ngx_shmtx_t *mtx);
ngx_uint_t ngx_shmtx_trylock(ngx_shmtx_t *mtx);
void ngx_shmtx_lock(ngx_shmtx_t *mtx);
void ngx_shmtx_unlock(ngx_shmtx_t *mtx);
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
index 24747c564..f598ceab3 100644
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -121,6 +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);
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c
index 03a746803..cc2532027 100644
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -194,6 +194,10 @@ ngx_http_flv_handler(ngx_http_request_t *r)
r->headers_out.content_length_n = len;
r->headers_out.last_modified_time = of.mtime;
+ if (ngx_http_set_etag(r) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
if (ngx_http_set_content_type(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 128d3d9c8..09994d9b2 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -306,6 +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);
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c
index b0183e0aa..da359766d 100644
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -207,6 +207,10 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
r->headers_out.content_length_n = of.size;
r->headers_out.last_modified_time = of.mtime;
+ if (ngx_http_set_etag(r) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
if (ngx_http_set_content_type(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index 938993434..5b85e59cd 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -57,6 +57,8 @@ static ngx_int_t ngx_http_add_header(ngx_http_request_t *r,
ngx_http_header_val_t *hv, ngx_str_t *value);
static ngx_int_t ngx_http_set_last_modified(ngx_http_request_t *r,
ngx_http_header_val_t *hv, ngx_str_t *value);
+static ngx_int_t ngx_http_set_response_header(ngx_http_request_t *r,
+ ngx_http_header_val_t *hv, ngx_str_t *value);
static void *ngx_http_headers_create_conf(ngx_conf_t *cf);
static char *ngx_http_headers_merge_conf(ngx_conf_t *cf,
@@ -72,9 +74,11 @@ static ngx_http_set_header_t ngx_http_set_headers[] = {
{ ngx_string("Cache-Control"), 0, ngx_http_add_cache_control },
- { ngx_string("Last-Modified"),
- offsetof(ngx_http_headers_out_t, last_modified),
- ngx_http_set_last_modified },
+ { ngx_string("Last-Modified"), 0, ngx_http_set_last_modified },
+
+ { ngx_string("ETag"),
+ offsetof(ngx_http_headers_out_t, etag),
+ ngx_http_set_response_header },
{ ngx_null_string, 0, NULL }
};
@@ -368,34 +372,56 @@ 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, **old;
+ ngx_table_elt_t *h;
- old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
+ ngx_http_clear_last_modified(r);
- r->headers_out.last_modified_time = -1;
+ if (value->len == 0) {
+ return NGX_OK;
+ }
- if (*old == NULL) {
+ r->headers_out.last_modified_time = ngx_http_parse_time(value->data,
+ value->len);
- if (value->len == 0) {
- return NGX_OK;
- }
+ h = ngx_list_push(&r->headers_out.headers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
+ r->headers_out.last_modified = h;
- *old = h;
+ h->hash = 1;
+ h->key = hv->key;
+ h->value = *value;
- } else {
- h = *old;
+ return NGX_OK;
+}
- if (value->len == 0) {
- h->hash = 0;
- return NGX_OK;
- }
+
+static ngx_int_t
+ngx_http_set_response_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
+ ngx_str_t *value)
+{
+ ngx_table_elt_t *h, **old;
+
+ old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
+
+ if (*old) {
+ (*old)->hash = 0;
+ *old = NULL;
+ }
+
+ if (value->len == 0) {
+ return NGX_OK;
}
+ h = ngx_list_push(&r->headers_out.headers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
+
+ *old = h;
+
h->hash = 1;
h->key = hv->key;
h->value = *value;
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index 2fe925f1c..e8a4ab4cc 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -110,7 +110,6 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
{
ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data;
- size_t len;
ngx_str_t val;
ngx_http_variable_value_t *value;
@@ -121,10 +120,8 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
return NGX_ERROR;
}
- len = val.len;
-
- if (len && map->hostnames && val.data[len - 1] == '.') {
- len--;
+ if (map->hostnames && val.len > 0 && val.data[val.len - 1] == '.') {
+ val.len--;
}
value = ngx_http_map_find(r, &map->map, &val);
@@ -281,6 +278,8 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
map->default_value = ctx.default_value ? ctx.default_value:
&ngx_http_variable_null_value;
+ map->hostnames = ctx.hostnames;
+
hash.key = ngx_hash_key_lc;
hash.max_size = mcf->hash_max_size;
hash.bucket_size = mcf->hash_bucket_size;
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index d3be23420..a216c87ef 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -586,6 +586,10 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.last_modified_time = of.mtime;
+ if (ngx_http_set_etag(r) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
if (ngx_http_set_content_type(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
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 488c36b72..7f1ab6236 100644
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -10,8 +10,10 @@
#include <ngx_http.h>
-static ngx_int_t ngx_http_test_precondition(ngx_http_request_t *r);
-static ngx_int_t ngx_http_test_not_modified(ngx_http_request_t *r);
+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);
static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
@@ -59,20 +61,56 @@ ngx_http_not_modified_header_filter(ngx_http_request_t *r)
return ngx_http_next_header_filter(r);
}
- if (r->headers_in.if_unmodified_since) {
- return ngx_http_test_precondition(r);
+ if (r->headers_in.if_unmodified_since
+ && !ngx_http_test_if_unmodified(r))
+ {
+ return ngx_http_filter_finalize_request(r, NULL,
+ NGX_HTTP_PRECONDITION_FAILED);
}
- if (r->headers_in.if_modified_since) {
- return ngx_http_test_not_modified(r);
+ if (r->headers_in.if_match
+ && !ngx_http_test_if_match(r, r->headers_in.if_match))
+ {
+ return ngx_http_filter_finalize_request(r, NULL,
+ NGX_HTTP_PRECONDITION_FAILED);
+ }
+
+ if (r->headers_in.if_modified_since || r->headers_in.if_none_match) {
+
+ if (r->headers_in.if_modified_since
+ && ngx_http_test_if_modified(r))
+ {
+ return ngx_http_next_header_filter(r);
+ }
+
+ if (r->headers_in.if_none_match
+ && !ngx_http_test_if_match(r, r->headers_in.if_none_match))
+ {
+ return ngx_http_next_header_filter(r);
+ }
+
+ /* not modified */
+
+ r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
+ r->headers_out.status_line.len = 0;
+ r->headers_out.content_type.len = 0;
+ ngx_http_clear_content_length(r);
+ ngx_http_clear_accept_ranges(r);
+
+ if (r->headers_out.content_encoding) {
+ r->headers_out.content_encoding->hash = 0;
+ r->headers_out.content_encoding = NULL;
+ }
+
+ return ngx_http_next_header_filter(r);
}
return ngx_http_next_header_filter(r);
}
-static ngx_int_t
-ngx_http_test_precondition(ngx_http_request_t *r)
+static ngx_uint_t
+ngx_http_test_if_unmodified(ngx_http_request_t *r)
{
time_t iums;
@@ -83,16 +121,15 @@ ngx_http_test_precondition(ngx_http_request_t *r)
"http iums:%d lm:%d", iums, r->headers_out.last_modified_time);
if (iums >= r->headers_out.last_modified_time) {
- return ngx_http_next_header_filter(r);
+ return 1;
}
- return ngx_http_filter_finalize_request(r, NULL,
- NGX_HTTP_PRECONDITION_FAILED);
+ return 0;
}
-static ngx_int_t
-ngx_http_test_not_modified(ngx_http_request_t *r)
+static ngx_uint_t
+ngx_http_test_if_modified(ngx_http_request_t *r)
{
time_t ims;
ngx_http_core_loc_conf_t *clcf;
@@ -100,7 +137,7 @@ ngx_http_test_not_modified(ngx_http_request_t *r)
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
- return ngx_http_next_header_filter(r);
+ return 1;
}
ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
@@ -109,27 +146,87 @@ ngx_http_test_not_modified(ngx_http_request_t *r)
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http ims:%d lm:%d", ims, r->headers_out.last_modified_time);
- if (ims != r->headers_out.last_modified_time) {
+ if (ims == r->headers_out.last_modified_time) {
+ return 0;
+ }
- if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
- || ims < r->headers_out.last_modified_time)
- {
- return ngx_http_next_header_filter(r);
- }
+ if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
+ || ims < r->headers_out.last_modified_time)
+ {
+ return 1;
}
- r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
- r->headers_out.status_line.len = 0;
- r->headers_out.content_type.len = 0;
- ngx_http_clear_content_length(r);
- ngx_http_clear_accept_ranges(r);
+ return 0;
+}
+
- if (r->headers_out.content_encoding) {
- r->headers_out.content_encoding->hash = 0;
- r->headers_out.content_encoding = NULL;
+static ngx_uint_t
+ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
+{
+ u_char *start, *end, ch;
+ ngx_str_t *etag, *list;
+
+ list = &header->value;
+
+ if (list->len == 1 && list->data[0] == '*') {
+ return 1;
}
- return ngx_http_next_header_filter(r);
+ if (r->headers_out.etag == NULL) {
+ return 0;
+ }
+
+ etag = &r->headers_out.etag->value;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http im:\"%V\" etag:%V", list, etag);
+
+ start = list->data;
+ end = list->data + list->len;
+
+ while (start < end) {
+
+ if (etag->len > (size_t) (end - start)) {
+ return 0;
+ }
+
+ if (ngx_strncmp(start, etag->data, etag->len) != 0) {
+ goto skip;
+ }
+
+ start += etag->len;
+
+ while (start < end) {
+ ch = *start;
+
+ if (ch == ' ' || ch == '\t') {
+ start++;
+ continue;
+ }
+
+ break;
+ }
+
+ if (start == end || *start == ',') {
+ return 1;
+ }
+
+ skip:
+
+ while (start < end && *start != ',') { start++; }
+ while (start < end) {
+ ch = *start;
+
+ if (ch == ' ' || ch == '\t' || ch == ',') {
+ start++;
+ continue;
+ }
+
+ break;
+ }
+ }
+
+ return 0;
}
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index 0eaeff915..82c202d33 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -146,7 +146,8 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
static ngx_int_t
ngx_http_range_header_filter(ngx_http_request_t *r)
{
- time_t if_range;
+ time_t if_range_time;
+ ngx_str_t *if_range, *etag;
ngx_http_core_loc_conf_t *clcf;
ngx_http_range_filter_ctx_t *ctx;
@@ -174,20 +175,47 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
goto next_filter;
}
- if (r->headers_in.if_range && r->headers_out.last_modified_time != -1) {
+ if (r->headers_in.if_range) {
- if_range = ngx_http_parse_time(r->headers_in.if_range->value.data,
- r->headers_in.if_range->value.len);
+ if_range = &r->headers_in.if_range->value;
+
+ if (if_range->len >= 2 && if_range->data[if_range->len - 1] == '"') {
+
+ if (r->headers_out.etag == NULL) {
+ goto next_filter;
+ }
+
+ etag = &r->headers_out.etag->value;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http ir:%V etag:%V", if_range, etag);
+
+ if (if_range->len != etag->len
+ || ngx_strncmp(if_range->data, etag->data, etag->len) != 0)
+ {
+ goto next_filter;
+ }
+
+ goto parse;
+ }
+
+ if (r->headers_out.last_modified_time == (time_t) -1) {
+ goto next_filter;
+ }
+
+ if_range_time = ngx_http_parse_time(if_range->data, if_range->len);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http ir:%d lm:%d",
- if_range, r->headers_out.last_modified_time);
+ if_range_time, r->headers_out.last_modified_time);
- if (if_range != r->headers_out.last_modified_time) {
+ if (if_range_time != r->headers_out.last_modified_time) {
goto next_filter;
}
}
+parse:
+
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_range_filter_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 219465ae9..13badac61 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -361,6 +361,7 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
ngx_http_clear_content_length(r);
ngx_http_clear_last_modified(r);
ngx_http_clear_accept_ranges(r);
+ ngx_http_clear_etag(r);
}
return ngx_http_next_header_filter(r);
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index 9d77e43b1..631eb17b2 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -220,6 +220,10 @@ ngx_http_static_handler(ngx_http_request_t *r)
r->headers_out.content_length_n = of.size;
r->headers_out.last_modified_time = of.mtime;
+ if (ngx_http_set_etag(r) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
if (ngx_http_set_content_type(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c
index be5e90c4e..989adf5ad 100644
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -168,6 +168,7 @@ ngx_http_sub_header_filter(ngx_http_request_t *r)
if (r == r->main) {
ngx_http_clear_content_length(r);
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
}
return ngx_http_next_header_filter(r);
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
index 9b0354b2e..94d1c86cc 100644
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -328,6 +328,7 @@ ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
}
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
}
rc = ngx_http_next_header_filter(r);
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index a71574b7b..863027a5d 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.2';
+our $VERSION = '1.3.3';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 5bb01d9ea..a8177aef7 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -650,6 +650,13 @@ static ngx_command_t ngx_http_core_commands[] = {
offsetof(ngx_http_core_loc_conf_t, chunked_transfer_encoding),
NULL },
+ { ngx_string("etag"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_core_loc_conf_t, etag),
+ NULL },
+
{ ngx_string("error_page"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_2MORE,
@@ -1809,6 +1816,42 @@ ngx_http_set_exten(ngx_http_request_t *r)
ngx_int_t
+ngx_http_set_etag(ngx_http_request_t *r)
+{
+ ngx_table_elt_t *etag;
+ ngx_http_core_loc_conf_t *clcf;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (!clcf->etag) {
+ return NGX_OK;
+ }
+
+ etag = ngx_list_push(&r->headers_out.headers);
+ if (etag == NULL) {
+ return NGX_ERROR;
+ }
+
+ etag->hash = 1;
+ ngx_str_set(&etag->key, "ETag");
+
+ etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
+ if (etag->value.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
+ r->headers_out.last_modified_time,
+ r->headers_out.content_length_n)
+ - etag->value.data;
+
+ r->headers_out.etag = etag;
+
+ return NGX_OK;
+}
+
+
+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)
{
@@ -2588,6 +2631,7 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
r->internal = 1;
r->content_handler = NULL;
+ r->uri_changed = 0;
r->loc_conf = (*clcfp)->loc_conf;
/* clear the modules contexts */
@@ -3509,6 +3553,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
clcf->recursive_error_pages = NGX_CONF_UNSET;
clcf->server_tokens = NGX_CONF_UNSET;
clcf->chunked_transfer_encoding = NGX_CONF_UNSET;
+ clcf->etag = NGX_CONF_UNSET;
clcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
@@ -3770,6 +3815,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
ngx_conf_merge_value(conf->chunked_transfer_encoding,
prev->chunked_transfer_encoding, 1);
+ ngx_conf_merge_value(conf->etag, prev->etag, 1);
ngx_conf_merge_ptr_value(conf->open_file_cache,
prev->open_file_cache, NULL);
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index e95d1e069..b11bdcd90 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -392,6 +392,7 @@ struct ngx_http_core_loc_conf_s {
ngx_flag_t recursive_error_pages; /* recursive_error_pages */
ngx_flag_t server_tokens; /* server_tokens */
ngx_flag_t chunked_transfer_encoding; /* chunked_transfer_encoding */
+ ngx_flag_t etag; /* etag */
#if (NGX_HTTP_GZIP)
ngx_flag_t gzip_vary; /* gzip_vary */
@@ -480,6 +481,7 @@ ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r,
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);
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,
@@ -555,5 +557,12 @@ extern ngx_str_t ngx_http_core_get_method;
r->headers_out.location = NULL; \
}
+#define ngx_http_clear_etag(r) \
+ \
+ if (r->headers_out.etag) { \
+ r->headers_out.etag->hash = 0; \
+ r->headers_out.etag = NULL; \
+ }
+
#endif /* _NGX_HTTP_CORE_H_INCLUDED_ */
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index e0ae5241f..60d7b9249 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -93,6 +93,14 @@ ngx_http_header_t ngx_http_headers_in[] = {
offsetof(ngx_http_headers_in_t, if_unmodified_since),
ngx_http_process_unique_header_line },
+ { ngx_string("If-Match"),
+ offsetof(ngx_http_headers_in_t, if_match),
+ ngx_http_process_unique_header_line },
+
+ { ngx_string("If-None-Match"),
+ offsetof(ngx_http_headers_in_t, if_none_match),
+ ngx_http_process_unique_header_line },
+
{ ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
ngx_http_process_user_agent },
@@ -747,6 +755,7 @@ ngx_http_process_request_line(ngx_event_t *rev)
r->request_line.len = r->request_end - r->request_start;
r->request_line.data = r->request_start;
+ r->request_length = r->header_in->pos - r->request_start;
if (r->args_start) {
@@ -1056,6 +1065,8 @@ ngx_http_process_request_headers(ngx_event_t *rev)
if (rc == NGX_OK) {
+ r->request_length += r->header_in->pos - r->header_name_start;
+
if (r->invalid_header && cscf->ignore_invalid_headers) {
/* there was error while a header line parsing */
@@ -1119,7 +1130,7 @@ ngx_http_process_request_headers(ngx_event_t *rev)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http header done");
- r->request_length += r->header_in->pos - r->header_in->start;
+ r->request_length += r->header_in->pos - r->header_name_start;
r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
@@ -1226,8 +1237,6 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
/* the client fills up the buffer with "\r\n" */
- r->request_length += r->header_in->end - r->header_in->start;
-
r->header_in->pos = r->header_in->start;
r->header_in->last = r->header_in->start;
@@ -1287,8 +1296,6 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
* to relocate the parser header pointers
*/
- r->request_length += r->header_in->end - r->header_in->start;
-
r->header_in = b;
return NGX_OK;
@@ -1297,8 +1304,6 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http large header copy: %d", r->header_in->pos - old);
- r->request_length += old - r->header_in->start;
-
new = b->start;
ngx_memcpy(new, old, r->header_in->pos - old);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index ec946c5a6..b6ff8983a 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -172,6 +172,8 @@ typedef struct {
ngx_table_elt_t *connection;
ngx_table_elt_t *if_modified_since;
ngx_table_elt_t *if_unmodified_since;
+ ngx_table_elt_t *if_match;
+ ngx_table_elt_t *if_none_match;
ngx_table_elt_t *user_agent;
ngx_table_elt_t *referer;
ngx_table_elt_t *content_length;
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 77b3dd13f..224cb811d 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -656,6 +656,7 @@ ngx_http_send_special_response(ngx_http_request_t *r,
ngx_http_clear_accept_ranges(r);
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
rc = ngx_http_send_header(r);
@@ -754,6 +755,7 @@ ngx_http_send_refresh(ngx_http_request_t *r)
ngx_http_clear_accept_ranges(r);
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
rc = ngx_http_send_header(r);
diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c
index ca5458104..2dfa1b7a1 100644
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -413,9 +413,7 @@ ngx_trylock_fd(ngx_fd_t fd)
{
struct flock fl;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_pid = 0;
+ ngx_memzero(&fl, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
@@ -432,9 +430,7 @@ ngx_lock_fd(ngx_fd_t fd)
{
struct flock fl;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_pid = 0;
+ ngx_memzero(&fl, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
@@ -451,9 +447,7 @@ ngx_unlock_fd(ngx_fd_t fd)
{
struct flock fl;
- fl.l_start = 0;
- fl.l_len = 0;
- fl.l_pid = 0;
+ ngx_memzero(&fl, sizeof(struct flock));
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;