this patch modifies the etag header returned by responses processed by the gzip filter, appending "-gzip" to the etag (instead of deleting it). Also, If-None-Match and If-Match requests work against the modified etag. (the gunzip module appends "-gunzip" to the etag).
cheers Andrew # HG changeset patch # User Andrew Williams <sobak...@gmail.com> # Date 1401259215 -34200 # Wed May 28 16:10:15 2014 +0930 # Node ID 102149a95d84250e709051b1f2c8b49a1872bd3e # Parent adb742cf27f771771b293cc280f594038e8d9aab append "-gzip" to etags processed by gzip_filter_module + not modified support diff -r adb742cf27f7 -r 102149a95d84 src/http/modules/ngx_http_gunzip_filter_module.c --- a/src/http/modules/ngx_http_gunzip_filter_module.c Tue May 27 17:58:09 2014 +0400 +++ b/src/http/modules/ngx_http_gunzip_filter_module.c Wed May 28 16:10:15 2014 +0930 @@ -115,6 +115,7 @@ static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_http_output_body_filter_pt ngx_http_next_body_filter; +static ngx_str_t ngx_http_gunzip_etag_suffix = ngx_string("-gunzip"); static ngx_int_t @@ -149,6 +150,13 @@ return ngx_http_next_header_filter(r); } + ngx_int_t etag_filter_result; + ngx_http_update_etag(r, &ngx_http_gunzip_etag_suffix); + if (ngx_http_test_etag_if_match(r, ngx_http_next_header_filter, + &etag_filter_result)) { + return etag_filter_result; + } + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gunzip_ctx_t)); if (ctx == NULL) { return NGX_ERROR; @@ -165,7 +173,6 @@ 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 -r adb742cf27f7 -r 102149a95d84 src/http/modules/ngx_http_gzip_filter_module.c --- a/src/http/modules/ngx_http_gzip_filter_module.c Tue May 27 17:58:09 2014 +0400 +++ b/src/http/modules/ngx_http_gzip_filter_module.c Wed May 28 16:10:15 2014 +0930 @@ -229,6 +229,7 @@ static ngx_str_t ngx_http_gzip_ratio = ngx_string("gzip_ratio"); +static ngx_str_t ngx_http_gzip_etag_suffix = ngx_string("-gzip"); static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_http_output_body_filter_pt ngx_http_next_body_filter; @@ -280,6 +281,13 @@ return ngx_http_next_header_filter(r); } + ngx_int_t etag_filter_result; + ngx_http_update_etag(r, &ngx_http_gzip_etag_suffix); + if (ngx_http_test_etag_if_match(r, ngx_http_next_header_filter, + &etag_filter_result)) { + return etag_filter_result; + } + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gzip_ctx_t)); if (ctx == NULL) { return NGX_ERROR; @@ -306,7 +314,6 @@ 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 -r adb742cf27f7 -r 102149a95d84 src/http/modules/ngx_http_not_modified_filter_module.c --- a/src/http/modules/ngx_http_not_modified_filter_module.c Tue May 27 17:58:09 2014 +0400 +++ b/src/http/modules/ngx_http_not_modified_filter_module.c Wed May 28 16:10:15 2014 +0930 @@ -12,8 +12,6 @@ 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); @@ -160,76 +158,6 @@ } -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; - } - - 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; -} - - static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf) { diff -r adb742cf27f7 -r 102149a95d84 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Tue May 27 17:58:09 2014 +0400 +++ b/src/http/ngx_http_core_module.c Wed May 28 16:10:15 2014 +0930 @@ -1851,6 +1851,134 @@ } +// update etag, append suffix +ngx_uint_t +ngx_http_update_etag(ngx_http_request_t *r, ngx_str_t *suffix) +{ + ngx_table_elt_t *etag; + void *old_etag_value; + + etag = r->headers_out.etag; + + if (etag == NULL || suffix == NULL) + return 0; + + old_etag_value = etag->value.data; + etag->value.data = ngx_pnalloc(r->pool, etag->value.len + + suffix->len + 1); + ngx_cpystrn(etag->value.data, old_etag_value, etag->value.len); + etag->value.len = ngx_sprintf(etag->value.data + etag->value.len - 1, + "%s\"", suffix->data) - etag->value.data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http updated etag: %s", etag->value.data); + + return 1; +} + + +ngx_int_t +ngx_http_test_etag_if_match(ngx_http_request_t *r, + ngx_http_output_header_filter_pt next_header_filter, + ngx_int_t *etag_filter_result) +{ + if (r->headers_in.if_match + && !ngx_http_test_if_match(r, r->headers_in.if_match)) { + *etag_filter_result = ngx_http_filter_finalize_request + (r, NULL, NGX_HTTP_PRECONDITION_FAILED); + return 1; + } + else if (r->headers_in.if_none_match + && ngx_http_test_if_match(r, r->headers_in.if_none_match)) { + /* 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; + } + + *etag_filter_result = next_header_filter(r); + return 1; + } + return 0; +} + + +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; + } + + 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; +} + + 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 -r adb742cf27f7 -r 102149a95d84 src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Tue May 27 17:58:09 2014 +0400 +++ b/src/http/ngx_http_core_module.h Wed May 28 16:10:15 2014 +0930 @@ -500,7 +500,6 @@ 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, @@ -527,6 +526,15 @@ (ngx_http_request_t *r, ngx_chain_t *chain); +ngx_int_t ngx_http_set_etag(ngx_http_request_t *r); +ngx_uint_t ngx_http_update_etag(ngx_http_request_t *r, ngx_str_t *suffix); +ngx_int_t ngx_http_test_etag_if_match(ngx_http_request_t *r, + ngx_http_output_header_filter_pt next_header_filter, + ngx_int_t *etag_filter_result); +ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r, + ngx_table_elt_t *header); + + ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *chain); ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain); _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel