From 5b2604b3914f87db2077f2239b8a98b66cf622af Mon Sep 17 00:00:00 2001 From: Daniel Jagszent Date: Sat, 25 Jun 2022 13:05:39 +0200 Subject: [PATCH] Make mod_zip compatible with nginx 1.23.0+ (#93) nginx 1.23 changed the way known multi value headers are handled (as linked lists) --- .github/workflows/build.yml | 2 +- config | 12 ++++++++++ ngx_http_zip_file.c | 7 +++--- ngx_http_zip_headers.c | 44 +++++++++++++++++++++++++++++++++++++ ngx_http_zip_headers.h | 4 ++++ ngx_http_zip_module.c | 8 +++---- 6 files changed, 69 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e0d5796..1ef7145 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ jobs: fail-fast: false matrix: compiler: [ gcc, clang ] - version: [ 1.19.10, 1.20.2, 1.21.4 ] + version: [ 1.19.10, 1.20.2, 1.21.4, 1.22.0, 1.23.0 ] steps: - name: Install carton run: sudo apt install carton diff --git a/config b/config index 9f006ef..f782bd4 100644 --- a/config +++ b/config @@ -36,3 +36,15 @@ if [ $ngx_found = yes ]; then CORE_LIBS="$CORE_LIBS $ngx_feature_libs" ngx_found=no fi + +ngx_feature="multi-value headers are linked lists (nginx 1.23.0+)" +ngx_feature_name="NGX_ZIP_MULTI_HEADERS_LINKED_LISTS" +ngx_feature_run=yes +ngx_feature_incs="#include \"nginx.h\"" +ngx_feature_path="src/core" +ngx_feature_test=" +#if nginx_version < 1023000 +#error multi headers are no linked lists +#endif +" +. auto/feature diff --git a/ngx_http_zip_file.c b/ngx_http_zip_file.c index 77b49ec..3e0e482 100644 --- a/ngx_http_zip_file.c +++ b/ngx_http_zip_file.c @@ -3,6 +3,7 @@ #include "ngx_http_zip_file.h" #include "ngx_http_zip_file_format.h" #include "ngx_http_zip_endian.h" +#include "ngx_http_zip_headers.h" #ifdef NGX_ZIP_HAVE_ICONV #include @@ -252,7 +253,7 @@ ngx_http_zip_generate_pieces(ngx_http_request_t *r, ngx_http_zip_ctx_t *ctx) // because UFT-8 flag (zip_utf8_flag) is set default for templates. ngx_int_t variable_header_status = NGX_OK; if (r->upstream) { - variable_header_status = ngx_http_variable_unknown_header(vv, &ngx_http_zip_header_name_separator, + variable_header_status = ngx_http_zip_variable_unknown_header(r, vv, &ngx_http_zip_header_name_separator, &r->upstream->headers_in.headers.part, sizeof("upstream_http_")-1); } else { vv->not_found = 1; @@ -266,7 +267,7 @@ ngx_http_zip_generate_pieces(ngx_http_request_t *r, ngx_http_zip_ctx_t *ctx) #ifdef NGX_ZIP_HAVE_ICONV variable_header_status = NGX_OK; if (r->upstream) { - variable_header_status = ngx_http_variable_unknown_header(vv, &ngx_http_zip_header_charset_name, + variable_header_status = ngx_http_zip_variable_unknown_header(r, vv, &ngx_http_zip_header_charset_name, &r->upstream->headers_in.headers.part, sizeof("upstream_http_")-1); } else { vv->not_found = 1; @@ -431,7 +432,7 @@ ngx_http_zip_generate_pieces(ngx_http_request_t *r, ngx_http_zip_ctx_t *ctx) // Collect names of original request's header fields that // have to be present in each of the issued sub-requests. - variable_header_status = ngx_http_variable_unknown_header(vv, &ngx_http_zip_header_name_pass_headers, + variable_header_status = ngx_http_zip_variable_unknown_header(r, vv, &ngx_http_zip_header_name_pass_headers, &r->upstream->headers_in.headers.part, sizeof("upstream_http_")-1); if (variable_header_status == NGX_OK && !vv->not_found) { diff --git a/ngx_http_zip_headers.c b/ngx_http_zip_headers.c index 2586c5d..a973bb7 100644 --- a/ngx_http_zip_headers.c +++ b/ngx_http_zip_headers.c @@ -21,6 +21,36 @@ ngx_http_zip_find_key_in_set(ngx_str_t *key, ngx_array_t *set) ngx_int_t ngx_http_zip_add_cache_control(ngx_http_request_t *r) { +#ifdef NGX_ZIP_MULTI_HEADERS_LINKED_LISTS + ngx_table_elt_t *cc; + + /* convoluted way of adding Cache-Control: max-age=0 */ + /* The header is necessary so IE doesn't barf */ + cc = r->headers_out.cache_control; + + if (cc == NULL) { + cc = ngx_list_push(&r->headers_out.headers); + if (cc == NULL) { + return NGX_ERROR; + } + + r->headers_out.cache_control = cc; + cc->next = NULL; + cc->hash = 1; + ngx_str_set(&cc->key, "Cache-Control"); + } else { + for (cc = cc->next; cc; cc = cc->next) { + cc->hash = 0; + } + + cc = r->headers_out.cache_control; + cc->next = NULL; + } + + ngx_str_set(&cc->value, "max-age=0"); + + return NGX_OK; +#else ngx_table_elt_t **ccp, *cc; ngx_uint_t i; @@ -62,6 +92,7 @@ ngx_http_zip_add_cache_control(ngx_http_request_t *r) ngx_str_set(&cc->value, "max-age=0"); return NGX_OK; +#endif } ngx_int_t @@ -285,3 +316,16 @@ ngx_http_zip_init_subrequest_headers(ngx_http_request_t *r, ngx_http_zip_ctx_t * return NGX_OK; } + + +ngx_int_t +ngx_http_zip_variable_unknown_header(ngx_http_request_t *r, + ngx_http_variable_value_t *v, ngx_str_t *var, + ngx_list_part_t *part, size_t prefix) +{ +#ifdef NGX_ZIP_MULTI_HEADERS_LINKED_LISTS + return ngx_http_variable_unknown_header(r, v, var, part, prefix); +#else + return ngx_http_variable_unknown_header(v, var, part, prefix); +#endif +} diff --git a/ngx_http_zip_headers.h b/ngx_http_zip_headers.h index ab2900d..f2a6187 100644 --- a/ngx_http_zip_headers.h +++ b/ngx_http_zip_headers.h @@ -13,3 +13,7 @@ ngx_int_t ngx_http_zip_init_multipart_range(ngx_http_request_t *r, ngx_int_t ngx_http_zip_init_subrequest_headers(ngx_http_request_t *r, ngx_http_zip_ctx_t *ctx, ngx_http_request_t *sr, ngx_http_zip_range_t *piece_range, ngx_http_zip_range_t *req_range); + +ngx_int_t ngx_http_zip_variable_unknown_header(ngx_http_request_t *r, + ngx_http_variable_value_t *v, ngx_str_t *var, ngx_list_part_t *part, + size_t prefix); diff --git a/ngx_http_zip_module.c b/ngx_http_zip_module.c index d14ae58..bb630bb 100644 --- a/ngx_http_zip_module.c +++ b/ngx_http_zip_module.c @@ -201,13 +201,13 @@ ngx_http_zip_main_request_header_filter(ngx_http_request_t *r) /* Look for X-Archive-Files */ ngx_int_t variable_header_status = NGX_OK; if (r->upstream) { - variable_header_status = ngx_http_variable_unknown_header(vv, + variable_header_status = ngx_http_zip_variable_unknown_header(r, vv, &ngx_http_zip_header_variable_name, - &r->upstream->headers_in.headers.part, sizeof("upstream_http_") - 1); + &r->upstream->headers_in.headers.part, sizeof("upstream_http_") - 1); } else if (r->headers_out.status == NGX_HTTP_OK) { - variable_header_status = ngx_http_variable_unknown_header(vv, + variable_header_status = ngx_http_zip_variable_unknown_header(r, vv, &ngx_http_zip_header_variable_name, - &r->headers_out.headers.part, sizeof("upstream_http_") - 1); + &r->headers_out.headers.part, sizeof("upstream_http_") - 1); } else { vv->not_found = 1; }