diff options
Diffstat (limited to 'main/nginx')
23 files changed, 2741 insertions, 321 deletions
diff --git a/main/nginx/APKBUILD b/main/nginx/APKBUILD index 0160d648472..d6240bc1499 100644 --- a/main/nginx/APKBUILD +++ b/main/nginx/APKBUILD @@ -4,6 +4,11 @@ # Contributor: Jakub Jirutka <jakub@jirutka.cz> # # secfixes: +# 1.24.0-r12: +# - CVE-2023-44487 +# 1.22.1-r0: +# - CVE-2022-41741 +# - CVE-2022-41742 # 1.20.2-r2: # - CVE-2021-46461 # - CVE-2021-46462 @@ -25,24 +30,30 @@ # - CVE-2018-16845 # 1.12.1-r0: # - CVE-2017-7529 +# 0: +# - CVE-2022-3638 # pkgname=nginx # NOTE: Upgrade only to even-numbered versions (e.g. 1.14.z, 1.16.z)! # Odd-numbered versions are mainline (development) versions. -pkgver=1.22.0 -pkgrel=6 +pkgver=1.24.0 +pkgrel=18 # Revision of nginx-tests to use for check(). -_tests_hgrev=bd21a4a7c9f5 -_njs_ver=0.7.6 +_tests_hgrev=22f45bf99a9e +_njs_ver=0.8.3 +# if this isn't set higher than testing/openresty that comes first for some reason +# even though this has a higher version.. +provider_priority=100 pkgdesc="HTTP and reverse proxy server (stable version)" url="https://www.nginx.org/" arch="all" license="BSD-2-Clause" -depends="" makedepends=" brotli-dev gd-dev geoip-dev + hiredis-dev + jansson-dev libmaxminddb-dev libxml2-dev libxslt-dev @@ -53,6 +64,8 @@ makedepends=" pkgconf zeromq-dev zlib-dev + zstd-dev + !zstd-static " checkdepends=" gd @@ -70,23 +83,29 @@ _grp_www="www-data" pkggroups="$_grp_ngx $_grp_www" install="$pkgname.pre-install $pkgname.post-install $pkgname.pre-upgrade $pkgname.post-upgrade" subpackages="$pkgname-debug $pkgname-doc $pkgname-openrc $pkgname-vim::noarch" -source="https://nginx.org/download/$pkgname-$pkgver.tar.gz +source="https://nginx.org/download/nginx-$pkgver.tar.gz + CVE-2023-44487.patch $pkgname-tests-$_tests_hgrev.tar.gz::https://hg.nginx.org/nginx-tests/archive/$_tests_hgrev.tar.gz $pkgname-njs-$_njs_ver.tar.gz::https://hg.nginx.org/njs/archive/$_njs_ver.tar.gz nginx-dav-ext-module~pr-56.patch::https://github.com/arut/nginx-dav-ext-module/pull/56.patch nginx-dav-ext-module~pr-62.patch::https://github.com/arut/nginx-dav-ext-module/commit/bbf93f75ca58657fb0f8376b0898f854f13cef91.patch - nginx-module-vts~01-938c19d.patch::https://github.com/vozlt/nginx-module-vts/commit/938c19d2e49d5f3355df5375725982d15f1270c4.patch - nginx-module-vts~02-ad40022.patch::https://github.com/vozlt/nginx-module-vts/commit/ad4002262c19e81390f518a14f99bb594862c575.patch - nginx-module-vts~03-c08781c.patch::https://github.com/vozlt/nginx-module-vts/commit/c08781c5095d9e6090c47176bdea322ce983ecb6.patch - nginx-module-vts~04-1a01a87.patch::https://github.com/vozlt/nginx-module-vts/commit/1a01a87e66c9f111fb399cf40def33ab193ae393.patch - nginx-module-vts~05-ead62a0.patch::https://github.com/vozlt/nginx-module-vts/commit/ead62a0caf405731c88ac138c4c0a82bb316cc18.patch - nginx-module-vts~fix-uri-overflow.patch - nginx-module-vts~cast-key-length-to-correct-type.patch - nginx-module-vts~set-histogram-buckets-on-first-request.patch + no-werror.patch traffic-accounting-nginx-module~disable-stream-module.patch + traffic-accounting-nginx-module~fix-memory-leak.patch nginx_cookie_flag_module~fix-mem-allocations.patch njs~mktemp-busybox-compat.patch - njs~nginx-1.20.x-compat.patch + naxsi~assert.patch + naxsi~ff-header.patch + naxsi~compat.patch + nginx-upload-progress-module~fix.patch + nginx-upload-progress-module~fix-http2.patch + ngx-fancyindex~fix-404-on-fs-root.patch + ngx-fancyindex~fix-missing-saturday.patch + nchan~dont-fail-redis-cluster-before-consensus.patch + nchan~fix-redis-race-condition.patch + nginx-upload-module~fixes.patch + nginx-upload-module~fix-nginx-compat.patch + zstd-nginx-module~fix-infinite-loop.patch nginx.conf default.conf stream.conf @@ -94,13 +113,12 @@ source="https://nginx.org/download/$pkgname-$pkgver.tar.gz $pkgname.initd $pkgname.confd " -builddir="$srcdir/$pkgname-$pkgver" _modules_dir="usr/lib/$pkgname/modules" _stream_js_depends="$pkgname-mod-stream" case "$CARCH" in - riscv64) _has_luajit=false;; + ppc64le|riscv64) _has_luajit=false;; *) _has_luajit=true; makedepends="$makedepends luajit-dev";; esac @@ -152,25 +170,28 @@ _add_module() { subpackages="$subpackages $pkgname-mod-$name:_module" } -_add_module "devel-kit" "v0.3.1" "https://github.com/vision5/ngx_devel_kit" +_add_module "devel-kit" "v0.3.3" "https://github.com/vision5/ngx_devel_kit" _devel_kit_so="ndk_http_module.so" _add_module "http-accounting" "v2.0" "https://github.com/Lax/traffic-accounting-nginx-module" -_add_module "http-array-var" "v0.05" "https://github.com/openresty/array-var-nginx-module" +_add_module "http-array-var" "v0.06" "https://github.com/openresty/array-var-nginx-module" _http_array_var_depends="$pkgname-mod-devel-kit" +_add_module "http-auth-jwt" "0.6.0" "https://github.com/kjdev/nginx-auth-jwt" +_http_auth_jwt_desc="Nginx third-party module kjdev/nginx-auth-jwt (version $_http_auth_jwt_ver)" + _add_module "http-brotli" "v1.0.0rc" "https://github.com/google/ngx_brotli" _http_brotli_so="ngx_http_brotli_filter_module.so ngx_http_brotli_static_module.so" -_add_module "http-cache-purge" "2.5.2" "https://github.com/nginx-modules/ngx_cache_purge" +_add_module "http-cache-purge" "2.5.3" "https://github.com/nginx-modules/ngx_cache_purge" _add_module "http-cookie-flag" "v1.1.0" "https://github.com/AirisX/nginx_cookie_flag_module" _http_cookie_flag_so="ngx_http_cookie_flag_filter_module.so" _add_module "http-dav-ext" "v3.0.0" "https://github.com/arut/nginx-dav-ext-module" -_add_module "http-echo" "v0.62" "https://github.com/openresty/echo-nginx-module" +_add_module "http-echo" "v0.63" "https://github.com/openresty/echo-nginx-module" _add_module "http-encrypted-session" "v0.09" "https://github.com/openresty/encrypted-session-nginx-module" _http_encrypted_session_depends="$pkgname-mod-devel-kit" @@ -181,13 +202,15 @@ _add_module "http-geoip2" "3.4" "https://github.com/leev/ngx_http_geoip2_module" _add_module "stream-geoip2" "3.4" "https://github.com/leev/ngx_http_geoip2_module" _stream_geoip2_depends="$pkgname-mod-stream" -_add_module "http-headers-more" "v0.33" "https://github.com/openresty/headers-more-nginx-module" +_add_module "http-headers-more" "v0.37" "https://github.com/openresty/headers-more-nginx-module" _http_headers_more_so="ngx_http_headers_more_filter_module.so" +_add_module "http-keyval" "0.2.0" "https://github.com/kjdev/nginx-keyval" + _add_module "http-log-zmq" "v1.0.0" "https://github.com/danifbento/nginx-log-zmq" # luajit is required for lua-nginx-module since v0.10.14 -_add_module "http-lua" "v0.10.21" "https://github.com/openresty/lua-nginx-module" "" "$_has_luajit" +_add_module "http-lua" "v0.10.26" "https://github.com/openresty/lua-nginx-module" "" "$_has_luajit" _http_lua_depends="$pkgname-mod-devel-kit lua-resty-core" _http_lua_provides="$pkgname-lua" # for backward compatibility @@ -197,7 +220,7 @@ _http_lua_upstream_depends="$pkgname-mod-http-lua" _add_module "http-naxsi" "1.3" "https://github.com/nbs-system/naxsi" "naxsi_src" _naxsi_provides="$pkgname-naxsi" # for backward compatibility -_add_module "http-nchan" "v1.3.0" "https://github.com/slact/nchan" +_add_module "http-nchan" "v1.3.6" "https://github.com/slact/nchan" _http_nchan_so="ngx_nchan_module.so" _add_module "http-redis2" "v0.15" "https://github.com/openresty/redis2-nginx-module" @@ -205,7 +228,7 @@ _add_module "http-redis2" "v0.15" "https://github.com/openresty/redis2-nginx-mod _add_module "http-set-misc" "v0.33" "https://github.com/openresty/set-misc-nginx-module" _http_set_misc_depends="$pkgname-mod-devel-kit" -_add_module "http-shibboleth" "v2.0.1" "https://github.com/nginx-shib/nginx-http-shibboleth" +_add_module "http-shibboleth" "v2.0.2" "https://github.com/nginx-shib/nginx-http-shibboleth" _add_module "http-untar" "v1.1" "https://github.com/ajax16384/ngx_http_untar_module" @@ -216,19 +239,21 @@ _http_upload_progress_so="ngx_http_uploadprogress_module.so" _add_module "http-upstream-fair" "0.1.3" "https://github.com/itoffshore/nginx-upstream-fair" -_add_module "http-upstream-jdomain" "1.4.0" "https://github.com/nicholaschiasson/ngx_upstream_jdomain" +_add_module "http-upstream-jdomain" "1.5.0" "https://github.com/nicholaschiasson/ngx_upstream_jdomain" -_add_module "http-vod" "1.29" "https://github.com/kaltura/nginx-vod-module" +_add_module "http-vod" "1.33" "https://github.com/kaltura/nginx-vod-module" -_add_module "http-vts" "v0.1.18" "https://github.com/vozlt/nginx-module-vts" +_add_module "http-vts" "v0.2.2" "https://github.com/vozlt/nginx-module-vts" _http_vts_so="ngx_http_vhost_traffic_status_module.so" -_add_module "http-zip" "1.2.0" "https://github.com/evanmiller/mod_zip" +_add_module "http-zip" "1.3.0" "https://github.com/evanmiller/mod_zip" + +_add_module "http-zstd" "0.1.1" "https://github.com/tokers/zstd-nginx-module" +_http_zstd_so="ngx_http_zstd_filter_module.so ngx_http_zstd_static_module.so" _add_module "rtmp" "v1.2.2" "https://github.com/arut/nginx-rtmp-module" _rtmp_provides="$pkgname-rtmp" # for backward compatibility - prepare() { local file; for file in $source; do file=${file%%::*} @@ -260,6 +285,14 @@ _build() { export LUAJIT_INC="$(pkgconf --variable=includedir luajit)" fi + # Fix compilation with gcc 13.1. + # TODO: Remove after upgrade to njs 0.7.13. + # https://github.com/nginx/njs/commit/e60d10f2007c332391d7a104453e13567ebbe52d + export NJS_CFLAGS="-Wno-error=dangling-pointer" + + # Enable support for Redis store in the http-keyval module. + export NGX_HTTP_KEYVAL_ZONE_REDIS=1 + # --without-pcre2 - Lua module is not compatible with PCRE2 yet # https://github.com/openresty/lua-nginx-module/issues/1984 ./configure \ @@ -319,8 +352,6 @@ _build() { } build() { - cd "$builddir" - _build --with-debug mv objs objs-debug @@ -339,18 +370,18 @@ check() { ;; esac - TEST_NGINX_BINARY="$builddir/objs/nginx" prove . + : ${JOBS:-1} + TEST_NGINX_BINARY="$builddir/objs/nginx" prove -j $((JOBS > 20 ? 20 : JOBS)) . - if [ -n "$_njs_mods" ]; then - msg "Running njs tests..." - cd "$srcdir"/njs-* - make test - fi + # FIXME: see !46437 + #if [ -n "$_njs_mods" ]; then + # msg "Running njs tests..." + # cd "$srcdir"/njs-* + # make test + #fi } package() { - cd "$builddir" - make DESTDIR="$pkgdir" install chown root:root "$pkgdir"/usr/sbin/nginx @@ -420,6 +451,7 @@ _module() { pkgdesc="Nginx module ${name//_/-}" [ "$ver" ] && pkgdesc="Nginx third-party module ${name//_/-} (version $ver)" + pkgdesc="$(getvar "_${name}_desc" "$pkgdesc")" url=$(getvar "_${name}_url" "$url") sonames=$(getvar "_${name}_so" "ngx_${name}_module.so") depends="$pkgname $(getvar "_${name}_depends")" @@ -452,7 +484,7 @@ _module() { ;; stream) mkdir -p ./etc/nginx/stream.d - install -m644 "$srcdir"/stream.conf ./etc/nginx/stream.conf + install -m644 -D "$srcdir"/stream.conf ./etc/nginx/conf.d/stream.conf ;; esac } @@ -463,56 +495,65 @@ getvar() { } sha512sums=" -074782dba9cd5f8f493fbb57e20bda6dc9171814d919a47ee9f825d93f12c9f9d496e25d063c983191b55ad6a236bcef252ce16ecc1d253dc8b23433557559b1 nginx-1.22.0.tar.gz -13ad8b3f7626f7fa11a1c395ccb361babb1b896789f8eda4350c7b214ec0c4674b9bfec253d29f6e82788da21a1b60cf2b0baef54f3ed2e5e404f286a6a9fbe7 nginx-tests-bd21a4a7c9f5.tar.gz -ef7d362c5d6c48d302ee0d74b72d7e1c19a14c414cc49432c33b2873c118717343c7fa195e210246b35c643ce98cd8ef8a07946dfce57c75f77255a215c57bd4 nginx-njs-0.7.6.tar.gz +1114e37de5664a8109c99cfb2faa1f42ff8ac63c932bcf3780d645e5ed32c0b2ac446f80305b4465994c8f9430604968e176ae464fd80f632d1cb2c8f6007ff3 nginx-1.24.0.tar.gz +18b69643648119dfab45101bb9404be667aeb9d550aa3bc9706e63e7da1c2806106e9a6bbfb2d10bd57ef56b9b5b0b524059353ec30a51469b44641cb7dbd8a6 CVE-2023-44487.patch +d882d7f79814bd5caf323099aef318a5f4c75c2eb81f13bbd9688fd5404f5a2e4dc653dbc23121f77cc5ccf59742f80fb34db38b8788030c54b376eb9a2065ff nginx-tests-22f45bf99a9e.tar.gz +1cec9a322c40aa2b4ec6eb5bea78d7442880b0cff3a41ad171a3dc3157a6990baec6c8b9eda99ee02a9e51c0b933f13ef17431079a5ff409aaf84b912c7f4df7 nginx-njs-0.8.3.tar.gz 4c7a94aaebbb69599b0067e74f9f3db54ec383ca9499292fec5b875bb0b5859aa11dc14cef5664c94dd54aba231f31e85feacddc49f7622aa4d0fdb38709b6e1 nginx-dav-ext-module~pr-56.patch fdd66e433126e194a3ef22737993191a04fcc4c8caa044b27cb22bea0e7f16c8fdbc900553507d2bb541cdb82b542845a297db2a48c2460a38dd772d0ebfca9d nginx-dav-ext-module~pr-62.patch -fa96e91f495e9891c03730bcafd948e597e7c5d74f2d30df0a8483ae04f7b30c89065a994a0baa5245470f8991db5844b26da925b23ff26c178a384f5f1a887c nginx-module-vts~01-938c19d.patch -1c37e58921478325bb4dd608900588cda49d608e859127f45a1df73176b228b060bf71d9530dc1ad434a287c7a3225e8fe307fcf1bd15758f327436283db6fb9 nginx-module-vts~02-ad40022.patch -9f9cda2f3f163654100adf9cde892b26f80d3de30ffec9fcdb0b3c1a42856f9219ebb024fd4c156fd8c4c4a6c7b17faca89e16916128da232d9f3bc825d716ff nginx-module-vts~03-c08781c.patch -e87d9c8cbebc147881e3a40e6944acfe836f29eb7b393af0465b04dd27f1fa42f17ab63d2bcc75053812140a92dceca4eb4e1f0e35877919af4bd3cd0b2b771a nginx-module-vts~04-1a01a87.patch -dfcfd4dd14ccb205ea80d28eae8cadd123015d5eddc004a31b7742d8117c69cad1b56868ba94dd75e22b7ef9f44da21c02e5f5f1ecd4f90473cd9fa6128518c5 nginx-module-vts~05-ead62a0.patch -5d6b5b2f409d8183576d7d58f75a92b859922e6dc6d2e12d3abb92f3491eca4962231c1ba5860366fd83c86283711b79a19c3c7823f042267f14925d7a49cc78 nginx-module-vts~fix-uri-overflow.patch -90efd127fef5c89ae3148ab626a4061875d84af376d41b2bd36b2cf3188c2a244013bf1d3b09fbde51b68f59f0893e0bfaf929319aeb818904c8cdadd853c229 nginx-module-vts~cast-key-length-to-correct-type.patch -48689e09dc87f395095408127669c9f21a32c13b1b700ffad225db0c8920ae9e4f08e88332c12c01d96ded2d091ad2033885d81d5d7c9479745b10620f36562d nginx-module-vts~set-histogram-buckets-on-first-request.patch +c89fab6d3d4226e37f2a8d2122d825046fc9a787e464fc75351a19fbda5b47016ddb907e0a61241a007304af921e11a0715895ba7b6d4c1112afe816177ed02a no-werror.patch 09ec9f18323197eafa55ff68e8c836ad3dd830e6cd3bd4aeaf34e179ef3f72f734a0117288c1c58813aff59f3f1f0f29ccd772a672e17551e7a4fd0693a89c92 traffic-accounting-nginx-module~disable-stream-module.patch +5a7e72fc6ade460b725e6b91d5eafeb2792ad9832fbdb84ed868bd9a25d43116e42877df587b5f3885a1e38769f072ed4e8605393aca672d61bc71dd106d392b traffic-accounting-nginx-module~fix-memory-leak.patch ac0f912ae90e0083cc761a622290223edeed0bd32213bbe766d637ac2dfd9835d163e5d16ef28740cbad05d6d92cc418d62df3413c70b4f2c63db02f8ca1c7cc nginx_cookie_flag_module~fix-mem-allocations.patch 4db527d663dbe9e8b503c3cbaa4eae34b45990a5359b3bb98ce970c705faefcac98de49439f2557756a2be8e2e06acc67f98942de01674c498832d80c3cb90c3 njs~mktemp-busybox-compat.patch -df1d910d5a433ef8aa6620e46bd46cb82c45c840e35420bf81a76e5a868ac73ad88aa3934d1c11bcf004a88a9cd13bf69a96ee1b08540251b09903a30430b199 njs~nginx-1.20.x-compat.patch -9c5ee975dffa15b76688ef798371635f38f1e6773b143c738add26297878dddfc20ebf276e3871a60f28b197e8a70496ca17d4816c2136171978c157bb8e591f nginx.conf +eee45b82a594c4dfa5eecf94cf14cd247bd1dd7d627aa0a26666828b3e2da1a358da251a23f0b5feeb5f95f6ba205af6ead54c1e6bcb67f6d11149c0580de3af naxsi~assert.patch +7c35f51d73b6c20b6b9b030e76a4898752eae38e0f8e4001286a93633f0b1b11c39fd883116d86a323338027766d15d99c824a9cd9ffe934bea80b7af2a3070c naxsi~ff-header.patch +3e000d58e1259a656bb49af23623e6542ec994e3fe699e0005afde9ded5d505e7a174b206390b55ef639e53fd47516a86d88de675df86d550808da1d2732e683 naxsi~compat.patch +745e900573bc4d1ca6dd40da4743387f9ffaa764cca59591fcbfb1afe67980e529184f81a7cf8f047ddd1962a6a26ed65f1589d69a4f63f6f5701549f38a0652 nginx-upload-progress-module~fix.patch +24bcde151301ed41eaea65c3792219b25dbb76e3eddd74064937038326698b83d6620d2515a954984502ad2a1c6c53843680952c2ce813f2da34652047675ddf nginx-upload-progress-module~fix-http2.patch +37ad4288684d8918045d406f9f46510211413ab343e47aa149e52fd773ad95e6ff10a1b4e7cdd60acaf9231a0c6a935ab489c25880444f1a79e8624693fa166e ngx-fancyindex~fix-404-on-fs-root.patch +d54eb2152b2ddbf3e8956cb7b4634b1657635b21b9b4f91309d45a43553c9506ad70161d265e0840c1e84c9e04c0e89061600176ad2ec39311b5c0ce75e42f1e ngx-fancyindex~fix-missing-saturday.patch +abda15727e34178db2f8013a1c47e480ba323a3b3b88a44bbada0169b8ce66743911ec7b551272fc8540199070b62eadc78a19989f770794b43877c6743f573d nchan~dont-fail-redis-cluster-before-consensus.patch +2a87aee322a146a55e58d48636cdb6a3a182c308a6fe5327c9c2ece0487f669fe6b3f231f56e395e12b7c2ae2dd929a72a03dc18b1032ccc733184aac50d2381 nchan~fix-redis-race-condition.patch +ef57603bd65ffbbb216fd748dab0126d3df7aafdfa70dce0ea9ef91373df95269546ec2fcaa03f842a8db3a16879274184a23b18db17b4f9be3916aedacb7765 nginx-upload-module~fixes.patch +bae6c3153810bf6f460248668f2c48e332aba37081e25e45a1691344508530ef1be9acee4d52f506cb09510c4fce8d93ca3178ba45af771c54e37126f4f11b1b nginx-upload-module~fix-nginx-compat.patch +97ed3a3ad636a8853a993db3a33c67da303063e7ac43c20eeac6afb9f71adafa5dedf5f5f8c6705a256294c0566e3ac9f5fa41930048ad80b10a7d2a7d3c9b53 zstd-nginx-module~fix-infinite-loop.patch +c209a220b6afc9354a1c4c39817199327425485b3da44778d632cdfd1d95b8412c58ba9b27a5c96599e7a34cc039f5b7d914ad82153c610b27dfbe21fdcdca77 nginx.conf 0907f69dc2d3dc1bad3a04fb6673f741f1a8be964e22b306ef9ae2f8e736e1f5733a8884bfe54f3553fff5132a0e5336716250f54272c3fec2177d6ba16986f3 default.conf -f3321a45736697009817db335ad36d3f1d05f60d98ac90a943220cdd4c00c52632f018db6a6076d5431a483525aacc5725b87b765b590e2f63b3ef98c5b16bd8 stream.conf +426f0c317322af7cab152f2070398c7aa5c059276ba504617a212f1e060bbb1dd9edc54e62d4cf5f14e3678235351c808ebeabe8b122757c74b3f505e8427106 stream.conf 09b110693e3f4377349ccea3c43cb8199c8579ee351eae34283299be99fdf764b0c1bddd552e13e4d671b194501618b29c822e1ad53b34101a73a63954363dbb nginx.logrotate ee10a5687740dde0c3d18d8b3555f49fcdc6abfc0a3bc2de1de3be0e99951a346fe8027d916aab73071ecd4e2c50871e7c867aca3a7a0fd16e3374c5caed1c57 nginx.initd 0b9b9ed01ac077e334c034faa2679f6e26740fb3362eebf8cef82d22b2af2a3faaa53bae3c9e14af51cbf64720a7c66431905ca5cc43f978366456cc4e3b7f4a nginx.confd -de1e3349d8dd08e5982279b2219dc8a8006739f0409b8e0f5c50d93434beff1fbafba43e9c5ac85a5fab90afc5c0a7244a340610339c36f82f2cba7233e72de9 ngx_devel_kit-0.3.1.tar.gz +a255e3a4a9b902b3e15140dc88bbbb152b0a9cdc64604152de41e1b254e81aa2a1e2c95c06cb4905c1520886acf9070031d63913b53fe98b034f8adad2bccf61 ngx_devel_kit-0.3.3.tar.gz 0df34c3765e18dc5cc5a053d3a17dbee17a686a1f6e76ad057c262741c4e4465c66bcef86e627a19258f836cad5f14745bf046fd396b00960ad79ed20c2a07bb traffic-accounting-nginx-module-2.0.tar.gz -7c9fa9b76bc7cd2473ceae6d5ffb8de26993be9293ea967908d6c4550e086affa7016df4c936fb0b79f1142dc0aa1a5f2058d417e6433b5a3497a45d7e866e84 array-var-nginx-module-0.05.tar.gz +bc72158856a1be18a26ee04c6b5b0f0a20bcce688610a493bf31e2a133e7eb12e11f7c18197a09a72b1513f6a08348ee5281b9d5b84cf43603539040ebd23c26 array-var-nginx-module-0.06.tar.gz +56fe87b7b456856c167b47e5dfc579ac77f15487785dd8411397f6041561b991218518218b4adf3054392fdf1569469a4eff288706f320cf8d2c45b066ef780b nginx-auth-jwt-0.6.0.tar.gz 05a880d5e48ac83be84498ed41fb4750211b827a9d7541acfd6ef494e5205a6e853d5594bfec3ab4ae668ea3f803e4f4b0ba550c76811971c8e266e42663c56d ngx_brotli-1.0.0rc.tar.gz -a5e5f901823559d42421f9bc8f2aaba6cc3ad9ddfba2bbad154bb6b70e2001ed1bf25781c2117faeea3c20d824c74827cdf6b97f45eda343b60f50b964e69c40 ngx_cache_purge-2.5.2.tar.gz +aebc9b19a3e7dda3b57e6bd6d86a5ab66d25e05cf5c6c99c71234c789700eb9da8e29529b8b2abf3d775ff3c2610e695fc88e647738769f0d3730bcafc3be38b ngx_cache_purge-2.5.3.tar.gz 352cc3d033cc67ee34209f958dac13ada2147de429f4dd3da301c865d52970d80c8aa3c193f7fb28cf4854b88baff07b6efc3bae1fb813fe53d5956a87dfc81a nginx_cookie_flag_module-1.1.0.tar.gz d0193ba90f1ef46c4e470630c4394bdf99d94fd2e3bd8be6cb2ba1655ec59944b1269025f032b79dc2c6dad366e54389ef6a6da2ddeb91d535a4027f2162fbde nginx-dav-ext-module-3.0.0.tar.gz -240896b1c559a71ca6ca87136d8535edd25b1d65ebb80d46080ad41c09ed1cec9737828f9efe260782294d660cea66cf402f4e75bba3fed26f3a94de0ae2f89b echo-nginx-module-0.62.tar.gz +c325ac4e3f3f735739e156d8c7ada503b34475c62533b4830231ff1b42c25cb0c841aae06b3448b589c2ab35da8d211436ed194d6fd062cad925af8152c5e789 echo-nginx-module-0.63.tar.gz 399ce2690e85ee27802e8031954a1a3aa3fdc9246e17323a72a298d235931a8dbebdcb121ac8788e074872df0ef5b5a8a3d512b17fbe860b38f696ce42de3655 encrypted-session-nginx-module-0.09.tar.gz c208cdf3e245527d7b313f9ef1f5d36ca26e3bdafe67df56492a13b7726587538665e5d9fd50f295fc933f218dc33394f2fe442713d15631701dbfc4a156799b ngx-fancyindex-0.5.2.tar.gz 18dea21e5ae2647bea1fc448058a1b773c936917245edef8d861d5e23ed92e9a3b1ec4ef43ffb2ece7b5899d787910adcf4fbd39f84d7e8d7c54759e2fee5b72 ngx_http_geoip2_module-3.4.tar.gz -13165b1b8d4be281b8bd2404fa48d456013d560bace094c81da08a35dc6a4f025a809a3ae3a42be6bbf67abbcbe41e0730aba06f905220f3baeb01e1192a7d37 headers-more-nginx-module-0.33.tar.gz +0cc2fffe506194d439e3669644d41b7943e2c3cffa3483eb70b92067930b358d506a14646eff8362b191a11c624db29f6b53d830876929dcb4ce1c9d7b2bc40d headers-more-nginx-module-0.37.tar.gz +45b8f107a492f415f5053b9b95d3dad481d5736c603b87c1342541214e89b9acbe37925f93acc396782406232e607879b52f9bb480f9021c10d405b832298022 nginx-keyval-0.2.0.tar.gz 015a358d987476bb61302fbbe1cb105f5314edc1a8b7ee6310aae697f755c79fcb1834ff561fced054c8cd5624f5387fcc1de729731ccd70662f2eb72bcdc174 nginx-log-zmq-1.0.0.tar.gz -c7594be48a3a5a8cc7bbda9288cb836c4c854ad22f91766dba944316d471ab8857a6b6a52813eb041af81939df73614db54ccd3ed35af87036d76317ebbe2e97 lua-nginx-module-0.10.21.tar.gz +9abf00844ef00ce1dc5ff08d6fe4ddccf843f2ad2de6fd450854b38a66b45add71e814205dba9b19225b9165e67eb93578e83e5fe37af4e0c891e61e6a6bfb3d lua-nginx-module-0.10.26.tar.gz 72887c4490854b099cb26bb3f840073a36b0d812bde4486f04dc1be182ca74f0d1e3fd709e77c240c2dcf37665f74cf04e188ea9efe8e127c6789b27b487d0cd lua-upstream-nginx-module-0.07.tar.gz d7aac69b5eceeb1b0db4741201159ade1e0e7f6f7c3e8c4afa2f8959c6c00c3b5285d5185747c2fb0b1400efda02e96799836315e7e492bb4a059b14acb2142d naxsi-1.3.tar.gz -c8cd3eb0b06fc0f17b5a9013d32f5a6d5a8252015b3ac27fbf74a7a1b97bc7ae78c5c8cdd7372e36f5f9d137b59635f007d836746282c85c4a972b6984ba2bef nchan-1.3.0.tar.gz +0f1c25d460dcf4e3407a1ef4bfcefe17eba7b0ff250f267e5bde0eb4298e9596c1e6992fc58fe35d8420888065353bf3883a1f1bbc5e607a00128992eb1ee6d2 nchan-1.3.6.tar.gz d6ca250db8de93edbd7875afca35e73cecdaf82132d1a7ee933cf94c6b8afa8e629e9e647a9321f2bc1fbb92137ec0d32dcd89b82ac5fae31e342537fb7e0431 redis2-nginx-module-0.15.tar.gz 1ff4c947538a5bd5f9d6adcd87b37f2702f5cc90e3342bc08359cbe8f290b705a3a2daa3dedfb1df3ce4bc19478c8fcac07081c4a53a804fc2862d50078278dc set-misc-nginx-module-0.33.tar.gz -1730845ea2e52be8c2f6cfceb2894304c5a07959a96940bb1617ee0e7cf81d22283304f411d9a219ddb71e4d9a66012bba0f6f5574d101aeb3c406f26c5d6a4e nginx-http-shibboleth-2.0.1.tar.gz +0f0c5167e999ffad0caa816d4b7d0a121f0598d578391834fe3293a3e023453d91b36ffc32a431ff3af3f9f376d2d78703998560094d20643b4049c2fec84bda nginx-http-shibboleth-2.0.2.tar.gz c3a7dd29c4a4e47d396b19622a290a04d4cceb97c1b8a508bc984eb8c81d17da4bf5789514bb996987f8343bc801ee4457a86a274bde98b49a809afdfc04cbde ngx_http_untar_module-1.1.tar.gz a0da355888398f86a6b5d065e58c05f9e057589ee785be9f515d77d7a020ae5a7b0656f5af30fb3b026f457326db2e26f4fed29026221ec5fc8156ef8586da25 nginx-upload-module-2.3.0.tar.gz c31c46344d49704389722325a041b9cd170fa290acefe92cfc572c07f711cd3039de78f28df48ca7dcb79b2e4bbe442580aaaf4d92883fd3a14bf41d66dd9d8c nginx-upload-progress-module-0.9.2.tar.gz 8adb7453c27748f4e685e3352e9b318b408da818754dc5b6244e908423941a8ba337561104f6e481f2553cbc0e334dcea73b57f8e810a9d6e974bb69ff8859e5 nginx-upstream-fair-0.1.3.tar.gz -bbf3f4808f17fa797fa0c27bc1351098aa5d6b5d227376a0ab01b4f424942ec5ad9f5c09c7af284345988b119268bf579b24065fb6bc6bc2f2b2392e918f09bc ngx_upstream_jdomain-1.4.0.tar.gz -4ffbd9f1f641e4304ffda2dfeee627d27fee69ca4f55cf7f5286c415a5962b5d332e69a73be026ebe253c1f7253c5843ea6cffb2663bded0e934ea0015a89bb0 nginx-vod-module-1.29.tar.gz -86b980095b3b80c8dce2e355db514cb4b3039c8408a2f5ca6df9e105d5462952fddd70f6581ec6aa2763e560b591664c27eefd978c4ea777b1f1f808bc60d4ec nginx-module-vts-0.1.18.tar.gz -92e1e5aa570b68a19bb718817f864c4347f6dc89f90d828071ab3d06c784cc2786674d9d64fffef8c23749d0a653f2eb996b412ab10015eea1ed895d81268ce1 mod_zip-1.2.0.tar.gz +2ac8351d8d325353534c87e0ef6034a5d3897411895b4e03f22fa06343337d86897331797541ab9201cd7dc8b0376d6d76eb4458849900348f5e199e0b0bd357 ngx_upstream_jdomain-1.5.0.tar.gz +29ef77f1bbdb2410ff317ebdd7434f31b8ec370ae6b617b92e745e87c11bc820b451181d1d2b57156b414348da14ac448b689b32b17ab418144292eda094512d nginx-vod-module-1.33.tar.gz +7295c1af3267b067793fb88e3d3a74fdba5187742141d447f597b8d726c455bfb163209eca5d00b00a57adc3f627078b404a43f5318f910a68c6aeaffb189b1c nginx-module-vts-0.2.2.tar.gz +8c5dda14da06ef776fe2b496c2f1b80d2c25c9269309aa560a006c369044c52917024a90f897b7212b2409a874bf2e0a3ab2dbc1e10ad84fa64f54f1f4df3d0d mod_zip-1.3.0.tar.gz +6feb544face95121ea076db5df8ca34854085b57602e732c7ba427be5e3f2bf668729d45497a2c91212f98ed8a2c347aa8778a54594f5d241e39e094a2556e4c zstd-nginx-module-0.1.1.tar.gz 3f8c803221854c4b1a06aadc6313fbfec74bd7179c0ee51d4365b26ffa8875881a6e1e48f777a9c9efbb9170ab7478a82920d5448a2c2df485503d37bb03ab81 nginx-rtmp-module-1.2.2.tar.gz " diff --git a/main/nginx/CVE-2023-44487.patch b/main/nginx/CVE-2023-44487.patch new file mode 100644 index 00000000000..b9fcfbf7d6c --- /dev/null +++ b/main/nginx/CVE-2023-44487.patch @@ -0,0 +1,71 @@ + +# HG changeset patch +# User Maxim Dounin <mdounin@mdounin.ru> +# Date 1696940019 -10800 +# Node ID cdda286c0f1b4b10f30d4eb6a63fefb9b8708ecc +# Parent 3db945fda515014d220151046d02f3960bcfca0a +HTTP/2: per-iteration stream handling limit. + +To ensure that attempts to flood servers with many streams are detected +early, a limit of no more than 2 * max_concurrent_streams new streams per one +event loop iteration was introduced. This limit is applied even if +max_concurrent_streams is not yet reached - for example, if corresponding +streams are handled synchronously or reset. + +Further, refused streams are now limited to maximum of max_concurrent_streams +and 100, similarly to priority_limit initial value, providing some tolerance +to clients trying to open several streams at the connection start, yet +low tolerance to flooding attempts. + +diff -r 3db945fda515 -r cdda286c0f1b src/http/v2/ngx_http_v2.c +--- a/src/http/v2/ngx_http_v2.c Fri Sep 22 19:23:57 2023 +0400 ++++ b/src/http/v2/ngx_http_v2.c Tue Oct 10 15:13:39 2023 +0300 +@@ -347,6 +347,7 @@ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 read handler"); + + h2c->blocked = 1; ++ h2c->new_streams = 0; + + if (c->close) { + c->close = 0; +@@ -1284,6 +1285,14 @@ + goto rst_stream; + } + ++ if (h2c->new_streams++ >= 2 * h2scf->concurrent_streams) { ++ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, ++ "client sent too many streams at once"); ++ ++ status = NGX_HTTP_V2_REFUSED_STREAM; ++ goto rst_stream; ++ } ++ + if (!h2c->settings_ack + && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) + && h2scf->preread_size < NGX_HTTP_V2_DEFAULT_WINDOW) +@@ -1349,6 +1358,12 @@ + + rst_stream: + ++ if (h2c->refused_streams++ > ngx_max(h2scf->concurrent_streams, 100)) { ++ ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, ++ "client sent too many refused streams"); ++ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_NO_ERROR); ++ } ++ + if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, status) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } +diff -r 3db945fda515 -r cdda286c0f1b src/http/v2/ngx_http_v2.h +--- a/src/http/v2/ngx_http_v2.h Fri Sep 22 19:23:57 2023 +0400 ++++ b/src/http/v2/ngx_http_v2.h Tue Oct 10 15:13:39 2023 +0300 +@@ -131,6 +131,8 @@ + ngx_uint_t processing; + ngx_uint_t frames; + ngx_uint_t idle; ++ ngx_uint_t new_streams; ++ ngx_uint_t refused_streams; + ngx_uint_t priority_limit; + + size_t send_window; + diff --git a/main/nginx/naxsi~assert.patch b/main/nginx/naxsi~assert.patch new file mode 100644 index 00000000000..35ae171d48a --- /dev/null +++ b/main/nginx/naxsi~assert.patch @@ -0,0 +1,23 @@ +Patch-Source: https://github.com/nbs-system/naxsi/commit/aa9da98b1b9b52e5d95bbc28dc8126c0920cb4cb + +From aa9da98b1b9b52e5d95bbc28dc8126c0920cb4cb Mon Sep 17 00:00:00 2001 +From: Giovanni <561184+wargio@users.noreply.github.com> +Date: Fri, 18 Dec 2020 11:31:42 +0100 +Subject: [PATCH] Fix #541 - Removing useless assert. + +--- + naxsi_src/naxsi_runtime.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/naxsi_src/naxsi_runtime.c b/naxsi_src/naxsi_runtime.c +index eccdce3e..28e0b29d 100644 +--- a/naxsi_src/naxsi_runtime.c ++++ b/naxsi_src/naxsi_runtime.c +@@ -1073,7 +1073,6 @@ ngx_http_nx_log(ngx_http_request_ctx_t* ctx, + ** don't handle uri > 4k, string will be split + */ + +- assert(strlen(fmt_config) != 0); + sub = snprintf((char*)fragment->data, + sz_left, + fmt_base, diff --git a/main/nginx/naxsi~compat.patch b/main/nginx/naxsi~compat.patch new file mode 100644 index 00000000000..ac9a2d64064 --- /dev/null +++ b/main/nginx/naxsi~compat.patch @@ -0,0 +1,133 @@ +Patch-Source: https://github.com/nbs-system/naxsi/commit/d714f1636ea49a9a9f4f06dba14aee003e970834 + +From d714f1636ea49a9a9f4f06dba14aee003e970834 Mon Sep 17 00:00:00 2001 +From: Danila Vershinin <ciapnz@gmail.com> +Date: Mon, 27 Jun 2022 19:45:00 +0300 +Subject: [PATCH] Fixes NGINX >= v.1.23.0 (all credits @lubomudr) (#598) + +--- + naxsi_src/naxsi.h | 4 ++-- + naxsi_src/naxsi_runtime.c | 42 ++++++++++++++++++++++++++++++++------- + 2 files changed, 37 insertions(+), 9 deletions(-) + +diff --git a/naxsi_src/naxsi.h b/naxsi_src/naxsi.h +index b2f5c1a5..8c1939e1 100644 +--- a/naxsi_src/naxsi.h ++++ b/naxsi_src/naxsi.h +@@ -9,12 +9,12 @@ + + #define NAXSI_VERSION "1.3" + ++#include <ngx_config.h> ++#include <ngx_core.h> + #include "ext/libinjection/libinjection_sqli.h" + #include "ext/libinjection/libinjection_xss.h" + #include <ctype.h> + #include <nginx.h> +-#include <ngx_config.h> +-#include <ngx_core.h> + #include <ngx_event.h> + #include <ngx_http.h> + #include <ngx_http_core_module.h> +diff --git a/naxsi_src/naxsi_runtime.c b/naxsi_src/naxsi_runtime.c +index 784852b0..6b55d2b3 100644 +--- a/naxsi_src/naxsi_runtime.c ++++ b/naxsi_src/naxsi_runtime.c +@@ -4,8 +4,8 @@ + * Licensed under GNU GPL v3.0 – See the LICENSE notice for details + */ + +-#include "assert.h" + #include "naxsi.h" ++#include "assert.h" + #include "naxsi_macros.h" + #include "naxsi_net.h" + +@@ -2912,20 +2912,20 @@ ngx_http_naxsi_data_parse(ngx_http_request_ctx_t* ctx, ngx_http_request_t* r) + /* and the presence of data to parse */ + r->request_body && ((!ctx->block || ctx->learning) && !ctx->drop)) + ngx_http_naxsi_body_parse(ctx, r, cf, main_cf); ++#if (NGX_HTTP_X_FORWARDED_FOR) + ngx_str_t tag; + tag.len = 15; + tag.data = ngx_pcalloc(r->pool, tag.len + 1); + if (tag.data) + memcpy(tag.data, "x-forwarded-for", 15); ++#if (nginx_version < 1023000) + unsigned int n = 0; + ngx_table_elt_t** h = NULL; + ngx_array_t a; +-#if (NGX_HTTP_X_FORWARDED_FOR) + if (r->headers_in.x_forwarded_for.nelts >= 1) { + a = r->headers_in.x_forwarded_for; + n = a.nelts; + } +-#endif + if (n >= 1) + h = a.elts; + if (n >= 1) { +@@ -2933,6 +2933,16 @@ ngx_http_naxsi_data_parse(ngx_http_request_ctx_t* ctx, ngx_http_request_t* r) + + ngx_http_naxsi_update_current_ctx_status(ctx, cf, r, &tag, (ngx_str_t*)h[0]->value.data); + } ++#else ++ ngx_table_elt_t* xff = NULL; ++ if (r->headers_in.x_forwarded_for != NULL) { ++ xff = r->headers_in.x_forwarded_for; ++ ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xfor %s", xff->value.data); ++ ++ ngx_http_naxsi_update_current_ctx_status(ctx, cf, r, &tag, (ngx_str_t*)xff->value.data); ++ } ++#endif ++#endif + } + + void +@@ -2947,19 +2957,20 @@ ngx_http_naxsi_update_current_ctx_status(ngx_http_request_ctx_t* ctx, + ngx_http_check_rule_t* cr; + + ngx_http_special_score_t* sc; +- unsigned int n = 0; + + NX_DEBUG(_debug_custom_score, NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "XX-custom check rules"); + + int ignore = 0; +- ngx_table_elt_t** h; +- ngx_array_t a; + + ctx->ignore = 0; + + /*cr, sc, cf, ctx*/ + if (cf->check_rules && ctx->special_scores) { + #if (NGX_HTTP_X_FORWARDED_FOR) ++#if (nginx_version < 1023000) ++ unsigned int n = 0; ++ ngx_table_elt_t** h; ++ ngx_array_t a; + if (r->headers_in.x_forwarded_for.nelts >= 1) { + a = r->headers_in.x_forwarded_for; + n = a.nelts; +@@ -2978,6 +2989,23 @@ ngx_http_naxsi_update_current_ctx_status(ngx_http_request_ctx_t* ctx, + ignore = nx_can_ignore_ip(&ip, cf) || nx_can_ignore_cidr(&ip, cf); + } + } else ++#else ++ ngx_table_elt_t* xff; ++ if (r->headers_in.x_forwarded_for != NULL) { ++ xff = r->headers_in.x_forwarded_for; ++ NX_DEBUG(_debug_whitelist_ignore, ++ NGX_LOG_DEBUG_HTTP, ++ r->connection->log, ++ 0, ++ "XX- lookup ignore X-Forwarded-For: %s", ++ xff->value.data); ++ ngx_str_t ip; ++ ip.len = strlen((char*)xff->value.data); ++ ip.data = ngx_pcalloc(r->pool, ip.len + 1); ++ memcpy(ip.data, xff->value.data, ip.len); ++ ignore = nx_can_ignore_ip(&ip, cf) || nx_can_ignore_cidr(&ip, cf); ++ } else ++#endif + #endif + { + ngx_str_t* ip = &r->connection->addr_text; diff --git a/main/nginx/naxsi~ff-header.patch b/main/nginx/naxsi~ff-header.patch new file mode 100644 index 00000000000..b6ed47760d8 --- /dev/null +++ b/main/nginx/naxsi~ff-header.patch @@ -0,0 +1,62 @@ +Patch-Source: https://github.com/nbs-system/naxsi/commit/296583f06ba5c43cc859e01fd3c0ae1271eef0ce + +From 296583f06ba5c43cc859e01fd3c0ae1271eef0ce Mon Sep 17 00:00:00 2001 +From: Fabrice Fontaine <fontaine.fabrice@gmail.com> +Date: Sat, 14 Aug 2021 12:57:28 +0200 +Subject: [PATCH] naxsi_src/naxsi_runtime.c: fix build without x_forwarded_for + (#568) + +x_forwarded_for is not available if realip, geo, geoip or proxy modules +aren't enabled resulting in the following build failure since version +1.1a and +https://github.com/nbs-system/naxsi/commit/07a056ccd36bc3c5c40dc17991db226cb8cf6241: + +/home/buildroot/autobuild/instance-3/output-1/build/nginx-naxsi-1.3/naxsi_src/naxsi_runtime.c: In function 'ngx_http_naxsi_data_parse': +/home/buildroot/autobuild/instance-3/output-1/build/nginx-naxsi-1.3/naxsi_src/naxsi_runtime.c:2846:20: error: 'ngx_http_headers_in_t' has no member named 'x_forwarded_for' + if (r->headers_in.x_forwarded_for.nelts >= 1) { + ^ + +Fixes: + - http://autobuild.buildroot.org/results/cdbc1536f6b5de3d4c836efa2f0dcaf0cdbb1462 + +Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> +--- + naxsi_src/naxsi_runtime.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/naxsi_src/naxsi_runtime.c b/naxsi_src/naxsi_runtime.c +index 28e0b29d..6a723d24 100644 +--- a/naxsi_src/naxsi_runtime.c ++++ b/naxsi_src/naxsi_runtime.c +@@ -2842,10 +2842,12 @@ ngx_http_naxsi_data_parse(ngx_http_request_ctx_t* ctx, ngx_http_request_t* r) + unsigned int n = 0; + ngx_table_elt_t** h = NULL; + ngx_array_t a; ++#if (NGX_HTTP_X_FORWARDED_FOR) + if (r->headers_in.x_forwarded_for.nelts >= 1) { + a = r->headers_in.x_forwarded_for; + n = a.nelts; + } ++#endif + if (n >= 1) + h = a.elts; + if (n >= 1) { +@@ -2879,6 +2881,7 @@ ngx_http_naxsi_update_current_ctx_status(ngx_http_request_ctx_t* ctx, + + /*cr, sc, cf, ctx*/ + if (cf->check_rules && ctx->special_scores) { ++#if (NGX_HTTP_X_FORWARDED_FOR) + if (r->headers_in.x_forwarded_for.nelts >= 1) { + a = r->headers_in.x_forwarded_for; + n = a.nelts; +@@ -2896,7 +2899,9 @@ ngx_http_naxsi_update_current_ctx_status(ngx_http_request_ctx_t* ctx, + memcpy(ip.data, h[0]->value.data, ip.len); + ignore = nx_can_ignore_ip(&ip, cf) || nx_can_ignore_cidr(&ip, cf); + } +- } else { ++ } else ++#endif ++ { + ngx_str_t* ip = &r->connection->addr_text; + NX_DEBUG(_debug_whitelist_ignore, + NGX_LOG_DEBUG_HTTP, diff --git a/main/nginx/nchan~dont-fail-redis-cluster-before-consensus.patch b/main/nginx/nchan~dont-fail-redis-cluster-before-consensus.patch new file mode 100644 index 00000000000..114ff925b97 --- /dev/null +++ b/main/nginx/nchan~dont-fail-redis-cluster-before-consensus.patch @@ -0,0 +1,49 @@ +Patch-Source: https://github.com/slact/nchan/commit/ed27e02adcac66ce73f5db387596fa063362ac6e +-- +From ed27e02adcac66ce73f5db387596fa063362ac6e Mon Sep 17 00:00:00 2001 +From: Fabio Urquiza <fabiorush@gmail.com> +Date: Wed, 1 Feb 2023 14:48:47 +0000 +Subject: [PATCH] Don't fail redis cluster nodes before consensus is reached + +diff --git a/src/store/redis/redis_nodeset.c b/src/store/redis/redis_nodeset.c +index 39fdd396..2c4646c4 100644 +--- a/src/store/redis/redis_nodeset.c ++++ b/src/store/redis/redis_nodeset.c +@@ -1052,6 +1052,9 @@ static void nodeset_cluster_check_event_callback(redisAsyncContext *ac, void *re + + for(i=0; i<n; i++) { + l = &lines[i]; ++ if(l->maybe_failed) { ++ nodeset_log_warning(ns, "Ignoring 'fail?' state reported by %V:%d for node %V", &node->connect_params.hostname, node->connect_params.port, &l->address); ++ } + if(l->failed && nodeset_node_remove_failed(ns, &l->id)) { + failed_nodes++; + continue; +diff --git a/src/store/redis/redis_nodeset_parser.c b/src/store/redis/redis_nodeset_parser.c +index 7ce0037b..e3052dc2 100644 +--- a/src/store/redis/redis_nodeset_parser.c ++++ b/src/store/redis/redis_nodeset_parser.c +@@ -132,7 +132,10 @@ static char *nodeset_parser_scan_cluster_nodes_line(const char *line, cluster_no + l->slot_ranges_count = 0; + l->master = 0; + } +- l->failed = nchan_ngx_str_substr((&l->flags), "fail"); ++ l->maybe_failed = nchan_ngx_str_substr((&l->flags), "fail?"); ++ if(!l->maybe_failed) ++ l->failed = nchan_ngx_str_substr((&l->flags), "fail"); ++ + l->self = nchan_ngx_str_substr((&l->flags), "myself"); + l->noaddr = nchan_ngx_str_substr((&l->flags), "noaddr"); + l->handshake = nchan_ngx_str_substr((&l->flags), "handshake"); +diff --git a/src/store/redis/redis_nodeset_parser.h b/src/store/redis/redis_nodeset_parser.h +index 5d564b62..a14ae146 100644 +--- a/src/store/redis/redis_nodeset_parser.h ++++ b/src/store/redis/redis_nodeset_parser.h +@@ -28,6 +28,7 @@ typedef struct { + unsigned master:1; + unsigned noaddr:1; + unsigned failed:1; ++ unsigned maybe_failed:1; + unsigned handshake:1; + unsigned self:1; + } cluster_nodes_line_t; diff --git a/main/nginx/nchan~fix-redis-race-condition.patch b/main/nginx/nchan~fix-redis-race-condition.patch new file mode 100644 index 00000000000..75d5b83a050 --- /dev/null +++ b/main/nginx/nchan~fix-redis-race-condition.patch @@ -0,0 +1,270 @@ +Patch-Source: https://github.com/slact/nchan/commit/cc705a948cf6797f669b64649605f007f6f26a42 +-- +From cc705a948cf6797f669b64649605f007f6f26a42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?F=C3=A1bio=20Urquiza?= <fabiorush@gmail.com> +Date: Mon, 20 Mar 2023 10:31:33 -0300 +Subject: [PATCH] Fix redis connection race condition on many workers (#666) + +diff --git a/src/nchan_module.c b/src/nchan_module.c +index ad6f3534..95b51521 100644 +--- a/src/nchan_module.c ++++ b/src/nchan_module.c +@@ -39,7 +39,6 @@ int nchan_redis_stats_enabled = 0; + + + static void nchan_publisher_body_handler(ngx_http_request_t *r); +-static void nchan_publisher_unavailable_body_handler(ngx_http_request_t *r); + + //#define DEBUG_LEVEL NGX_LOG_WARN + //#define DEBUG_LEVEL NGX_LOG_DEBUG +@@ -746,18 +745,6 @@ ngx_int_t nchan_pubsub_handler(ngx_http_request_t *r) { + return NGX_OK; + } + +- if(cf->redis.enabled && !nchan_store_redis_ready(cf)) { +- //using redis, and it's not ready yet +- if(r->method == NGX_HTTP_POST || r->method == NGX_HTTP_PUT) { +- //discard request body before responding +- nchan_http_publisher_handler(r, nchan_publisher_unavailable_body_handler); +- } +- else { +- nchan_respond_status(r, NGX_HTTP_SERVICE_UNAVAILABLE, NULL, NULL, 0); +- } +- return NGX_OK; +- } +- + if(cf->pub.websocket || cf->pub.http) { + char *err; + if(!nchan_parse_message_buffer_config(r, cf, &err)) { +@@ -841,6 +828,13 @@ ngx_int_t nchan_pubsub_handler(ngx_http_request_t *r) { + #if FAKESHARD + memstore_sub_debug_start(); + #endif ++ ++ if(cf->redis.enabled && ngx_process_slot == memstore_channel_owner(channel_id) && !nchan_store_redis_ready(cf)) { ++ //using redis, and it's not ready yet ++ nchan_respond_status(r, NGX_HTTP_SERVICE_UNAVAILABLE, NULL, NULL, 0); ++ return NGX_OK; ++ } ++ + if((msg_id = nchan_subscriber_get_msg_id(r)) == NULL) { + goto bad_msgid; + } +@@ -1249,11 +1243,6 @@ static ngx_int_t nchan_publisher_body_authorize_handler(ngx_http_request_t *r, v + return NGX_OK; + } + +-static void nchan_publisher_unavailable_body_handler(ngx_http_request_t *r) { +- nchan_http_finalize_request(r, NGX_HTTP_SERVICE_UNAVAILABLE); +- return; +-} +- + static void nchan_publisher_body_handler(ngx_http_request_t *r) { + ngx_str_t *channel_id; + nchan_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_nchan_module); +diff --git a/src/store/memory/ipc-handlers.c b/src/store/memory/ipc-handlers.c +index 55df2fd3..bee7c1d9 100644 +--- a/src/store/memory/ipc-handlers.c ++++ b/src/store/memory/ipc-handlers.c +@@ -47,6 +47,8 @@ + L(benchmark_finish_reply) \ + L(redis_stats_request) \ + L(redis_stats_reply) \ ++ L(redis_conn_ready) \ ++ L(redis_conn_ready_reply) \ + + + +@@ -1205,6 +1207,35 @@ static void receive_redis_stats_reply(ngx_int_t sender, redis_stats_request_data + shm_free(nchan_store_memory_shmem, data->stats); + } + ++////////// REDIS CONN READY DATA //////////////// ++typedef struct { ++ ngx_int_t ready; ++ nchan_loc_conf_t *cf; ++ callback_pt callback; ++ void *privdata; ++} redis_conn_ready_data_t; ++ ++ngx_int_t memstore_ipc_send_redis_conn_ready(ngx_int_t dst, nchan_loc_conf_t *cf, callback_pt callback, void* privdata) { ++ DBG("send redis_conn_ready to %i", dst); ++ redis_conn_ready_data_t data; ++ DEBUG_MEMZERO(&data); ++ data.ready = 0; ++ data.cf = cf; ++ data.callback = callback; ++ data.privdata = privdata; ++ ++ return ipc_cmd(redis_conn_ready, dst, &data); ++} ++ ++static void receive_redis_conn_ready(ngx_int_t sender, redis_conn_ready_data_t *d) { ++ DBG("received redis_conn_ready request for privdata %p", d->privdata); ++ d->ready = nchan_store_redis_ready(d->cf); ++ ipc_cmd(redis_conn_ready_reply, sender, d); ++} ++ ++static void receive_redis_conn_ready_reply(ngx_int_t sender, redis_conn_ready_data_t *d) { ++ d->callback(d->ready, NULL, d->privdata); ++} + + #define MAKE_ipc_cmd_handler(val) [offsetof(ipc_handlers_t, val)/sizeof(ipc_handler_pt)] = (ipc_handler_pt )receive_ ## val, + static ipc_handler_pt ipc_cmd_handler[] = { +diff --git a/src/store/memory/ipc-handlers.h b/src/store/memory/ipc-handlers.h +index e22c4a0d..7fd9c19c 100644 +--- a/src/store/memory/ipc-handlers.h ++++ b/src/store/memory/ipc-handlers.h +@@ -26,3 +26,5 @@ ngx_int_t memstore_ipc_broadcast_benchmark_finish(void); + ngx_int_t memstore_ipc_broadcast_benchmark_abort(void); + + ngx_int_t memstore_ipc_broadcast_redis_stats_request(void *nodeset, callback_pt cb, void *pd); ++ ++ngx_int_t memstore_ipc_send_redis_conn_ready(ngx_int_t dst, nchan_loc_conf_t *cf, callback_pt callback, void* privdata); +\ No newline at end of file +diff --git a/src/store/memory/memstore.c b/src/store/memory/memstore.c +index f8b4ee8b..e1e1c7a8 100755 +--- a/src/store/memory/memstore.c ++++ b/src/store/memory/memstore.c +@@ -2079,12 +2079,13 @@ static void subscribe_data_free(subscribe_data_t *d) { + #define SUB_CHANNEL_NOTSURE 2 + + static ngx_int_t nchan_store_subscribe_channel_existence_check_callback(ngx_int_t channel_status, void* _, subscribe_data_t *d); +-static ngx_int_t nchan_store_subscribe_continued(ngx_int_t channel_status, void* _, subscribe_data_t *d); ++static ngx_int_t nchan_store_subscribe_stage2(ngx_int_t continue_subscription, void* _, subscribe_data_t *d); ++static ngx_int_t nchan_store_subscribe_stage3(ngx_int_t channel_status, void* _, subscribe_data_t *d); + + static ngx_int_t nchan_store_subscribe(ngx_str_t *channel_id, subscriber_t *sub) { + ngx_int_t owner = memstore_channel_owner(channel_id); + subscribe_data_t *d = subscribe_data_alloc(sub->cf->redis.enabled ? -1 : owner); +- ++ + assert(d != NULL); + + d->channel_owner = owner; +@@ -2095,24 +2096,51 @@ static ngx_int_t nchan_store_subscribe(ngx_str_t *channel_id, subscriber_t *sub) + d->channel_exists = 0; + d->group_channel_limit_pass = 0; + d->msg_id = sub->last_msgid; +- +- if(sub->cf->subscribe_only_existing_channel || sub->cf->max_channel_subscribers > 0) { ++ ++ if(sub->cf->redis.enabled && memstore_slot() != owner) { ++ ngx_int_t rc; + sub->fn->reserve(sub); + d->reserved = 1; +- if(memstore_slot() != owner) { +- ngx_int_t rc; +- rc = memstore_ipc_send_channel_existence_check(owner, channel_id, sub->cf, (callback_pt )nchan_store_subscribe_channel_existence_check_callback, d); +- if(rc == NGX_DECLINED) { // out of memory +- nchan_store_subscribe_channel_existence_check_callback(SUB_CHANNEL_UNAUTHORIZED, NULL, d); +- return NGX_ERROR; ++ rc = memstore_ipc_send_redis_conn_ready(d->channel_owner, sub->cf, (callback_pt)nchan_store_subscribe_stage2, d); ++ if(rc == NGX_DECLINED) { // out of memory ++ nchan_store_subscribe_stage2(0, NULL, d); ++ return NGX_ERROR; ++ } ++ } else { ++ return nchan_store_subscribe_stage2(1, NULL, d); ++ } ++ return NGX_OK; ++} ++ ++static ngx_int_t nchan_store_subscribe_stage2(ngx_int_t continue_subscription, void* _, subscribe_data_t *d) { ++ if(continue_subscription) { ++ if(d->sub->cf->subscribe_only_existing_channel || d->sub->cf->max_channel_subscribers > 0) { ++ if(!d->reserved) { ++ d->sub->fn->reserve(d->sub); ++ d->reserved = 1; ++ } ++ if(memstore_slot() != d->channel_owner) { ++ ngx_int_t rc; ++ rc = memstore_ipc_send_channel_existence_check(d->channel_owner, d->channel_id, d->sub->cf, (callback_pt )nchan_store_subscribe_channel_existence_check_callback, d); ++ if(rc == NGX_DECLINED) { // out of memory ++ nchan_store_subscribe_channel_existence_check_callback(SUB_CHANNEL_UNAUTHORIZED, NULL, d); ++ return NGX_ERROR; ++ } ++ } ++ else { ++ return nchan_store_subscribe_stage3(SUB_CHANNEL_NOTSURE, NULL, d); + } + } + else { +- return nchan_store_subscribe_continued(SUB_CHANNEL_NOTSURE, NULL, d); ++ return nchan_store_subscribe_stage3(SUB_CHANNEL_AUTHORIZED, NULL, d); + } +- } +- else { +- return nchan_store_subscribe_continued(SUB_CHANNEL_AUTHORIZED, NULL, d); ++ } else { ++ //using redis, and it's not ready yet ++ if(d->sub->fn->release(d->sub, 0) == NGX_OK) { ++ d->reserved = 0; ++ nchan_respond_status(d->sub->request, NGX_HTTP_SERVICE_UNAVAILABLE, NULL, NULL, 0); ++ } ++ subscribe_data_free(d); + } + return NGX_OK; + } +@@ -2120,7 +2148,7 @@ static ngx_int_t nchan_store_subscribe(ngx_str_t *channel_id, subscriber_t *sub) + static ngx_int_t nchan_store_subscribe_channel_existence_check_callback(ngx_int_t channel_status, void* _, subscribe_data_t *d) { + if(d->sub->fn->release(d->sub, 0) == NGX_OK) { + d->reserved = 0; +- return nchan_store_subscribe_continued(channel_status, _, d); ++ return nchan_store_subscribe_stage3(channel_status, _, d); + } + else {//don't go any further, the sub has been deleted + subscribe_data_free(d); +@@ -2143,7 +2171,7 @@ static ngx_int_t redis_subscribe_channel_existence_callback(ngx_int_t status, vo + /* + else if (cf->max_channel_subscribers > 0) { + // don't check this anymore -- a total subscribers count check is less +- // useful as a per-instance check, which is handled in nchan_store_subscribe_continued ++ // useful as a per-instance check, which is handled in nchan_store_subscribe_stage3 + // shared total subscriber count check can be re-enabled with another config setting + channel_status = channel->subscribers >= cf->max_channel_subscribers ? SUB_CHANNEL_UNAUTHORIZED : SUB_CHANNEL_AUTHORIZED; + } +@@ -2152,7 +2180,7 @@ static ngx_int_t redis_subscribe_channel_existence_callback(ngx_int_t status, vo + channel_status = SUB_CHANNEL_AUTHORIZED; + + } +- nchan_store_subscribe_continued(channel_status, NULL, data); ++ nchan_store_subscribe_stage3(channel_status, NULL, data); + } + else { + //error!! +@@ -2196,7 +2224,7 @@ static ngx_int_t group_subscribe_channel_limit_reached(ngx_int_t rc, nchan_chann + if(d->sub->status != DEAD) { + if(chaninfo) { + //ok, channel already exists. +- nchan_store_subscribe_continued(SUB_CHANNEL_AUTHORIZED, NULL, d); ++ nchan_store_subscribe_stage3(SUB_CHANNEL_AUTHORIZED, NULL, d); + } + else { + //nope. no channel, no subscribing. +@@ -2219,14 +2247,14 @@ static ngx_int_t group_subscribe_channel_limit_check(ngx_int_t _, nchan_group_t + if(shm_group) { + if(!shm_group->limit.channels || (shm_group->channels < shm_group->limit.channels)) { + d->group_channel_limit_pass = 1; +- rc = nchan_store_subscribe_continued(SUB_CHANNEL_AUTHORIZED, NULL, d); ++ rc = nchan_store_subscribe_stage3(SUB_CHANNEL_AUTHORIZED, NULL, d); + } + else if (shm_group->limit.channels && shm_group->channels == shm_group->limit.channels){ + //no new channels! + rc = nchan_store_find_channel(d->channel_id, d->sub->cf, (callback_pt )group_subscribe_channel_limit_reached, d); + } + else { +- rc = nchan_store_subscribe_continued(SUB_CHANNEL_UNAUTHORIZED, NULL, d); ++ rc = nchan_store_subscribe_stage3(SUB_CHANNEL_UNAUTHORIZED, NULL, d); + } + + } +@@ -2246,7 +2274,7 @@ static ngx_int_t group_subscribe_channel_limit_check(ngx_int_t _, nchan_group_t + return rc; + } + +-static ngx_int_t nchan_store_subscribe_continued(ngx_int_t channel_status, void* _, subscribe_data_t *d) { ++static ngx_int_t nchan_store_subscribe_stage3(ngx_int_t channel_status, void* _, subscribe_data_t *d) { + memstore_channel_head_t *chanhead = NULL; + int retry_null_chanhead = 1; + //store_message_t *chmsg; diff --git a/main/nginx/nginx-module-vts~cast-key-length-to-correct-type.patch b/main/nginx/nginx-module-vts~cast-key-length-to-correct-type.patch deleted file mode 100644 index e29d52ffd44..00000000000 --- a/main/nginx/nginx-module-vts~cast-key-length-to-correct-type.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 63b917ff8b6755bc6b7e30d4f61daad4b7817372 Mon Sep 17 00:00:00 2001 -From: Jonathan Giddy <jgiddy@mesosphere.com> -Date: Fri, 22 Mar 2019 21:59:57 +0000 -Subject: [PATCH] Cast key length to correct type - ---- - src/ngx_http_vhost_traffic_status_shm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Patch-Source: https://github.com/vozlt/nginx-module-vts/pull/161 - -diff --git a/src/ngx_http_vhost_traffic_status_shm.c b/src/ngx_http_vhost_traffic_status_shm.c -index 8066fc0..d87336f 100644 ---- a/src/ngx_http_vhost_traffic_status_shm.c -+++ b/src/ngx_http_vhost_traffic_status_shm.c -@@ -147,7 +147,7 @@ ngx_http_vhost_traffic_status_shm_add_node(ngx_http_request_t *r, - vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; - - node->key = hash; -- vtsn->len = (u_char) key->len; -+ vtsn->len = (u_short) key->len; - ngx_http_vhost_traffic_status_node_init(r, vtsn); - vtsn->stat_upstream.type = type; - ngx_memcpy(vtsn->data, key->data, key->len); diff --git a/main/nginx/nginx-module-vts~fix-uri-overflow.patch b/main/nginx/nginx-module-vts~fix-uri-overflow.patch deleted file mode 100644 index 840b5bc0805..00000000000 --- a/main/nginx/nginx-module-vts~fix-uri-overflow.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 5c58aaaa0e3ade270ef0d0534def769a4b3a8b26 Mon Sep 17 00:00:00 2001 -From: spacewander <spacewanderlzx@gmail.com> -Date: Thu, 20 Aug 2020 16:34:58 +0800 -Subject: [PATCH] fix: limit the r->uri search scope to avoid overflow - -r->uri doesn't end with '\0'. - ---- - src/ngx_http_vhost_traffic_status_display.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -Patch-Source: https://github.com/vozlt/nginx-module-vts/pull/188 - -diff --git a/src/ngx_http_vhost_traffic_status_display.c b/src/ngx_http_vhost_traffic_status_display.c -index c0d106a..10b5a62 100644 ---- a/src/ngx_http_vhost_traffic_status_display.c -+++ b/src/ngx_http_vhost_traffic_status_display.c -@@ -38,10 +38,10 @@ ngx_http_vhost_traffic_status_display_handler(ngx_http_request_t *r) - - len = 0; - -- p = (u_char *) ngx_strchr(r->uri.data, '/'); -+ p = (u_char *) ngx_strlchr(r->uri.data, r->uri.data + r->uri.len, '/'); - - if (p) { -- p = (u_char *) ngx_strchr(p + 1, '/'); -+ p = (u_char *) ngx_strlchr(p + 1, r->uri.data + r->uri.len, '/'); - len = r->uri.len - (p - r->uri.data); - } - diff --git a/main/nginx/nginx-module-vts~set-histogram-buckets-on-first-request.patch b/main/nginx/nginx-module-vts~set-histogram-buckets-on-first-request.patch deleted file mode 100644 index c15d0a30d79..00000000000 --- a/main/nginx/nginx-module-vts~set-histogram-buckets-on-first-request.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 25cba1362d42f483f797651609100e732f53cb37 Mon Sep 17 00:00:00 2001 -From: Jonathan Giddy <jgiddy@mesosphere.com> -Date: Fri, 29 Mar 2019 17:00:19 +0000 -Subject: [PATCH] Set histogram buckets on first request - -The `ngx_http_vhost_traffic_status_node_init` function initializes -the data structures and processes the first request. However it -was not updating the histogram buckets. Refactor the common code -from this function and `ngx_http_vhost_traffic_status_node_set` -into a common `ngx_http_vhost_traffic_status_node_update` function -to fix this and to reduce the chance of similar problems. ---- - src/ngx_http_vhost_traffic_status_node.c | 59 +++++++++++------------- - src/ngx_http_vhost_traffic_status_node.h | 2 + - 2 files changed, 30 insertions(+), 31 deletions(-) - -Patch-Source: https://github.com/vozlt/nginx-module-vts/pull/163 - -diff --git a/src/ngx_http_vhost_traffic_status_node.c b/src/ngx_http_vhost_traffic_status_node.c -index 1688bee..b91f2ce 100644 ---- a/src/ngx_http_vhost_traffic_status_node.c -+++ b/src/ngx_http_vhost_traffic_status_node.c -@@ -312,12 +312,15 @@ ngx_http_vhost_traffic_status_node_zero(ngx_http_vhost_traffic_status_node_t *vt - - } - -- -+/* -+ Initialize the node and update it with the first request. -+ Set the `stat_request_time` to the time of the first request. -+*/ - void - ngx_http_vhost_traffic_status_node_init(ngx_http_request_t *r, - ngx_http_vhost_traffic_status_node_t *vtsn) - { -- ngx_uint_t status = r->headers_out.status; -+ ngx_msec_int_t ms; - - /* init serverZone */ - ngx_http_vhost_traffic_status_node_zero(vtsn); -@@ -333,49 +336,50 @@ ngx_http_vhost_traffic_status_node_init(ngx_http_request_t *r, - &vtsn->stat_upstream.response_buckets); - - /* set serverZone */ -- vtsn->stat_request_counter = 1; -- vtsn->stat_in_bytes = (ngx_atomic_uint_t) r->request_length; -- vtsn->stat_out_bytes = (ngx_atomic_uint_t) r->connection->sent; -- -- ngx_http_vhost_traffic_status_add_rc(status, vtsn); -- -- vtsn->stat_request_time = (ngx_msec_t) ngx_http_vhost_traffic_status_request_time(r); -- vtsn->stat_request_time_counter = (ngx_atomic_uint_t) vtsn->stat_request_time; -- -- ngx_http_vhost_traffic_status_node_time_queue_insert(&vtsn->stat_request_times, -- vtsn->stat_request_time); -- --#if (NGX_HTTP_CACHE) -- if (r->upstream != NULL && r->upstream->cache_status != 0) { -- ngx_http_vhost_traffic_status_add_cc(r->upstream->cache_status, vtsn); -- } --#endif -+ ms = ngx_http_vhost_traffic_status_request_time(r); -+ vtsn->stat_request_time = (ngx_msec_t) ms; - -+ ngx_http_vhost_traffic_status_node_update(r, vtsn, ms); - } - -- -+/* -+ Update the node from a subsequent request. Now there is more than one request, -+ calculate the average request time. -+*/ - void - ngx_http_vhost_traffic_status_node_set(ngx_http_request_t *r, - ngx_http_vhost_traffic_status_node_t *vtsn) - { -- ngx_uint_t status; - ngx_msec_int_t ms; - ngx_http_vhost_traffic_status_node_t ovtsn; - ngx_http_vhost_traffic_status_loc_conf_t *vtscf; - - vtscf = ngx_http_get_module_loc_conf(r, ngx_http_vhost_traffic_status_module); - -- status = r->headers_out.status; - ovtsn = *vtsn; - -+ ms = ngx_http_vhost_traffic_status_request_time(r); -+ ngx_http_vhost_traffic_status_node_update(r, vtsn, ms); -+ -+ vtsn->stat_request_time = ngx_http_vhost_traffic_status_node_time_queue_average( -+ &vtsn->stat_request_times, vtscf->average_method, -+ vtscf->average_period); -+ -+ ngx_http_vhost_traffic_status_add_oc((&ovtsn), vtsn); -+} -+ -+void -+ngx_http_vhost_traffic_status_node_update(ngx_http_request_t *r, -+ ngx_http_vhost_traffic_status_node_t *vtsn, ngx_msec_int_t ms) -+{ -+ ngx_uint_t status = r->headers_out.status; -+ - vtsn->stat_request_counter++; - vtsn->stat_in_bytes += (ngx_atomic_uint_t) r->request_length; - vtsn->stat_out_bytes += (ngx_atomic_uint_t) r->connection->sent; - - ngx_http_vhost_traffic_status_add_rc(status, vtsn); - -- ms = ngx_http_vhost_traffic_status_request_time(r); -- - vtsn->stat_request_time_counter += (ngx_atomic_uint_t) ms; - - ngx_http_vhost_traffic_status_node_time_queue_insert(&vtsn->stat_request_times, -@@ -384,20 +388,13 @@ ngx_http_vhost_traffic_status_node_set(ngx_http_request_t *r, - ngx_http_vhost_traffic_status_node_histogram_observe(&vtsn->stat_request_buckets, - ms); - -- vtsn->stat_request_time = ngx_http_vhost_traffic_status_node_time_queue_average( -- &vtsn->stat_request_times, vtscf->average_method, -- vtscf->average_period); -- - #if (NGX_HTTP_CACHE) - if (r->upstream != NULL && r->upstream->cache_status != 0) { - ngx_http_vhost_traffic_status_add_cc(r->upstream->cache_status, vtsn); - } - #endif -- -- ngx_http_vhost_traffic_status_add_oc((&ovtsn), vtsn); - } - -- - void - ngx_http_vhost_traffic_status_node_time_queue_zero( - ngx_http_vhost_traffic_status_node_time_queue_t *q) -diff --git a/src/ngx_http_vhost_traffic_status_node.h b/src/ngx_http_vhost_traffic_status_node.h -index 9ea6f23..3bbb53e 100644 ---- a/src/ngx_http_vhost_traffic_status_node.h -+++ b/src/ngx_http_vhost_traffic_status_node.h -@@ -118,6 +118,8 @@ void ngx_http_vhost_traffic_status_node_init(ngx_http_request_t *r, - ngx_http_vhost_traffic_status_node_t *vtsn); - void ngx_http_vhost_traffic_status_node_set(ngx_http_request_t *r, - ngx_http_vhost_traffic_status_node_t *vtsn); -+void ngx_http_vhost_traffic_status_node_update(ngx_http_request_t *r, -+ ngx_http_vhost_traffic_status_node_t *vtsn, ngx_msec_int_t ms); - - void ngx_http_vhost_traffic_status_node_time_queue_zero( - ngx_http_vhost_traffic_status_node_time_queue_t *q); diff --git a/main/nginx/nginx-upload-module~fix-nginx-compat.patch b/main/nginx/nginx-upload-module~fix-nginx-compat.patch new file mode 100644 index 00000000000..474a84fec4b --- /dev/null +++ b/main/nginx/nginx-upload-module~fix-nginx-compat.patch @@ -0,0 +1,40 @@ +Patch-Source: https://github.com/fdintino/nginx-upload-module/commit/96e64603dc5a588a2d1ae59a62b0019d6b41070c +-- +From 96e64603dc5a588a2d1ae59a62b0019d6b41070c Mon Sep 17 00:00:00 2001 +From: Karthikdasari0423 <92445174+Karthikdasari0423@users.noreply.github.com> +Date: Thu, 22 Jun 2023 01:40:07 +0530 +Subject: [PATCH] Update ngx_http_upload_module.c (#147) + +* Update ngx_http_upload_module.c + +* Fix whitespace + +--------- + +Co-authored-by: Frankie Dintino <fdintino@gmail.com> +--- + ngx_http_upload_module.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ngx_http_upload_module.c b/ngx_http_upload_module.c +index c51429f..66150f0 100644 +--- a/ngx_http_upload_module.c ++++ b/ngx_http_upload_module.c +@@ -12,7 +12,7 @@ + + #include <ngx_md5.h> + +-typedef ngx_md5_t MD5_CTX; ++typedef ngx_md5_t MD5_CTX1; + + #define MD5Init ngx_md5_init + #define MD5Update ngx_md5_update +@@ -189,7 +189,7 @@ typedef struct { + } ngx_http_upload_loc_conf_t; + + typedef struct ngx_http_upload_md5_ctx_s { +- MD5_CTX md5; ++ MD5_CTX1 md5; + u_char md5_digest[MD5_DIGEST_LENGTH * 2]; + } ngx_http_upload_md5_ctx_t; + diff --git a/main/nginx/nginx-upload-module~fixes.patch b/main/nginx/nginx-upload-module~fixes.patch new file mode 100644 index 00000000000..423647d8089 --- /dev/null +++ b/main/nginx/nginx-upload-module~fixes.patch @@ -0,0 +1,620 @@ +git diff 2.3.0..643b4c1fa6993da6bc1f82e7121ca62a7696ee6b ngx_http_upload_module.c +-- +commit 643b4c1fa6993da6bc1f82e7121ca62a7696ee6b +Author: Frankie Dintino <fdintino@gmail.com> +Date: Sun Jun 21 17:09:17 2020 -0400 + + Fix bug caused by uploading a single byte range + + fixes #115 + +commit 1ac57ac4d37bfb0c09337f2eef3fab5a1c1e9a38 +Author: Romain Pomier <romain@cardiologs.com> +Date: Wed Apr 8 18:42:38 2020 +0200 + + Handle quotes problems in Content-Type and Content-Disposition + +commit 1b0c530a3abf5c8782feabcfa2e89a312687f968 +Author: Frankie Dintino <fdintino@gmail.com> +Date: Mon Feb 10 12:48:52 2020 -0500 + + Fix issue where upload headers were only added to final request + + fixes #124 + +commit a350ce9d6814438db56428ad6365db994dbd27f6 +Author: Valery Kholodkov <valery@coldrift.com> +Date: Mon Nov 18 18:04:55 2019 +0100 + + Update read handler + +commit 8d50edd32ae788c3e0c12fe1940007e9faa3f15d +Author: Demid Rudak <demid.r@didww.com> +Date: Mon Apr 1 15:37:52 2019 +0300 + + Fixed upload_aggregate_form_field 'upload_file_md5' calculation + +commit 666428bf8ea3ee3e5bd40aaa693624234feb6da3 +Author: Frankie Dintino <fdintino@gmail.com> +Date: Fri Aug 10 11:39:01 2018 -0400 + + Fix and add tests for upload_add_header + +commit e8d93f8f37db62f2588c7b3a20c873514fce4f5d +Author: Frankie Dintino <fdintino@gmail.com> +Date: Fri Aug 10 11:35:16 2018 -0400 + + Remove unnecessary ngx_http_upload_variable_set function + +commit 9c58c8ae9b3f4d44a28eebdffbdc1ab4224e3f90 +Author: Frankie Dintino <fdintino@gmail.com> +Date: Mon Aug 6 09:38:52 2018 -0400 + + Fix bug when uc and lc hash aggregate fields present in the same request +-- +diff --git a/ngx_http_upload_module.c b/ngx_http_upload_module.c +index 3ac3279..c51429f 100644 +--- a/ngx_http_upload_module.c ++++ b/ngx_http_upload_module.c +@@ -55,8 +55,8 @@ typedef ngx_md5_t MD5_CTX; + #define X_SESSION_ID_STRING "X-Session-ID:" + #define FORM_DATA_STRING "form-data" + #define ATTACHMENT_STRING "attachment" +-#define FILENAME_STRING "filename=\"" +-#define FIELDNAME_STRING "name=\"" ++#define FILENAME_STRING "filename=" ++#define FIELDNAME_STRING "name=" + #define BYTES_UNIT_STRING "bytes " + + #define NGX_UPLOAD_MALFORMED -11 +@@ -302,8 +302,6 @@ static void *ngx_http_upload_create_loc_conf(ngx_conf_t *cf); + static char *ngx_http_upload_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child); + static ngx_int_t ngx_http_upload_add_variables(ngx_conf_t *cf); +-static void ngx_http_upload_variable_set(ngx_http_request_t *r, +- ngx_http_variable_value_t *v, uintptr_t data); + static ngx_int_t ngx_http_upload_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + static ngx_int_t ngx_http_upload_md5_variable(ngx_http_request_t *r, +@@ -326,6 +324,10 @@ static ngx_int_t ngx_http_upload_uint_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + static char *ngx_http_upload_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + ++static ngx_int_t ++ngx_http_upload_process_field_templates(ngx_http_request_t *r, ++ ngx_http_upload_field_template_t *t, ngx_str_t *field_name, ngx_str_t *field_value); ++ + static ngx_int_t ngx_http_upload_start_handler(ngx_http_upload_ctx_t *u); + static void ngx_http_upload_finish_handler(ngx_http_upload_ctx_t *u); + static void ngx_http_upload_abort_handler(ngx_http_upload_ctx_t *u); +@@ -345,9 +347,7 @@ static ngx_int_t ngx_http_read_upload_client_request_body(ngx_http_request_t *r) + + static char *ngx_http_upload_set_form_field(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +-static char *ngx_http_upload_add_header(ngx_conf_t *cf, ngx_command_t *cmd, +- void *conf); +-static ngx_int_t ngx_http_upload_eval_path(ngx_http_request_t *r); ++ static ngx_int_t ngx_http_upload_eval_path(ngx_http_request_t *r); + static ngx_int_t ngx_http_upload_eval_state_path(ngx_http_request_t *r); + static char *ngx_http_upload_pass_form_field(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +@@ -666,7 +666,7 @@ static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */ + { ngx_string("upload_add_header"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE2, +- ngx_http_upload_add_header, ++ ngx_http_upload_set_form_field, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_upload_loc_conf_t, header_templates), + NULL}, +@@ -710,7 +710,7 @@ static ngx_http_variable_t ngx_http_upload_variables[] = { /* {{{ */ + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_string("upload_content_type"), +- ngx_http_upload_variable_set, ++ NULL, + ngx_http_upload_variable, + (uintptr_t) offsetof(ngx_http_upload_ctx_t, content_type), + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, +@@ -1052,18 +1052,14 @@ err: + static ngx_int_t ngx_http_upload_add_headers(ngx_http_request_t *r, ngx_http_upload_loc_conf_t *ulcf) { /* {{{ */ + ngx_str_t name; + ngx_str_t value; +- ngx_http_upload_header_template_t *t; ++ ngx_http_upload_field_template_t *t; + ngx_table_elt_t *h; + ngx_uint_t i; + +- if(ulcf->header_templates != NULL) { ++ if (ulcf->header_templates != NULL) { + t = ulcf->header_templates->elts; +- for(i = 0; i < ulcf->header_templates->nelts; i++) { +- if(ngx_http_complex_value(r, t->name, &name) != NGX_OK) { +- return NGX_ERROR; +- } +- +- if(ngx_http_complex_value(r, t->value, &value) != NGX_OK) { ++ for (i = 0; i < ulcf->header_templates->nelts; i++) { ++ if (ngx_http_upload_process_field_templates(r, &t[i], &name, &value) != NGX_OK) { + return NGX_ERROR; + } + +@@ -1079,8 +1075,6 @@ static ngx_int_t ngx_http_upload_add_headers(ngx_http_request_t *r, ngx_http_upl + h->value.len = value.len; + h->value.data = value.data; + } +- +- t++; + } + } + +@@ -1180,10 +1174,6 @@ static ngx_int_t ngx_http_upload_body_handler(ngx_http_request_t *r) { /* {{{ */ + ngx_str_t dummy = ngx_string("<ngx_upload_module_dummy>"); + ngx_table_elt_t *h; + +- if(ngx_http_upload_add_headers(r, ulcf) != NGX_OK) { +- return NGX_HTTP_INTERNAL_SERVER_ERROR; +- } +- + if(ctx->prevent_output) { + r->headers_out.status = NGX_HTTP_CREATED; + +@@ -1360,6 +1350,27 @@ static ngx_int_t ngx_http_upload_body_handler(ngx_http_request_t *r) { /* {{{ */ + return rc; + } /* }}} */ + ++static ngx_int_t ++ngx_http_upload_process_field_templates( ++ ngx_http_request_t *r, ngx_http_upload_field_template_t *t, ++ ngx_str_t *name, ngx_str_t *value) ++{ ++ if (t->field_lengths == NULL) { ++ *name = t->value.key; ++ } else if (ngx_http_script_run(r, name, t->field_lengths->elts, 0, ++ t->field_values->elts) == NULL) { ++ return NGX_UPLOAD_SCRIPTERROR; ++ } ++ ++ if (t->value_lengths == NULL) { ++ *value = t->value.value; ++ } else if (ngx_http_script_run(r, value, t->value_lengths->elts, 0, ++ t->value_values->elts) == NULL) { ++ return NGX_UPLOAD_SCRIPTERROR; ++ } ++ return NGX_OK; ++} ++ + static ngx_int_t ngx_http_upload_start_handler(ngx_http_upload_ctx_t *u) { /* {{{ */ + ngx_http_request_t *r = u->request; + ngx_http_upload_loc_conf_t *ulcf = ngx_http_get_module_loc_conf(r, ngx_http_upload_module); +@@ -1495,28 +1506,10 @@ static ngx_int_t ngx_http_upload_start_handler(ngx_http_upload_ctx_t *u) { /* {{ + + t = ulcf->field_templates->elts; + for (i = 0; i < ulcf->field_templates->nelts; i++) { ++ rc = ngx_http_upload_process_field_templates(r, &t[i], &field_name, &field_value); + +- if (t[i].field_lengths == NULL) { +- field_name = t[i].value.key; +- }else{ +- if (ngx_http_script_run(r, &field_name, t[i].field_lengths->elts, 0, +- t[i].field_values->elts) == NULL) +- { +- rc = NGX_UPLOAD_SCRIPTERROR; +- goto cleanup_file; +- } +- } +- +- if (t[i].value_lengths == NULL) { +- field_value = t[i].value.value; +- }else{ +- if (ngx_http_script_run(r, &field_value, t[i].value_lengths->elts, 0, +- t[i].value_values->elts) == NULL) +- { +- rc = NGX_UPLOAD_SCRIPTERROR; +- goto cleanup_file; +- } +- } ++ if(rc != NGX_OK) ++ goto cleanup_file; + + rc = ngx_http_upload_append_field(u, &field_name, &field_value); + +@@ -1603,6 +1596,11 @@ static ngx_int_t ngx_http_upload_start_handler(ngx_http_upload_ctx_t *u) { /* {{ + u->discard_data = 1; + } + ++ ++ if(ngx_http_upload_add_headers(r, ulcf) != NGX_OK) { ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ + return NGX_OK; + + cleanup_file: +@@ -1697,25 +1695,10 @@ static void ngx_http_upload_finish_handler(ngx_http_upload_ctx_t *u) { /* {{{ */ + if(ulcf->aggregate_field_templates) { + af = ulcf->aggregate_field_templates->elts; + for (i = 0; i < ulcf->aggregate_field_templates->nelts; i++) { +- +- if (af[i].field_lengths == NULL) { +- aggregate_field_name = af[i].value.key; +- }else{ +- if (ngx_http_script_run(r, &aggregate_field_name, af[i].field_lengths->elts, 0, +- af[i].field_values->elts) == NULL) +- { +- goto rollback; +- } +- } +- +- if (af[i].value_lengths == NULL) { +- aggregate_field_value = af[i].value.value; +- }else{ +- if (ngx_http_script_run(r, &aggregate_field_value, af[i].value_lengths->elts, 0, +- af[i].value_values->elts) == NULL) +- { +- goto rollback; +- } ++ rc = ngx_http_upload_process_field_templates(r, &af[i], &aggregate_field_name, ++ &aggregate_field_value); ++ if (rc != NGX_OK) { ++ goto rollback; + } + + rc = ngx_http_upload_append_field(u, &aggregate_field_name, &aggregate_field_value); +@@ -2001,7 +1984,7 @@ ngx_http_upload_buf_merge_range(ngx_http_upload_merger_state_t *ms, ngx_http_upl + return NGX_ERROR; + } + +- if(ms->current_range_n.start >= ms->current_range_n.end || ms->current_range_n.start >= ms->current_range_n.total ++ if(ms->current_range_n.start > ms->current_range_n.end || ms->current_range_n.start > ms->current_range_n.total + || ms->current_range_n.end > ms->current_range_n.total) + { + ngx_log_debug3(NGX_LOG_DEBUG_CORE, ms->log, 0, +@@ -2398,21 +2381,6 @@ ngx_http_upload_add_variables(ngx_conf_t *cf) + return NGX_OK; + } /* }}} */ + +-static void /* {{{ ngx_http_upload_variable_set */ +-ngx_http_upload_variable_set(ngx_http_request_t *r, +- ngx_http_variable_value_t *v, uintptr_t data) +-{ +- ngx_str_t *s; +- ngx_http_upload_ctx_t *u; +- +- u = ngx_http_get_module_ctx(r, ngx_http_upload_module); +- +- s = (ngx_str_t *) ((char *) u + data); +- +- s->len = v->len; +- s->data = v->data; +-} /* }}} */ +- + static ngx_int_t /* {{{ ngx_http_upload_variable */ + ngx_http_upload_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +@@ -2434,88 +2402,78 @@ ngx_http_upload_variable(ngx_http_request_t *r, + return NGX_OK; + } /* }}} */ + +-static ngx_int_t /* {{{ ngx_http_upload_md5_variable */ +-ngx_http_upload_md5_variable(ngx_http_request_t *r, +- ngx_http_variable_value_t *v, uintptr_t data) ++static ngx_int_t ++ngx_http_upload_hash_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data, u_char *digest, ++ ngx_uint_t digest_len) + { + ngx_uint_t i; +- ngx_http_upload_ctx_t *u; + u_char *c; ++ u_char *p; + u_char *hex_table; + +- u = ngx_http_get_module_ctx(r, ngx_http_upload_module); +- +- if(u->md5_ctx == NULL || u->partial_content) { +- v->not_found = 1; +- return NGX_OK; +- } +- + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + hex_table = (u_char*)data; +- c = u->md5_ctx->md5_digest + MD5_DIGEST_LENGTH * 2; + +- i = MD5_DIGEST_LENGTH; ++ p = ngx_palloc(r->pool, digest_len * 2); ++ if (p == NULL) { ++ return NGX_ERROR; ++ } ++ ++ c = p + digest_len * 2; ++ i = digest_len; + + do{ + i--; +- *--c = hex_table[u->md5_ctx->md5_digest[i] & 0xf]; +- *--c = hex_table[u->md5_ctx->md5_digest[i] >> 4]; ++ *--c = hex_table[digest[i] & 0xf]; ++ *--c = hex_table[digest[i] >> 4]; + }while(i != 0); + +- v->data = u->md5_ctx->md5_digest; +- v->len = MD5_DIGEST_LENGTH * 2; ++ v->data = c; ++ v->len = digest_len * 2; + + return NGX_OK; + } /* }}} */ + +-static ngx_int_t /* {{{ ngx_http_upload_sha1_variable */ +-ngx_http_upload_sha1_variable(ngx_http_request_t *r, ++static ngx_int_t /* {{{ ngx_http_upload_md5_variable */ ++ngx_http_upload_md5_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) + { +- ngx_uint_t i; + ngx_http_upload_ctx_t *u; +- u_char *c; +- u_char *hex_table; + + u = ngx_http_get_module_ctx(r, ngx_http_upload_module); + +- if(u->sha1_ctx == NULL || u->partial_content) { ++ if(u->md5_ctx == NULL || u->partial_content) { + v->not_found = 1; + return NGX_OK; + } ++ return ngx_http_upload_hash_variable(r, v, data, u->md5_ctx->md5_digest, MD5_DIGEST_LENGTH); ++} /* }}} */ + +- v->valid = 1; +- v->no_cacheable = 0; +- v->not_found = 0; +- +- hex_table = (u_char*)data; +- c = u->sha1_ctx->sha1_digest + SHA_DIGEST_LENGTH * 2; +- +- i = SHA_DIGEST_LENGTH; ++static ngx_int_t /* {{{ ngx_http_upload_sha1_variable */ ++ngx_http_upload_sha1_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data) ++{ ++ ngx_http_upload_ctx_t *u; + +- do{ +- i--; +- *--c = hex_table[u->sha1_ctx->sha1_digest[i] & 0xf]; +- *--c = hex_table[u->sha1_ctx->sha1_digest[i] >> 4]; +- }while(i != 0); ++ u = ngx_http_get_module_ctx(r, ngx_http_upload_module); + +- v->data = u->sha1_ctx->sha1_digest; +- v->len = SHA_DIGEST_LENGTH * 2; ++ if(u->sha1_ctx == NULL || u->partial_content) { ++ v->not_found = 1; ++ return NGX_OK; ++ } + +- return NGX_OK; ++ return ngx_http_upload_hash_variable(r, v, data, u->sha1_ctx->sha1_digest, SHA_DIGEST_LENGTH); + } /* }}} */ + + static ngx_int_t /* {{{ ngx_http_upload_sha256_variable */ + ngx_http_upload_sha256_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) + { +- ngx_uint_t i; + ngx_http_upload_ctx_t *u; +- u_char *c; +- u_char *hex_table; + + u = ngx_http_get_module_ctx(r, ngx_http_upload_module); + +@@ -2524,35 +2482,14 @@ ngx_http_upload_sha256_variable(ngx_http_request_t *r, + return NGX_OK; + } + +- v->valid = 1; +- v->no_cacheable = 0; +- v->not_found = 0; +- +- hex_table = (u_char*)data; +- c = u->sha256_ctx->sha256_digest + SHA256_DIGEST_LENGTH * 2; +- +- i = SHA256_DIGEST_LENGTH; +- +- do{ +- i--; +- *--c = hex_table[u->sha256_ctx->sha256_digest[i] & 0xf]; +- *--c = hex_table[u->sha256_ctx->sha256_digest[i] >> 4]; +- }while(i != 0); +- +- v->data = u->sha256_ctx->sha256_digest; +- v->len = SHA256_DIGEST_LENGTH * 2; +- +- return NGX_OK; ++ return ngx_http_upload_hash_variable(r, v, data, u->sha256_ctx->sha256_digest, SHA256_DIGEST_LENGTH); + } /* }}} */ + + static ngx_int_t /* {{{ ngx_http_upload_sha512_variable */ + ngx_http_upload_sha512_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) + { +- ngx_uint_t i; + ngx_http_upload_ctx_t *u; +- u_char *c; +- u_char *hex_table; + + u = ngx_http_get_module_ctx(r, ngx_http_upload_module); + +@@ -2561,25 +2498,7 @@ ngx_http_upload_sha512_variable(ngx_http_request_t *r, + return NGX_OK; + } + +- v->valid = 1; +- v->no_cacheable = 0; +- v->not_found = 0; +- +- hex_table = (u_char*)data; +- c = u->sha512_ctx->sha512_digest + SHA512_DIGEST_LENGTH * 2; +- +- i = SHA512_DIGEST_LENGTH; +- +- do{ +- i--; +- *--c = hex_table[u->sha512_ctx->sha512_digest[i] & 0xf]; +- *--c = hex_table[u->sha512_ctx->sha512_digest[i] >> 4]; +- }while(i != 0); +- +- v->data = u->sha512_ctx->sha512_digest; +- v->len = SHA512_DIGEST_LENGTH * 2; +- +- return NGX_OK; ++ return ngx_http_upload_hash_variable(r, v, data, u->sha512_ctx->sha512_digest, SHA512_DIGEST_LENGTH); + } /* }}} */ + + static ngx_int_t /* {{{ ngx_http_upload_crc32_variable */ +@@ -2922,73 +2841,6 @@ ngx_http_upload_pass_form_field(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) + return NGX_CONF_OK; + } /* }}} */ + +-static char * /* {{{ ngx_http_upload_add_header */ +-ngx_http_upload_add_header(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +-{ +- ngx_str_t *value; +- ngx_http_upload_header_template_t *h; +- ngx_array_t **field; +- ngx_http_compile_complex_value_t ccv; +- +- field = (ngx_array_t**) (((u_char*)conf) + cmd->offset); +- +- value = cf->args->elts; +- +- /* +- * Add new entry to header template list +- */ +- if (*field == NULL) { +- *field = ngx_array_create(cf->pool, 1, +- sizeof(ngx_http_upload_header_template_t)); +- if (*field == NULL) { +- return NGX_CONF_ERROR; +- } +- } +- +- h = ngx_array_push(*field); +- if (h == NULL) { +- return NGX_CONF_ERROR; +- } +- +- /* +- * Compile header name +- */ +- h->name = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); +- if(h->name == NULL) { +- return NGX_CONF_ERROR; +- } +- +- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); +- +- ccv.cf = cf; +- ccv.value = &value[1]; +- ccv.complex_value = h->name; +- +- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { +- return NGX_CONF_ERROR; +- } +- +- /* +- * Compile header value +- */ +- h->value = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); +- if(h->value == NULL) { +- return NGX_CONF_ERROR; +- } +- +- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); +- +- ccv.cf = cf; +- ccv.value = &value[2]; +- ccv.complex_value = h->value; +- +- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { +- return NGX_CONF_ERROR; +- } +- +- return NGX_CONF_OK; +-} /* }}} */ +- + static char * /* {{{ ngx_http_upload_cleanup */ + ngx_http_upload_cleanup(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) + { +@@ -3599,6 +3451,8 @@ ngx_http_do_read_upload_client_request_body(ngx_http_request_t *r) + ngx_del_timer(c->read); + } + ++ r->read_event_handler = ngx_http_block_reading; ++ + rc = ngx_http_process_request_body(r, u->to_write); + + switch(rc) { +@@ -3667,16 +3521,14 @@ static ngx_int_t upload_parse_content_disposition(ngx_http_upload_ctx_t *upload_ + + if(filename_start != 0) { + +- filename_start += sizeof(FILENAME_STRING)-1; +- +- filename_end = filename_start + strcspn(filename_start, "\""); ++ filename_start += sizeof(FILENAME_STRING) - 1; + +- if(*filename_end != '\"') { +- ngx_log_debug0(NGX_LOG_DEBUG_CORE, upload_ctx->log, 0, +- "malformed filename in part header"); +- return NGX_UPLOAD_MALFORMED; ++ if (*filename_start == '\"') { ++ filename_start++; + } + ++ filename_end = filename_start + strcspn(filename_start, "\";"); ++ + /* + * IE sends full path, strip path from filename + * Also strip all UNIX path references +@@ -3703,16 +3555,14 @@ static ngx_int_t upload_parse_content_disposition(ngx_http_upload_ctx_t *upload_ + // }while((fieldname_start != 0) && (fieldname_start + sizeof(FIELDNAME_STRING) - 1 == filename_start)); + + if(fieldname_start != 0) { +- fieldname_start += sizeof(FIELDNAME_STRING)-1; ++ fieldname_start += sizeof(FIELDNAME_STRING) - 1; + +- if(fieldname_start != filename_start) { +- fieldname_end = fieldname_start + strcspn(fieldname_start, "\""); ++ if (*fieldname_start == '\"') { ++ fieldname_start++; ++ } + +- if(*fieldname_end != '\"') { +- ngx_log_error(NGX_LOG_ERR, upload_ctx->log, 0, +- "malformed fieldname in part header"); +- return NGX_UPLOAD_MALFORMED; +- } ++ if(fieldname_start != filename_start) { ++ fieldname_end = fieldname_start + strcspn(fieldname_start, "\";"); + + upload_ctx->field_name.len = fieldname_end - fieldname_start; + upload_ctx->field_name.data = ngx_pcalloc(upload_ctx->request->pool, upload_ctx->field_name.len + 1); +@@ -4087,6 +3937,12 @@ static ngx_int_t upload_parse_request_headers(ngx_http_upload_ctx_t *upload_ctx, + boundary_start_ptr += sizeof(BOUNDARY_STRING) - 1; + boundary_end_ptr = boundary_start_ptr + strcspn((char*)boundary_start_ptr, " ;\n\r"); + ++ // Handle quoted boundaries ++ if ((boundary_end_ptr - boundary_start_ptr) >= 2 && boundary_start_ptr[0] == '"' && *(boundary_end_ptr - 1) == '"') { ++ boundary_start_ptr++; ++ boundary_end_ptr--; ++ } ++ + if(boundary_end_ptr == boundary_start_ptr) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, upload_ctx->log, 0, + "boundary is empty"); diff --git a/main/nginx/nginx-upload-progress-module~fix-http2.patch b/main/nginx/nginx-upload-progress-module~fix-http2.patch new file mode 100644 index 00000000000..9886e1d7f09 --- /dev/null +++ b/main/nginx/nginx-upload-progress-module~fix-http2.patch @@ -0,0 +1,44 @@ +Patch-Source: https://github.com/masterzen/nginx-upload-progress-module/pull/57 +-- +From 594f1233c3c622ad51a2bde0c3289747af20e245 Mon Sep 17 00:00:00 2001 +From: Allan Jude <allanjude@freebsd.org> +Date: Sat, 26 Nov 2022 20:28:10 +0000 +Subject: [PATCH] Restore functionality of upload-progress for HTTP2 + +The upload-progress module was only getting notified of the first +block of uploaded data, because r->read_event_handler was being +reset by ngx_http_v2_read_request_body() and +ngx_http_v2_process_request_body() + +The patch detects that situation, updates module_ctx to call the +new function, then reinserts itself as the read_event_handler so +we continue to be notified about uploaded data. + +Introduced in nginx/nginx@67d160bf25e02ba6679bb6c3b9cbdfeb29b759de + +Sponsored-by: ScaleEngine Inc. +--- + ngx_http_uploadprogress_module.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/ngx_http_uploadprogress_module.c b/ngx_http_uploadprogress_module.c +index 33bdaf7..f17ad92 100644 +--- a/ngx_http_uploadprogress_module.c ++++ b/ngx_http_uploadprogress_module.c +@@ -489,6 +489,16 @@ static void ngx_http_uploadprogress_event_handler(ngx_http_request_t *r) + module_ctx = ngx_http_get_module_ctx(r, ngx_http_uploadprogress_module); + if (module_ctx != NULL ) { + module_ctx->read_event_handler(r); ++ /* ++ * Both ngx_http_v2_read_request_body() and ++ * ngx_http_v2_process_request_body() modify read_event_handler, ++ * we respect the change, but re-interpose our function so we still get ++ * future events, otherwise we miss all upload progress. ++ */ ++ if (r->read_event_handler != ngx_http_uploadprogress_event_handler) { ++ module_ctx->read_event_handler = r->read_event_handler; ++ r->read_event_handler = ngx_http_uploadprogress_event_handler; ++ } + } + + /* at this stage, r is not anymore safe to use */ diff --git a/main/nginx/nginx-upload-progress-module~fix.patch b/main/nginx/nginx-upload-progress-module~fix.patch new file mode 100644 index 00000000000..7d5fd1bde6d --- /dev/null +++ b/main/nginx/nginx-upload-progress-module~fix.patch @@ -0,0 +1,937 @@ +Patch-Source: https://github.com/masterzen/nginx-upload-progress-module/compare/master...msva:nginx-upload-progress-module:master + +Ref https://github.com/masterzen/nginx-upload-progress-module/issues/56 + +diff --git a/ngx_http_uploadprogress_module.c b/ngx_http_uploadprogress_module.c +index 33bdaf7..577c146 100644 +--- a/ngx_http_uploadprogress_module.c ++++ b/ngx_http_uploadprogress_module.c +@@ -8,6 +8,7 @@ + #include <ngx_core.h> + #include <ngx_http.h> + ++ + #define TIMER_FREQUENCY 15 * 1000 + + typedef enum { +@@ -31,6 +32,8 @@ struct ngx_http_uploadprogress_node_s { + off_t rest; + off_t length; + ngx_uint_t done; ++ ngx_uint_t sequence; ++ ngx_uint_t sent_portion; + time_t timeout; + struct ngx_http_uploadprogress_node_s *prev; + struct ngx_http_uploadprogress_node_s *next; +@@ -65,7 +68,13 @@ typedef struct { + ngx_str_t content_type; + ngx_array_t templates; + ngx_str_t header; ++ ngx_str_t header_mul; ++ ++ ngx_addr_t progress_server; ++ int udp_socket; ++ + ngx_str_t jsonp_parameter; ++ ngx_int_t json_multiple:1; + } ngx_http_uploadprogress_conf_t; + + typedef struct { +@@ -87,6 +96,8 @@ static ngx_int_t ngx_http_uploadprogress_offset_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + static ngx_int_t ngx_http_uploadprogress_status_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); ++static ngx_int_t ngx_http_uploadprogress_id_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data); + static ngx_int_t ngx_http_uploadprogress_callback_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + static char* ngx_http_upload_progress_set_template(ngx_conf_t * cf, ngx_http_uploadprogress_template_t *t, ngx_str_t *source); +@@ -97,6 +108,8 @@ static char* ngx_http_upload_progress_template(ngx_conf_t * cf, ngx_command_t * + static char* ngx_http_upload_progress_java_output(ngx_conf_t * cf, ngx_command_t * cmd, void *conf); + static char* ngx_http_upload_progress_json_output(ngx_conf_t * cf, ngx_command_t * cmd, void *conf); + static char* ngx_http_upload_progress_jsonp_output(ngx_conf_t * cf, ngx_command_t * cmd, void *conf); ++static char* ngx_http_upload_progress_json_multiple_output(ngx_conf_t * cf, ngx_command_t * cmd, void *conf); ++static char* ngx_http_upload_progress_jsonp_multiple_output(ngx_conf_t * cf, ngx_command_t * cmd, void *conf); + static void ngx_clean_old_connections(ngx_event_t * ev); + static ngx_int_t ngx_http_uploadprogress_content_handler(ngx_http_request_t *r); + +@@ -112,7 +125,7 @@ static ngx_command_t ngx_http_uploadprogress_commands[] = { + NULL}, + + {ngx_string("track_uploads"), +- NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2, ++ NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2 | NGX_CONF_TAKE3, + ngx_http_track_uploads, + NGX_HTTP_LOC_CONF_OFFSET, + 0, +@@ -160,6 +173,20 @@ static ngx_command_t ngx_http_uploadprogress_commands[] = { + 0, + NULL}, + ++ {ngx_string("upload_progress_json_multiple_output"), ++ NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS, ++ ngx_http_upload_progress_json_multiple_output, ++ NGX_HTTP_LOC_CONF_OFFSET, ++ 0, ++ NULL}, ++ ++ {ngx_string("upload_progress_jsonp_multiple_output"), ++ NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS, ++ ngx_http_upload_progress_jsonp_multiple_output, ++ NGX_HTTP_LOC_CONF_OFFSET, ++ 0, ++ NULL}, ++ + {ngx_string("upload_progress_header"), + NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, + ngx_conf_set_str_slot, +@@ -167,6 +194,13 @@ static ngx_command_t ngx_http_uploadprogress_commands[] = { + offsetof(ngx_http_uploadprogress_conf_t, header), + NULL}, + ++ {ngx_string("upload_progress_header_mul"), ++ NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, ++ ngx_conf_set_str_slot, ++ NGX_HTTP_LOC_CONF_OFFSET, ++ offsetof(ngx_http_uploadprogress_conf_t, header_mul), ++ NULL}, ++ + {ngx_string("upload_progress_jsonp_parameter"), + NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, + ngx_conf_set_str_slot, +@@ -195,6 +229,10 @@ static ngx_http_variable_t ngx_http_uploadprogress_variables[] = { + (uintptr_t) offsetof(ngx_http_uploadprogress_node_t, err_status), + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + ++ { ngx_string("uploadprogress_id"), NULL, ngx_http_uploadprogress_id_variable, ++ (uintptr_t) offsetof(ngx_http_uploadprogress_node_t, err_status), ++ NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, ++ + { ngx_string("uploadprogress_callback"), NULL, ngx_http_uploadprogress_callback_variable, + (uintptr_t) NULL, + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, +@@ -261,9 +299,24 @@ static ngx_str_t ngx_http_uploadprogress_jsonp_defaults[] = { + ngx_string("$uploadprogress_callback({ \"state\" : \"uploading\", \"received\" : $uploadprogress_received, \"size\" : $uploadprogress_length });\r\n") + }; + ++static ngx_str_t ngx_http_uploadprogress_json_multiple_defaults[] = { ++ ngx_string("{ \"id\" : $uploadprogress_id, \"state\" : \"starting\" }"), ++ ngx_string("{ \"id\" : $uploadprogress_id, \"state\" : \"error\", \"status\" : $uploadprogress_status }"), ++ ngx_string("{ \"id\" : $uploadprogress_id, \"state\" : \"done\" }"), ++ ngx_string("{ \"id\" : $uploadprogress_id, \"state\" : \"uploading\", \"received\" : $uploadprogress_received, \"size\" : $uploadprogress_length }") ++}; ++ ++static ngx_str_t ngx_http_uploadprogress_jsonp_multiple_defaults[] = { ++ ngx_string("$uploadprogress_callback({ \"id\" : $uploadprogress_id, \"state\" : \"starting\" });\r\n"), ++ ngx_string("$uploadprogress_callback({ \"id\" : $uploadprogress_id, \"state\" : \"error\", \"status\" : $uploadprogress_status });\r\n"), ++ ngx_string("$uploadprogress_callback({ \"id\" : $uploadprogress_id, \"state\" : \"done\" });\r\n"), ++ ngx_string("$uploadprogress_callback({ \"id\" : $uploadprogress_id, \"state\" : \"uploading\", \"received\" : $uploadprogress_received, \"size\" : $uploadprogress_length });\r\n") ++}; ++ + + static ngx_array_t ngx_http_uploadprogress_global_templates; + ++ + static ngx_str_t* + get_tracking_id(ngx_http_request_t * r) + { +@@ -328,7 +381,7 @@ get_tracking_id(ngx_http_request_t * r) + i = 1; + break; + } +- if (len<=0) ++ else if (!len) + break; + } + while(p++); +@@ -355,6 +408,97 @@ get_tracking_id(ngx_http_request_t * r) + return NULL; + } + ++static ngx_str_t* ++get_tracking_ids_mul(ngx_http_request_t * r) ++{ ++ u_char *p, *start_p; ++ ngx_uint_t i; ++ ngx_list_part_t *part; ++ ngx_table_elt_t *header; ++ ngx_str_t *ret, args; ++ ngx_http_uploadprogress_conf_t *upcf; ++ ++ upcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module); ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upload-progress: get_tracking_ids"); ++ ++ part = &r->headers_in.headers.part; ++ header = part->elts; ++ ++ for (i = 0; /* void */ ; i++) { ++ ++ if (i >= part->nelts) { ++ if (part->next == NULL) { ++ break; ++ } ++ ++ part = part->next; ++ header = part->elts; ++ i = 0; ++ } ++ ++ if (header[i].key.len == upcf->header_mul.len ++ && ngx_strncasecmp(header[i].key.data, upcf->header_mul.data, ++ header[i].key.len) == 0) { ++ ret = ngx_calloc(sizeof(ngx_str_t), r->connection->log ); ++ ret->data = header[i].value.data; ++ ret->len = header[i].value.len; ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload-progress: get_tracking_ids found header: %V", ret); ++ return ret; ++ } ++ } ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload-progress: get_tracking_ids no header found"); ++ ++ /* not found, check as a request arg */ ++ /* it is possible the request args have not been yet created (or already released) */ ++ /* so let's try harder first from the request line */ ++ args.len = r->args.len; ++ args.data = r->args.data; ++ ++ if (args.len && args.data) { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload-progress: get_tracking_id no header found, args found"); ++ i = 0; ++ p = args.data; ++ do { ++ ngx_uint_t len = args.len - (p - args.data); ++ if (len >= (upcf->header_mul.len + 1) && ngx_strncasecmp(p, upcf->header_mul.data, upcf->header_mul.len) == 0 ++ && p[upcf->header_mul.len] == '=') { ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload-progress: get_tracking_id found args: %s",p); ++ i = 1; ++ break; ++ } ++ else if (!len) ++ break; ++ } ++ while(p++); ++ ++ if (i) { ++ start_p = p += upcf->header_mul.len + 1; ++ while (p < args.data + args.len) { ++ if (*((p++) + 1) == '&') { ++ break; ++ } ++ } ++ ++ ret = ngx_calloc(sizeof(ngx_str_t), r->connection->log); ++ ret->data = start_p; ++ ret->len = p - start_p; ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload-progress: get_tracking_id found args: %V",ret); ++ return ret; ++ } ++ } ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload-progress: get_tracking_id no id found"); ++ return NULL; ++} ++ + static ngx_http_uploadprogress_node_t * + find_node(ngx_str_t * id, ngx_http_uploadprogress_ctx_t * ctx, ngx_log_t * log) + { +@@ -540,6 +684,27 @@ static void ngx_http_uploadprogress_event_handler(ngx_http_request_t *r) + + if(up->length == 0) + up->length = r->headers_in.content_length_n; ++ if(upcf->udp_socket != -1 && upcf->progress_server.socklen != 0) ++ { ++ u_char datagram_buf[1024]; ++ u_char * end; ++ off_t uploaded; ++ ngx_uint_t portion; ++ ++ uploaded = up->length - up->rest; ++ if(up->length) ++ portion = 100 * uploaded / up->length; ++ else ++ portion = 100; ++ if(portion > up->sent_portion) ++ { ++ end = ngx_snprintf(datagram_buf, sizeof(datagram_buf), "{\"id\" : \"%V\", \"sequence\" : %d, \"size\" : %uO, \"uploaded\" : %uO }", ++ id, up->sequence, up->length, uploaded); ++ sendto(upcf->udp_socket, datagram_buf, end - datagram_buf, 0, (struct sockaddr*)upcf->progress_server.sockaddr, upcf->progress_server.socklen); ++ up->sent_portion = portion; ++ ++up->sequence; ++ } ++ } + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "upload-progress: read_event_handler storing rest %uO/%uO for %V", up->rest, up->length, id); + } else { +@@ -559,12 +724,12 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r) + ngx_chain_t out; + ngx_int_t rc, found=0, done=0, err_status=0; + off_t rest=0, length=0; +- ngx_uint_t len, i; ++ ngx_uint_t len; + ngx_slab_pool_t *shpool; + ngx_http_uploadprogress_conf_t *upcf; + ngx_http_uploadprogress_ctx_t *ctx; + ngx_http_uploadprogress_node_t *up; +- ngx_table_elt_t *expires, *cc, **ccp; ++ ngx_table_elt_t *expires, *cc; + ngx_http_uploadprogress_state_t state; + ngx_http_uploadprogress_template_t *t; + +@@ -578,9 +743,13 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r) + return rc; + } + +- /* get the tracking id if any */ +- id = get_tracking_id(r); ++ upcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module); + ++ /* get the tracking id if any */ ++ if(upcf->json_multiple) ++ id = get_tracking_ids_mul(r); ++ else ++ id = get_tracking_id(r); + + if (id == NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +@@ -591,8 +760,6 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r) + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "reportuploads handler found id: %V", id); + +- upcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module); +- + if (upcf->shm_zone == NULL) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "reportuploads no shm_zone for id: %V", id); +@@ -600,32 +767,6 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r) + return NGX_DECLINED; + } + +- ctx = upcf->shm_zone->data; +- +- /* get the original connection of the upload */ +- shpool = (ngx_slab_pool_t *) upcf->shm_zone->shm.addr; +- +- ngx_shmtx_lock(&shpool->mutex); +- +- up = find_node(id, ctx, r->connection->log); +- if (up != NULL) { +- ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "reportuploads found node: %V (rest: %uO, length: %uO, done: %ui, err_status: %ui)", id, up->rest, up->length, up->done, up->err_status); +- rest = up->rest; +- length = up->length; +- done = up->done; +- err_status = up->err_status; +- found = 1; +- } else { +- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "reportuploads not found: %V", id); +- } +- ngx_shmtx_unlock(&shpool->mutex); +- ngx_free(id); +- +- /* send the output */ +- r->headers_out.content_type = upcf->content_type; +- + /* force no-cache */ + expires = r->headers_out.expires; + +@@ -637,6 +778,7 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r) + } + + r->headers_out.expires = expires; ++ expires->next = NULL; + + expires->hash = 1; + expires->key.len = sizeof("Expires") - 1; +@@ -646,37 +788,28 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r) + len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT"); + expires->value.len = len - 1; + +- ccp = r->headers_out.cache_control.elts; +- if (ccp == NULL) { +- +- if (ngx_array_init(&r->headers_out.cache_control, r->pool, +- 1, sizeof(ngx_table_elt_t *)) +- != NGX_OK) { +- return NGX_HTTP_INTERNAL_SERVER_ERROR; +- } +- +- ccp = ngx_array_push(&r->headers_out.cache_control); +- if (ccp == NULL) { +- return NGX_HTTP_INTERNAL_SERVER_ERROR; +- } +- ++ cc = r->headers_out.cache_control; ++ if (cc == NULL) { + cc = ngx_list_push(&r->headers_out.headers); + if (cc == NULL) { ++ expires->hash = 0; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + ++ r->headers_out.cache_control = cc; ++ cc->next = NULL; ++ + cc->hash = 1; + cc->key.len = sizeof("Cache-Control") - 1; + cc->key.data = (u_char *) "Cache-Control"; + +- *ccp = cc; +- + } else { +- for (i = 1; i < r->headers_out.cache_control.nelts; i++) { +- ccp[i]->hash = 0; ++ for (cc = cc->next; cc; cc = cc->next) { ++ cc->hash = 0; + } + +- cc = ccp[0]; ++ cc = r->headers_out.cache_control; ++ cc->next = NULL; + } + + expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT"; +@@ -695,59 +828,282 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r) + } + } + +- ngx_http_set_ctx(r, up, ngx_http_uploadprogress_module); ++ ctx = upcf->shm_zone->data; + +-/* ++ /* get the original connection of the upload */ ++ shpool = (ngx_slab_pool_t *) upcf->shm_zone->shm.addr; ++ ++ if(upcf->json_multiple) ++ { ++ ngx_chain_t * p_chain_end = 0; ++ ngx_chain_t * p_chain_start = 0; ++ size_t offs = 0; ++ u_char * p1 = id->data, * p2; ++ r->headers_out.content_length_n = 0; ++ while(offs < id->len) ++ { ++ p2 = memchr((char *)id->data + offs, ';', id->len - offs); ++ if(!p2) p2 = id->data + id->len; ++ size_t len = p2 - p1; ++ if(len) ++ { ++ ngx_str_t sub_id; ++ sub_id.data = p1; ++ sub_id.len = len; ++ ++ // ----> ++ ++ ngx_shmtx_lock(&shpool->mutex); ++ ++ up = find_node(&sub_id, ctx, r->connection->log); ++ if (up != NULL) { ++ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "reportuploads found node: %V (rest: %uO, length: %uO, done: %ui, err_status: %ui)", &sub_id, up->rest, up->length, up->done, up->err_status); ++ rest = up->rest; ++ length = up->length; ++ done = up->done; ++ err_status = up->err_status; ++ found = 1; ++ } else { ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "reportuploads not found: %V", &sub_id); ++ } ++ ngx_shmtx_unlock(&shpool->mutex); ++ ++ /* send the output */ ++ r->headers_out.content_type = upcf->content_type; ++ ++ if(up == NULL) ++ { ++ // For current id ++ ngx_http_uploadprogress_node_t * tmp_node = ngx_pcalloc(r->pool, sizeof(ngx_http_uploadprogress_node_t) + sub_id.len); ++ tmp_node->len = sub_id.len; ++ ngx_memcpy(tmp_node->data, sub_id.data, sub_id.len); ++ ngx_http_set_ctx(r, tmp_node, ngx_http_uploadprogress_module); ++ } ++ else ++ ngx_http_set_ctx(r, up, ngx_http_uploadprogress_module); ++ ++ ++ if (!found) { ++ state = uploadprogress_state_starting; ++ } else if (err_status >= NGX_HTTP_BAD_REQUEST) { ++ state = uploadprogress_state_error; ++ } else if (done) { ++ state = uploadprogress_state_done; ++ } else if ( length == 0 && rest == 0 ) { ++ state = uploadprogress_state_starting; ++ } else { ++ state = uploadprogress_state_uploading; ++ } ++ ++ t = upcf->templates.elts; ++ ++ if (ngx_http_script_run(r, &response, t[(ngx_uint_t)state].lengths->elts, 0, ++ t[(ngx_uint_t)state].values->elts) == NULL) ++ { ++ ngx_free(id); ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload progress: state=%d, err_status=%ui, remaining=%uO, length=%uO", ++ state, err_status, (length - rest), length); ++ ++ if(p_chain_end) ++ { ++ p_chain_end->next = ngx_palloc(r->pool, sizeof(ngx_chain_t)); ++ if (p_chain_end->next == NULL) { ++ ngx_free(id); ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ p_chain_end = p_chain_end->next; ++ ++ // Insert comma ++ b = ngx_calloc_buf(r->pool); ++ if (b == NULL) { ++ ngx_free(id); ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ b->pos = b->start = ngx_palloc(r->pool, 2); ++ if (b->pos == NULL) { ++ ngx_free(id); ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ b->last = b->end = b->pos + 2; ++ ngx_memcpy(b->pos, ", ", 2); ++ b->temporary = 1; ++ b->memory = 1; ++ ++ p_chain_end->buf = b; ++ p_chain_end->next = ngx_palloc(r->pool, sizeof(ngx_chain_t)); ++ if (p_chain_end->next == NULL) { ++ ngx_free(id); ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ p_chain_end = p_chain_end->next; ++ } ++ else ++ { ++ p_chain_start = p_chain_end = ngx_palloc(r->pool, sizeof(ngx_chain_t)); ++ } ++ ++ b = ngx_calloc_buf(r->pool); ++ if (b == NULL) { ++ ngx_free(id); ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ b->pos = b->start = response.data; ++ b->last = b->end = response.data + response.len; ++ ++ b->temporary = 1; ++ b->memory = 1; ++ ++ p_chain_end->buf = b; ++ p_chain_end->next = NULL; ++ ++ // ----> ++ ++ r->headers_out.content_length_n += b->last - b->pos; ++ ++ p1 = p2 + 1; ++ } ++ offs += len + 1; ++ } ++ ngx_free(id); ++ if(!p_chain_end) // Malformed id ++ { ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "reportuploads malformed multiple id"); ++ return NGX_DECLINED; ++ } ++ // Prepend brace ++ b = ngx_calloc_buf(r->pool); ++ if (b == NULL) { ++ ngx_free(id); ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ b->pos = b->start = ngx_palloc(r->pool, 2); ++ if (b->pos == NULL) { ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ b->last = b->end = b->pos + 2; ++ ngx_memcpy(b->pos, "[ ", 2); ++ b->temporary = 1; ++ b->memory = 1; ++ r->headers_out.content_length_n += 2; ++ ++ out.buf = b; ++ out.next = p_chain_start; ++ ++ // Append brace ++ p_chain_end->next = ngx_palloc(r->pool, sizeof(ngx_chain_t)); ++ if (p_chain_end->next == NULL) { ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ p_chain_end = p_chain_end->next; ++ ++ b = ngx_calloc_buf(r->pool); ++ if (b == NULL) { ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ ++ b->pos = b->start = ngx_palloc(r->pool, 2); ++ if (b->pos == NULL) { ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } ++ b->last = b->end = b->pos + 4; ++ ngx_memcpy(b->pos, " ]\r\n", 4); ++ b->temporary = 1; ++ b->memory = 1; ++ r->headers_out.content_length_n += 4; ++ ++ p_chain_end->buf = b; ++ p_chain_end->next = NULL; ++ ++ r->headers_out.status = NGX_HTTP_OK; ++ p_chain_end->buf->last_buf = 1; ++ } ++ else ++ { ++ ngx_shmtx_lock(&shpool->mutex); ++ ++ up = find_node(id, ctx, r->connection->log); ++ if (up != NULL) { ++ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "reportuploads found node: %V (rest: %uO, length: %uO, done: %ui, err_status: %ui)", id, up->rest, up->length, up->done, up->err_status); ++ rest = up->rest; ++ length = up->length; ++ done = up->done; ++ err_status = up->err_status; ++ found = 1; ++ } else { ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "reportuploads not found: %V", id); ++ } ++ ngx_shmtx_unlock(&shpool->mutex); ++ ngx_free(id); ++ ++ /* send the output */ ++ r->headers_out.content_type = upcf->content_type; ++ ++ ngx_http_set_ctx(r, up, ngx_http_uploadprogress_module); ++ ++ /* + There are 4 possibilities + * request not yet started: found = false + * request in error: err_status >= NGX_HTTP_BAD_REQUEST + * request finished: done = true + * request not yet started but registered: length==0 && rest ==0 +- * reauest in progress: rest > 0 ++ * reauest in progress: rest > 0 + */ + +- if (!found) { +- state = uploadprogress_state_starting; +- } else if (err_status >= NGX_HTTP_BAD_REQUEST) { +- state = uploadprogress_state_error; +- } else if (done) { +- state = uploadprogress_state_done; +- } else if ( length == 0 && rest == 0 ) { +- state = uploadprogress_state_starting; +- } else { +- state = uploadprogress_state_uploading; +- } ++ if (!found) { ++ state = uploadprogress_state_starting; ++ } else if (err_status >= NGX_HTTP_BAD_REQUEST) { ++ state = uploadprogress_state_error; ++ } else if (done) { ++ state = uploadprogress_state_done; ++ } else if ( length == 0 && rest == 0 ) { ++ state = uploadprogress_state_starting; ++ } else { ++ state = uploadprogress_state_uploading; ++ } + +- t = upcf->templates.elts; ++ t = upcf->templates.elts; + +- if (ngx_http_script_run(r, &response, t[(ngx_uint_t)state].lengths->elts, 0, +- t[(ngx_uint_t)state].values->elts) == NULL) +- { +- return NGX_HTTP_INTERNAL_SERVER_ERROR; +- } ++ if (ngx_http_script_run(r, &response, t[(ngx_uint_t)state].lengths->elts, 0, ++ t[(ngx_uint_t)state].values->elts) == NULL) ++ { ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } + +- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +- "upload progress: state=%d, err_status=%ui, remaining=%uO, length=%uO", +- state, err_status, (length - rest), length); ++ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ++ "upload progress: state=%d, err_status=%ui, remaining=%uO, length=%uO", ++ state, err_status, (length - rest), length); + +- b = ngx_calloc_buf(r->pool); +- if (b == NULL) { +- return NGX_HTTP_INTERNAL_SERVER_ERROR; +- } ++ b = ngx_calloc_buf(r->pool); ++ if (b == NULL) { ++ return NGX_HTTP_INTERNAL_SERVER_ERROR; ++ } + +- b->pos = b->start = response.data; +- b->last = b->end = response.data + response.len; ++ b->pos = b->start = response.data; ++ b->last = b->end = response.data + response.len; + +- b->temporary = 1; +- b->memory = 1; ++ b->temporary = 1; ++ b->memory = 1; + +- out.buf = b; +- out.next = NULL; ++ out.buf = b; ++ out.next = NULL; + +- r->headers_out.status = NGX_HTTP_OK; +- r->headers_out.content_length_n = b->last - b->pos; ++ r->headers_out.status = NGX_HTTP_OK; ++ r->headers_out.content_length_n = b->last - b->pos; ++ ++ b->last_buf = 1; ++ } + +- b->last_buf = 1; + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { +@@ -774,8 +1130,8 @@ ngx_http_uploadprogress_handler(ngx_http_request_t * r) + ngx_http_uploadprogress_cleanup_t *upcln; + ngx_pool_cleanup_t *cln; + +- /* Is it a POST connection */ +- if (r->method != NGX_HTTP_POST) { ++ /* Only look for progress IDs on POST, PUT and PATCH */ ++ if (!(r->method & (NGX_HTTP_POST | NGX_HTTP_PUT | NGX_HTTP_PATCH))) { + return NGX_DECLINED; + } + +@@ -852,6 +1208,8 @@ ngx_http_uploadprogress_handler(ngx_http_request_t * r) + up->rest = 0; + up->length = 0; + up->timeout = 0; ++ up->sequence = 0; ++ up->sent_portion = 0; + + /* Properly handles small files where no read events happen after the */ + /* request is first handled (apparently this can happen on linux with epoll) */ +@@ -859,6 +1217,8 @@ ngx_http_uploadprogress_handler(ngx_http_request_t * r) + up->length = r->headers_in.content_length_n; + if (r->request_body) { + up->rest = r->request_body->rest; ++ } else { ++ up->rest = up->length; + } + } + +@@ -1197,6 +1557,8 @@ ngx_http_uploadprogress_errortracker(ngx_http_request_t * r) + up->rest = 0; + up->length = 0; + up->timeout = 0; ++ up->sequence = 0; ++ up->sent_portion = 0; + + ngx_memcpy(up->data, id->data, id->len); + +@@ -1288,6 +1650,7 @@ ngx_http_uploadprogress_create_loc_conf(ngx_conf_t * cf) + elt->values = NULL; + elt->lengths = NULL; + } ++ conf->udp_socket = -1; + + return conf; + } +@@ -1329,6 +1692,7 @@ ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t * cf, void *parent, void *chil + } + + ngx_conf_merge_str_value(conf->header, prev->header, "X-Progress-ID"); ++ ngx_conf_merge_str_value(conf->header_mul, prev->header_mul, "X-ProgressMultiple-ID"); + ngx_conf_merge_str_value(conf->jsonp_parameter, prev->jsonp_parameter, "callback"); + + return NGX_CONF_OK; +@@ -1447,6 +1811,7 @@ ngx_http_track_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf) + ngx_http_core_loc_conf_t *clcf; + ngx_http_uploadprogress_conf_t *lzcf = conf; + ngx_str_t *value; ++ ngx_url_t url; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "ngx_track_uploads in"); + +@@ -1471,10 +1836,27 @@ ngx_http_track_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf) + lzcf->timeout = ngx_parse_time(&value[2], 1); + if (lzcf->timeout == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, +- "track_uploads \"%V\" timeout value invalid", &value[1]); ++ "track_uploads \"%V\" timeout value invalid", &value[2]); + return NGX_CONF_ERROR; + } + ++ if(cf->args->nelts > 3) ++ { ++ ngx_memzero(&url, sizeof(ngx_url_t)); ++ url.url = value[3]; ++ url.default_port = 80; ++ url.no_resolve = 0; ++ ++ if(ngx_parse_url(cf->pool, &url) != NGX_OK) ++ { ++ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Invalid graphite server %V: %s", &url.host, url.err); ++ return NGX_CONF_ERROR; ++ } ++ lzcf->progress_server = url.addrs[0]; ++ if(lzcf->udp_socket == -1) ++ lzcf->udp_socket = ngx_socket(PF_INET, SOCK_DGRAM, 0); ++ } ++ + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + lzcf->handler = clcf->handler; + if ( lzcf->handler == NULL ) +@@ -1555,6 +1937,8 @@ ngx_http_upload_progress_template(ngx_conf_t * cf, ngx_command_t * cmd, void *co + ngx_http_uploadprogress_state_map_t *m = ngx_http_uploadprogress_state_map; + ngx_http_uploadprogress_template_t *t; + ++ upcf->json_multiple = 0; ++ + value = cf->args->elts; + + while(m->name.data != NULL) { +@@ -1584,6 +1968,8 @@ ngx_http_upload_progress_java_output(ngx_conf_t * cf, ngx_command_t * cmd, void + ngx_uint_t i; + char* rc; + ++ upcf->json_multiple = 0; ++ + t = (ngx_http_uploadprogress_template_t*)upcf->templates.elts; + + for(i = 0;i < upcf->templates.nelts;i++) { +@@ -1608,6 +1994,8 @@ ngx_http_upload_progress_json_output(ngx_conf_t * cf, ngx_command_t * cmd, void + ngx_uint_t i; + char* rc; + ++ upcf->json_multiple = 0; ++ + t = (ngx_http_uploadprogress_template_t*)upcf->templates.elts; + + for(i = 0;i < upcf->templates.nelts;i++) { +@@ -1632,6 +2020,8 @@ ngx_http_upload_progress_jsonp_output(ngx_conf_t * cf, ngx_command_t * cmd, void + ngx_uint_t i; + char* rc; + ++ upcf->json_multiple = 0; ++ + t = (ngx_http_uploadprogress_template_t*)upcf->templates.elts; + + for(i = 0;i < upcf->templates.nelts;i++) { +@@ -1648,6 +2038,58 @@ ngx_http_upload_progress_jsonp_output(ngx_conf_t * cf, ngx_command_t * cmd, void + return NGX_CONF_OK; + } + ++static char* ++ngx_http_upload_progress_json_multiple_output(ngx_conf_t * cf, ngx_command_t * cmd, void *conf) ++{ ++ ngx_http_uploadprogress_conf_t *upcf = conf; ++ ngx_http_uploadprogress_template_t *t; ++ ngx_uint_t i; ++ char* rc; ++ ++ upcf->json_multiple = 1; ++ ++ t = (ngx_http_uploadprogress_template_t*)upcf->templates.elts; ++ ++ for(i = 0;i < upcf->templates.nelts;i++) { ++ rc = ngx_http_upload_progress_set_template(cf, t + i, ngx_http_uploadprogress_json_multiple_defaults + i); ++ ++ if(rc != NGX_CONF_OK) { ++ return rc; ++ } ++ } ++ ++ upcf->content_type.data = (u_char*)"application/json"; ++ upcf->content_type.len = sizeof("application/json") - 1; ++ ++ return NGX_CONF_OK; ++} ++ ++static char* ++ngx_http_upload_progress_jsonp_multiple_output(ngx_conf_t * cf, ngx_command_t * cmd, void *conf) ++{ ++ ngx_http_uploadprogress_conf_t *upcf = conf; ++ ngx_http_uploadprogress_template_t *t; ++ ngx_uint_t i; ++ char* rc; ++ ++ upcf->json_multiple = 1; ++ ++ t = (ngx_http_uploadprogress_template_t*)upcf->templates.elts; ++ ++ for(i = 0;i < upcf->templates.nelts;i++) { ++ rc = ngx_http_upload_progress_set_template(cf, t + i, ngx_http_uploadprogress_jsonp_multiple_defaults + i); ++ ++ if(rc != NGX_CONF_OK) { ++ return rc; ++ } ++ } ++ ++ upcf->content_type.data = (u_char*)"application/json"; ++ upcf->content_type.len = sizeof("application/json") - 1; ++ ++ return NGX_CONF_OK; ++} ++ + static ngx_int_t ngx_http_uploadprogress_received_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) + { +@@ -1724,6 +2166,30 @@ ngx_http_uploadprogress_status_variable(ngx_http_request_t *r, + return NGX_OK; + } + ++static ngx_int_t ++ngx_http_uploadprogress_id_variable(ngx_http_request_t *r, ++ ngx_http_variable_value_t *v, uintptr_t data) ++{ ++ ngx_http_uploadprogress_node_t *up; ++ u_char *p; ++ ++ up = ngx_http_get_module_ctx(r, ngx_http_uploadprogress_module); ++ ++ p = ngx_palloc(r->pool, up->len); ++ if (p == NULL) { ++ return NGX_ERROR; ++ } ++ ++ v->len = up->len; ++ v->data = p; ++ ngx_memcpy(v->data, up->data, up->len); ++ v->valid = 1; ++ v->no_cacheable = 0; ++ v->not_found = 0; ++ ++ return NGX_OK; ++} ++ + static ngx_int_t + ngx_http_uploadprogress_callback_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) diff --git a/main/nginx/nginx.conf b/main/nginx/nginx.conf index bc784a31879..89fa9854bf6 100644 --- a/main/nginx/nginx.conf +++ b/main/nginx/nginx.conf @@ -14,9 +14,8 @@ error_log /var/log/nginx/error.log warn; # Includes files with directives to load dynamic modules. include /etc/nginx/modules/*.conf; -# Uncomment to include files with config snippets into the root context. -# NOTE: This will be enabled by default in Alpine 3.15. -#include /etc/nginx/conf.d/*.conf; +# Include files with config snippets into the root context. +include /etc/nginx/conf.d/*.conf; events { # The maximum number of simultaneous connections that can be opened by @@ -32,7 +31,7 @@ http { # Name servers used to resolve names of upstream servers into addresses. # It's also needed when using tcpsocket and udpsocket in Lua modules. - #resolver 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001; + #resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001]; # Don't tell nginx version to the clients. Default is 'on'. server_tokens off; @@ -102,6 +101,3 @@ http { # Includes virtual hosts configs. include /etc/nginx/http.d/*.conf; } - -# TIP: Uncomment if you use stream module. -#include /etc/nginx/stream.conf; diff --git a/main/nginx/nginx.post-upgrade b/main/nginx/nginx.post-upgrade index 58e8e1baed6..3062f98223f 100644 --- a/main/nginx/nginx.post-upgrade +++ b/main/nginx/nginx.post-upgrade @@ -22,38 +22,25 @@ fi # Handle transition from /etc/nginx/conf.d to /etc/nginx/http.d. if [ "$(apk version -t "$ver_old" '1.18.0-r13')" = '<' ]; then - default_conf='/usr/share/nginx/http-default_server.conf' - - if [ -z "$(ls -A /etc/nginx/conf.d 2>/dev/null)" ]; then - # conf.d dir doesn't exist or is empty, so the user doesn't use it. - # Thus we can install default.conf to the new directory. - install -m644 "$default_conf" /etc/nginx/http.d/default.conf - - else - if ! [ -e /etc/nginx/conf.d/default.conf ]; then - # conf.d dir exists and is not empty, but there's no default.conf - # file, so the user probably did not modify it and apk has removed - # it during this upgrade. Prior this version, the default.conf - # would be installed, so install it now for backward compatibility. - install -m644 "$default_conf" /etc/nginx/conf.d/default.conf - fi - if ! [ -e /etc/nginx/nginx.conf.apk-new ]; then - # There's no updated nginx.conf, so the user didn't modify this - # config and apk replaced it during this upgrade. However, the - # user has some vhost configs in the old directory, so we have - # to revert the include back to the legacy path. - sed -i 's|include /etc/nginx/http\.d|# WARNING: Do not use this directory for virtual hosts anymore, use directory http.d!\n\tinclude /etc/nginx/conf.d|' \ - /etc/nginx/nginx.conf - fi + if ! [ -e /etc/nginx/http.d/default.conf ]; then + install -D -m644 /usr/share/nginx/http-default_server.conf \ + /etc/nginx/http.d/default.conf fi +fi - cat >&2 <<-EOF - * - * The default and preferred location for nginx vhost configs has been changed - * from /etc/nginx/conf.d to /etc/nginx/http.d. Although we did our best to not - * break existing setups by this upgrade, we strongly recommend to verify it. - * - EOF +# Handle transition from /etc/nginx/conf.d to /etc/nginx/http.d. +if [ "$(apk version -t "$ver_old" '1.22.0-r7')" = '<' ]; then + if sed -En '/^http\s*\{/,/^\}/{ /^\s*include\s+\/etc\/nginx\/conf.d\/.*;/p }' /etc/nginx/nginx.conf | grep -q .; then + cat >&2 <<-EOF + !! + !! Found 'include /etc/nginx/conf.d/*.conf' in the 'http' section! + !! The default and preferred location for nginx http configs has been changed + !! from /etc/nginx/conf.d to /etc/nginx/http.d. The former is now used for + !! configs to be included in the root context. Move your vhost configs from + !! /etc/nginx/conf.d/ to /etc/nginx/http.d/ and update /etc/nginx/nginx.conf. + !! + EOF + fi fi # Handle trasition from /var/tmp/nginx to /var/lib/nginx/tmp diff --git a/main/nginx/ngx-fancyindex~fix-404-on-fs-root.patch b/main/nginx/ngx-fancyindex~fix-404-on-fs-root.patch new file mode 100644 index 00000000000..1c0df2bf257 --- /dev/null +++ b/main/nginx/ngx-fancyindex~fix-404-on-fs-root.patch @@ -0,0 +1,27 @@ +Patch-Source: https://github.com/aperezdc/ngx-fancyindex/commit/83bef5c8a633ebbf96576eeb596a972a5816e057 +-- +From 83bef5c8a633ebbf96576eeb596a972a5816e057 Mon Sep 17 00:00:00 2001 +From: Ryan Schmidt <git@ryandesign.com> +Date: Fri, 13 May 2022 00:16:09 -0500 +Subject: [PATCH] Fix 404 not found when indexing filesystem root + +Backport of https://github.com/nginx/nginx/commit/4c89c09ad8e574509446efab0347b124372bc53a + +Fixes #107 + +diff --git a/ngx_http_fancyindex_module.c b/ngx_http_fancyindex_module.c +index e6928dd..dd721d0 100644 +--- a/ngx_http_fancyindex_module.c ++++ b/ngx_http_fancyindex_module.c +@@ -684,7 +684,10 @@ make_content_buf( + return NGX_HTTP_INTERNAL_SERVER_ERROR; + + allocated = path.len; +- path.len = last - path.data - 1; ++ path.len = last - path.data; ++ if (path.len > 1) { ++ path.len--; ++ } + path.data[path.len] = '\0'; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, diff --git a/main/nginx/ngx-fancyindex~fix-missing-saturday.patch b/main/nginx/ngx-fancyindex~fix-missing-saturday.patch new file mode 100644 index 00000000000..b34f3e5d361 --- /dev/null +++ b/main/nginx/ngx-fancyindex~fix-missing-saturday.patch @@ -0,0 +1,25 @@ +Patch-Source: https://github.com/aperezdc/ngx-fancyindex/commit/674e99547d21b8bd9a36dc5d8689d08632d3a34d +-- +From 674e99547d21b8bd9a36dc5d8689d08632d3a34d Mon Sep 17 00:00:00 2001 +From: Adrian Perez de Castro <aperez@igalia.com> +Date: Thu, 19 Jan 2023 20:51:08 +0200 +Subject: [PATCH] Add missing entry in long weekday names array + +The entry for Saturday was missing, as pointed out in the bug report. +While at it, add a test case. + +Fixes #157 + +diff --git a/ngx_http_fancyindex_module.c b/ngx_http_fancyindex_module.c +index bfccdc8..ed349d5 100644 +--- a/ngx_http_fancyindex_module.c ++++ b/ngx_http_fancyindex_module.c +@@ -37,7 +37,7 @@ static const char *short_weekday[] = { + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", + }; + static const char *long_weekday[] = { +- "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Sunday", ++ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", + }; + static const char *short_month[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", diff --git a/main/nginx/njs~nginx-1.20.x-compat.patch b/main/nginx/njs~nginx-1.20.x-compat.patch deleted file mode 100644 index c24a12a59b0..00000000000 --- a/main/nginx/njs~nginx-1.20.x-compat.patch +++ /dev/null @@ -1,15 +0,0 @@ -Fix compatibility with nginx 1.20.x. - -See-Also: https://github.com/nginx/njs/issues/18 - ---- a/nginx/config.make -+++ b/nginx/config.make -@@ -3,7 +3,7 @@ - $ngx_addon_dir/../build/libnjs.a: $NGX_MAKEFILE - cd $ngx_addon_dir/.. \\ - && if [ -f build/Makefile ]; then \$(MAKE) clean; fi \\ -- && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure --no-openssl --no-pcre \\ -+ && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure \\ - && \$(MAKE) libnjs - - END diff --git a/main/nginx/no-werror.patch b/main/nginx/no-werror.patch new file mode 100644 index 00000000000..58ab7f48537 --- /dev/null +++ b/main/nginx/no-werror.patch @@ -0,0 +1,11 @@ +--- a/auto/cc/gcc ++++ b/auto/cc/gcc +@@ -166,7 +166,7 @@ + + + # stop on warning +-CFLAGS="$CFLAGS -Werror" ++CFLAGS="$CFLAGS" + + # debug + CFLAGS="$CFLAGS -g" diff --git a/main/nginx/stream.conf b/main/nginx/stream.conf index 24387445497..4b7177de0c3 100644 --- a/main/nginx/stream.conf +++ b/main/nginx/stream.conf @@ -1,4 +1,4 @@ -# /etc/nginx/stream.conf +# /etc/nginx/conf.d/stream.conf stream { # Specifies the main log format. diff --git a/main/nginx/traffic-accounting-nginx-module~fix-memory-leak.patch b/main/nginx/traffic-accounting-nginx-module~fix-memory-leak.patch new file mode 100644 index 00000000000..4822d25b656 --- /dev/null +++ b/main/nginx/traffic-accounting-nginx-module~fix-memory-leak.patch @@ -0,0 +1,253 @@ +Patch-Source: https://github.com/Lax/traffic-accounting-nginx-module/commit/900fceedcb00a840510d547a5b1e135b4f340745 +Patch-Source: https://github.com/Lax/traffic-accounting-nginx-module/commit/c0667a81a3ab3f62f30e9051179dc705261ec556 +-- +From 900fceedcb00a840510d547a5b1e135b4f340745 Mon Sep 17 00:00:00 2001 +From: Tony Liu <Tony.Liu@harmonicinc.com> +Date: Thu, 19 Aug 2021 08:03:47 +0000 +Subject: [PATCH] use ngx_calloc to replace ngx_pcalloc to avoid memory leak + https://github.com/Lax/traffic-accounting-nginx-module/issues/53 + +--- + src/http/ngx_http_accounting_module.c | 8 +++---- + src/ngx_traffic_accounting.h | 8 +++---- + src/ngx_traffic_accounting_module.c | 11 +++++----- + src/ngx_traffic_accounting_module.h | 4 ++-- + src/ngx_traffic_accounting_period_metrics.c | 24 ++++++++++----------- + src/stream/ngx_stream_accounting_module.c | 8 +++---- + 6 files changed, 30 insertions(+), 33 deletions(-) + +diff --git a/src/http/ngx_http_accounting_module.c b/src/http/ngx_http_accounting_module.c +index 63eccf0..23a5fc3 100644 +--- a/src/http/ngx_http_accounting_module.c ++++ b/src/http/ngx_http_accounting_module.c +@@ -139,7 +139,7 @@ ngx_http_accounting_process_init(ngx_cycle_t *cycle) + } + + if (amcf->current == NULL) { +- if (ngx_traffic_accounting_period_create(cycle->pool, amcf) != NGX_OK) ++ if (ngx_traffic_accounting_period_create(amcf) != NGX_OK) + return NGX_ERROR; + } + +@@ -206,7 +206,7 @@ worker_process_alarm_handler(ngx_event_t *ev) + + amcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, ngx_http_accounting_module); + +- ngx_traffic_accounting_period_rotate(amcf->current->pool, amcf); ++ ngx_traffic_accounting_period_rotate(amcf); + ngx_traffic_accounting_period_rbtree_iterate(amcf->previous, + worker_process_export_metrics, + amcf->previous->created_at, +@@ -243,10 +243,10 @@ ngx_http_accounting_request_handler(ngx_http_request_t *r) + + amcf = ngx_http_get_module_main_conf(r, ngx_http_accounting_module); + +- metrics = ngx_traffic_accounting_period_fetch_metrics(amcf->current, accounting_id); ++ metrics = ngx_traffic_accounting_period_fetch_metrics(amcf->current, accounting_id, amcf->log); + if (metrics == NULL) { return NGX_ERROR; } + +- if (ngx_traffic_accounting_metrics_init(metrics, amcf->current->pool, ngx_http_statuses_len) == NGX_ERROR) ++ if (ngx_traffic_accounting_metrics_init(metrics, ngx_http_statuses_len, amcf->log) == NGX_ERROR) + return NGX_ERROR; + + amcf->current->updated_at = ngx_timeofday(); +diff --git a/src/ngx_traffic_accounting.h b/src/ngx_traffic_accounting.h +index 1812927..462becf 100644 +--- a/src/ngx_traffic_accounting.h ++++ b/src/ngx_traffic_accounting.h +@@ -38,21 +38,19 @@ typedef struct { + ngx_rbtree_t rbtree; + ngx_rbtree_node_t sentinel; + +- ngx_pool_t *pool; +- + ngx_time_t *created_at; + ngx_time_t *updated_at; + } ngx_traffic_accounting_period_t; + +-ngx_int_t ngx_traffic_accounting_metrics_init(ngx_traffic_accounting_metrics_t *metrics, ngx_pool_t *pool, size_t len); ++ngx_int_t ngx_traffic_accounting_metrics_init(ngx_traffic_accounting_metrics_t *metrics, size_t len, ngx_log_t *log); + + ngx_int_t ngx_traffic_accounting_period_init(ngx_traffic_accounting_period_t *period); +-void ngx_traffic_accounting_period_insert(ngx_traffic_accounting_period_t *period, ngx_str_t *name); ++void ngx_traffic_accounting_period_insert(ngx_traffic_accounting_period_t *period, ngx_str_t *name, ngx_log_t *log); + void ngx_traffic_accounting_period_insert_metrics(ngx_traffic_accounting_period_t *period, ngx_traffic_accounting_metrics_t *metrics); + void ngx_traffic_accounting_period_delete(ngx_traffic_accounting_period_t *period, ngx_str_t *name); + void ngx_traffic_accounting_period_delete_metrics(ngx_traffic_accounting_period_t *period, ngx_traffic_accounting_metrics_t *metrics); + ngx_traffic_accounting_metrics_t * ngx_traffic_accounting_period_lookup_metrics(ngx_traffic_accounting_period_t *period, ngx_str_t *name); +-ngx_traffic_accounting_metrics_t * ngx_traffic_accounting_period_fetch_metrics(ngx_traffic_accounting_period_t *period, ngx_str_t *name); ++ngx_traffic_accounting_metrics_t * ngx_traffic_accounting_period_fetch_metrics(ngx_traffic_accounting_period_t *period, ngx_str_t *name, ngx_log_t *log); + + typedef ngx_int_t (*ngx_traffic_accounting_period_iterate_func)(void *val, void *para1, void *para2); + +diff --git a/src/ngx_traffic_accounting_module.c b/src/ngx_traffic_accounting_module.c +index ebc877a..2291db7 100644 +--- a/src/ngx_traffic_accounting_module.c ++++ b/src/ngx_traffic_accounting_module.c +@@ -9,15 +9,14 @@ + + + ngx_int_t +-ngx_traffic_accounting_period_create(ngx_pool_t *pool, ngx_traffic_accounting_main_conf_t *amcf) ++ngx_traffic_accounting_period_create(ngx_traffic_accounting_main_conf_t *amcf) + { + ngx_traffic_accounting_period_t *period; + +- period = ngx_pcalloc(pool, sizeof(ngx_traffic_accounting_period_t)); ++ period = ngx_calloc(sizeof(ngx_traffic_accounting_period_t), amcf->log); + if (period == NULL) + return NGX_ERROR; + +- period->pool = pool; + ngx_traffic_accounting_period_init(period); + + period->created_at = ngx_timeofday(); +@@ -28,11 +27,11 @@ ngx_traffic_accounting_period_create(ngx_pool_t *pool, ngx_traffic_accounting_ma + } + + ngx_int_t +-ngx_traffic_accounting_period_rotate(ngx_pool_t *pool, ngx_traffic_accounting_main_conf_t *amcf) ++ngx_traffic_accounting_period_rotate(ngx_traffic_accounting_main_conf_t *amcf) + { +- ngx_pfree(pool, amcf->previous); ++ ngx_free(amcf->previous); + + amcf->previous = amcf->current; + +- return ngx_traffic_accounting_period_create(pool, amcf); ++ return ngx_traffic_accounting_period_create(amcf); + } +diff --git a/src/ngx_traffic_accounting_module.h b/src/ngx_traffic_accounting_module.h +index 08881f1..adfccec 100644 +--- a/src/ngx_traffic_accounting_module.h ++++ b/src/ngx_traffic_accounting_module.h +@@ -46,8 +46,8 @@ ngx_str_t * ngx_traffic_accounting_get_accounting_id(void *entry, ngx_get_loc_co + ngx_get_indexed_variable_pt get_indexed_variable); + + +-ngx_int_t ngx_traffic_accounting_period_create(ngx_pool_t *pool, ngx_traffic_accounting_main_conf_t *amcf); +-ngx_int_t ngx_traffic_accounting_period_rotate(ngx_pool_t *pool, ngx_traffic_accounting_main_conf_t *amcf); ++ngx_int_t ngx_traffic_accounting_period_create(ngx_traffic_accounting_main_conf_t *amcf); ++ngx_int_t ngx_traffic_accounting_period_rotate(ngx_traffic_accounting_main_conf_t *amcf); + + + #endif /* _NGX_TRAFFIC_ACCOUNTING_MODULE_H_INCLUDED_ */ +diff --git a/src/ngx_traffic_accounting_period_metrics.c b/src/ngx_traffic_accounting_period_metrics.c +index b6b7055..302bd84 100644 +--- a/src/ngx_traffic_accounting_period_metrics.c ++++ b/src/ngx_traffic_accounting_period_metrics.c +@@ -10,17 +10,17 @@ + static void ngx_traffic_accounting_period_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); + + ngx_int_t +-ngx_traffic_accounting_metrics_init(ngx_traffic_accounting_metrics_t *metrics, ngx_pool_t *pool, size_t len) ++ngx_traffic_accounting_metrics_init(ngx_traffic_accounting_metrics_t *metrics, size_t len, ngx_log_t *log) + { + if (metrics->nr_status == NULL) { +- metrics->nr_status = ngx_pcalloc(pool, sizeof(ngx_uint_t) * len); ++ metrics->nr_status = ngx_calloc(sizeof(ngx_uint_t) * len, log); + + if (metrics->nr_status == NULL) + return NGX_ERROR; + } + + if (metrics->nr_upstream_status == NULL) { +- metrics->nr_upstream_status = ngx_pcalloc(pool, sizeof(ngx_uint_t) * len); ++ metrics->nr_upstream_status = ngx_calloc(sizeof(ngx_uint_t) * len, log); + + if (metrics->nr_upstream_status == NULL) + return NGX_ERROR; +@@ -39,14 +39,14 @@ ngx_traffic_accounting_period_init(ngx_traffic_accounting_period_t *period) + } + + void +-ngx_traffic_accounting_period_insert(ngx_traffic_accounting_period_t *period, ngx_str_t *name) ++ngx_traffic_accounting_period_insert(ngx_traffic_accounting_period_t *period, ngx_str_t *name, ngx_log_t *log) + { + ngx_traffic_accounting_metrics_t *metrics; + +- metrics = ngx_pcalloc(period->pool, sizeof(ngx_traffic_accounting_metrics_t)); ++ metrics = ngx_calloc(sizeof(ngx_traffic_accounting_metrics_t), log); + + void *data; +- data = ngx_pcalloc(period->pool, name->len+1); ++ data = ngx_calloc(name->len+1, log); + ngx_memcpy(data, name->data, name->len); + + metrics->name.data = data; +@@ -82,7 +82,7 @@ void + ngx_traffic_accounting_period_delete_metrics(ngx_traffic_accounting_period_t *period, ngx_traffic_accounting_metrics_t *metrics) + { + ngx_rbtree_delete(&period->rbtree, &metrics->rbnode); +- ngx_pfree(period->pool, metrics); ++ ngx_free(metrics); + } + + ngx_traffic_accounting_metrics_t * +@@ -124,7 +124,7 @@ ngx_traffic_accounting_period_lookup_metrics(ngx_traffic_accounting_period_t *pe + } + + ngx_traffic_accounting_metrics_t * +-ngx_traffic_accounting_period_fetch_metrics(ngx_traffic_accounting_period_t *period, ngx_str_t *name) ++ngx_traffic_accounting_period_fetch_metrics(ngx_traffic_accounting_period_t *period, ngx_str_t *name, ngx_log_t *log) + { + ngx_traffic_accounting_metrics_t *n; + +@@ -132,7 +132,7 @@ ngx_traffic_accounting_period_fetch_metrics(ngx_traffic_accounting_period_t *per + if (n != NULL) + return n; + +- ngx_traffic_accounting_period_insert(period, name); ++ ngx_traffic_accounting_period_insert(period, name, log); + + return ngx_traffic_accounting_period_lookup_metrics(period, name); + } +@@ -158,9 +158,10 @@ ngx_traffic_accounting_period_rbtree_iterate(ngx_traffic_accounting_period_t *pe + if (rc == NGX_DONE) { + /* NGX_DONE -> destroy node */ + ngx_rbtree_delete(rbtree, node); +- ngx_pfree(period->pool, n->nr_status); +- ngx_pfree(period->pool, n->nr_upstream_status); +- ngx_pfree(period->pool, n); ++ ngx_free(n->nr_status); ++ ngx_free(n->nr_upstream_status); ++ ngx_free(n->name.data); ++ ngx_free(n); + + goto done; + } +diff --git a/src/stream/ngx_stream_accounting_module.c b/src/stream/ngx_stream_accounting_module.c +index b1839d1..3db787d 100644 +--- a/src/stream/ngx_stream_accounting_module.c ++++ b/src/stream/ngx_stream_accounting_module.c +@@ -136,7 +136,7 @@ ngx_stream_accounting_process_init(ngx_cycle_t *cycle) + } + + if (amcf->current == NULL) { +- if (ngx_traffic_accounting_period_create(cycle->pool, amcf) != NGX_OK) ++ if (ngx_traffic_accounting_period_create(amcf) != NGX_OK) + return NGX_ERROR; + } + +@@ -203,7 +203,7 @@ worker_process_alarm_handler(ngx_event_t *ev) + + amcf = ngx_stream_cycle_get_module_main_conf(ngx_cycle, ngx_stream_accounting_module); + +- ngx_traffic_accounting_period_rotate(amcf->current->pool, amcf); ++ ngx_traffic_accounting_period_rotate(amcf); + ngx_traffic_accounting_period_rbtree_iterate(amcf->previous, + worker_process_export_metrics, + amcf->previous->created_at, +@@ -240,10 +240,10 @@ ngx_stream_accounting_session_handler(ngx_stream_session_t *s) + + amcf = ngx_stream_get_module_main_conf(s, ngx_stream_accounting_module); + +- metrics = ngx_traffic_accounting_period_fetch_metrics(amcf->current, accounting_id); ++ metrics = ngx_traffic_accounting_period_fetch_metrics(amcf->current, accounting_id, amcf->log); + if (metrics == NULL) { return NGX_ERROR; } + +- if (ngx_traffic_accounting_metrics_init(metrics, amcf->current->pool, ngx_stream_statuses_len) == NGX_ERROR) ++ if (ngx_traffic_accounting_metrics_init(metrics, ngx_stream_statuses_len, amcf->log) == NGX_ERROR) + return NGX_ERROR; + + amcf->current->updated_at = ngx_timeofday(); diff --git a/main/nginx/zstd-nginx-module~fix-infinite-loop.patch b/main/nginx/zstd-nginx-module~fix-infinite-loop.patch new file mode 100644 index 00000000000..7f71271681a --- /dev/null +++ b/main/nginx/zstd-nginx-module~fix-infinite-loop.patch @@ -0,0 +1,47 @@ +patch-source: https://github.com/tokers/zstd-nginx-module/pull/23 + +From 7f86e5bbd7711b216688c418ffe2a64c9b25f319 Mon Sep 17 00:00:00 2001 +From: drawing <cppbreak@qq.com> +Date: Mon, 12 Jun 2023 14:37:00 +0800 +Subject: [PATCH] bugfix: fix zstd module infinite loop when upstream return + content-length abnormal + +--- + filter/ngx_http_zstd_filter_module.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/filter/ngx_http_zstd_filter_module.c b/filter/ngx_http_zstd_filter_module.c +index d5784ba..cea386f 100644 +--- a/filter/ngx_http_zstd_filter_module.c ++++ b/filter/ngx_http_zstd_filter_module.c +@@ -440,6 +440,8 @@ ngx_http_zstd_filter_compress(ngx_http_request_t *r, ngx_http_zstd_ctx_t *ctx) + ctx->out_buf->last += ctx->buffer_out.pos - pos_out; + ctx->redo = 0; + ++ unsigned last_action = ctx->action; ++ + if (rc > 0) { + if (ctx->action == NGX_HTTP_ZSTD_FILTER_COMPRESS) { + ctx->action = NGX_HTTP_ZSTD_FILTER_FLUSH; +@@ -459,7 +461,7 @@ ngx_http_zstd_filter_compress(ngx_http_request_t *r, ngx_http_zstd_ctx_t *ctx) + ctx->action = NGX_HTTP_ZSTD_FILTER_COMPRESS; /* restore */ + } + +- if (ngx_buf_size(ctx->out_buf) == 0) { ++ if (ngx_buf_size(ctx->out_buf) == 0 && last_action != NGX_HTTP_ZSTD_FILTER_FLUSH) { + return NGX_AGAIN; + } + +@@ -469,6 +471,12 @@ ngx_http_zstd_filter_compress(ngx_http_request_t *r, ngx_http_zstd_ctx_t *ctx) + } + + b = ctx->out_buf; ++ if (ngx_buf_size(b) == 0) { ++ b = ngx_calloc_buf(ctx->request->pool); ++ if (b == NULL) { ++ return NGX_ERROR; ++ } ++ } + + if (rc == 0 && (ctx->flush || ctx->last)) { + r->connection->buffered &= ~NGX_HTTP_GZIP_BUFFERED; |