From 2a15f069d05c4ea626e8b348ed14bd076fa39bda Mon Sep 17 00:00:00 2001 From: tzssangglass Date: Wed, 17 Jun 2026 10:25:22 +0800 Subject: [PATCH 1/2] ci: switch HTTP/3 curl to static-curl 8.20.0. --- .github/workflows/build_and_test.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index b0eebcc1ca..74d2df8f2f 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -153,10 +153,12 @@ jobs: https://github.com/openresty/openresty-deps-prebuild/releases/download/v20230902/drizzle7-$DRIZZLE_VER.tar.gz fi wget https://github.com/openresty/openresty-deps-prebuild/releases/download/v20230902/boringssl-20230902-x64-focal.tar.gz - wget https://github.com/openresty/openresty-deps-prebuild/releases/download/v20230902/curl-h3-x64-focal.tar.gz + wget https://github.com/stunnel/static-curl/releases/download/8.20.0/curl-linux-x86_64-glibc-8.20.0.tar.xz - - name: Install curl-h3 - run: sudo tar -C / -xf curl-h3-x64-focal.tar.gz + - name: Install HTTP/3-capable curl + run: | + sudo mkdir -p /opt/curl/bin + sudo tar -C /opt/curl/bin -xf curl-linux-x86_64-glibc-8.20.0.tar.xz curl - name: Start memcached (native, UDP enabled) run: | @@ -239,7 +241,7 @@ jobs: - name: Build nginx run: | export LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH - export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:/opt/curl-h3/bin:$PATH + export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:/opt/curl/bin:$PATH export NGX_BUILD_CC=$CC sh util/build-without-ssl.sh ${{ matrix.NGINX_VERSION }} > build.log 2>&1 || (cat build.log && exit 1) sh util/build-with-dd.sh ${{ matrix.NGINX_VERSION }} > build.log 2>&1 || (cat build.log && exit 1) @@ -250,7 +252,7 @@ jobs: - name: Run releng check run: | - export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:/opt/curl-h3/bin:$PATH + export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:/opt/curl/bin:$PATH ngx-releng > check.txt || true lines=$(wc -l check.txt | awk '{print $1}') if [ "$lines" -gt 5 ]; then cat check.txt; exit 1; fi @@ -272,7 +274,7 @@ jobs: - name: Run tests run: | export LD_LIBRARY_PATH=$LUAJIT_LIB:$PWD/mockeagain:$LD_LIBRARY_PATH - export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:/opt/curl-h3/bin:$PATH + export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:/opt/curl/bin:$PATH export LD_PRELOAD=$PWD/mockeagain/mockeagain.so export TEST_NGINX_HTTP3_CRT=$PWD/t/cert/http3/http3.crt export TEST_NGINX_HTTP3_KEY=$PWD/t/cert/http3/http3.key From d9403d4df0e742d45be6467cc0a28931ca7fd0e4 Mon Sep 17 00:00:00 2001 From: tzssangglass Date: Thu, 25 Jun 2026 23:00:03 +0800 Subject: [PATCH 2/2] tests: adapt curl_error expectations to curl 8.20.0 CI switched to curl 8.20.0 (static-curl 8.20.0). Several curl changes since 8.3.0 altered the stderr messages our tests match against, so the affected `--- curl_error` expectations need updating. The changes map to three upstream curl commits: * http/3: add description for known server error codes (f6e8531c03ed, 8.19.0) appends the error code and its name to the HTTP/3 stream reset message: "HTTP/3 stream 0 reset by server" -> "HTTP/3 stream 0 reset by server (error 0x102 INTERNAL_ERROR)" -> t/005-exit.t * h2+h3: align stream close handling (0f042efcb1, 8.19.0) rewrites the HTTP/2 stream reset message and aligns it with HTTP/3: "HTTP/2 stream 1 was not closed cleanly" / "was reset" -> "HTTP/2 stream 1 reset by server (error 0x2 INTERNAL_ERROR)" (it also changed the HTTP/3 path that emits "ngtcp2_conn_writev_stream returned error: ERR_CLOSING") -> t/033-ctx.t, t/041-header-filter.t, t/091-coroutine.t * ngtcp2: check error code on connect failure (115fe808f2, 8.17.0) makes a QUIC handshake aborted by the server a permanent connect failure (CURLE_COULDNT_CONNECT, exit 7) instead of retrying until a timeout. The test (which deliberately fails the handshake via ngx.exit(500) in ssl_certificate_by_lua*) now sees: "curl: (28) Connection time-out" -> "Failed to connect to ... port ... after N ms: Could not connect to server" -> t/166-ssl-client-hello.t --- t/005-exit.t | 5 ++--- t/033-ctx.t | 2 +- t/041-header-filter.t | 44 ++++++++++++++++++++-------------------- t/091-coroutine.t | 4 ++-- t/166-ssl-client-hello.t | 2 +- 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/t/005-exit.t b/t/005-exit.t index 7b82a81e4c..e4a883d131 100644 --- a/t/005-exit.t +++ b/t/005-exit.t @@ -783,7 +783,7 @@ GET /t --- no_error_log [error] --- curl_error -curl: (95) HTTP/3 stream 0 reset by server +curl: (95) HTTP/3 stream 0 reset by server (error 0x102 INTERNAL_ERROR) @@ -802,8 +802,7 @@ GET /t --- no_error_log [error] --- curl_error -curl: (95) HTTP/3 stream 0 reset by server - +curl: (95) HTTP/3 stream 0 reset by server (error 0x102 INTERNAL_ERROR) === TEST 29: refuses NGX_AGAIN diff --git a/t/033-ctx.t b/t/033-ctx.t index 77bd15f8c1..bcb34ad909 100644 --- a/t/033-ctx.t +++ b/t/033-ctx.t @@ -279,7 +279,7 @@ GET /t --- error_log ngx.ctx = 32 --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ diff --git a/t/041-header-filter.t b/t/041-header-filter.t index 23730815da..3ce70711e2 100644 --- a/t/041-header-filter.t +++ b/t/041-header-filter.t @@ -125,7 +125,7 @@ GET /read --- error_code --- response_body --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -469,7 +469,7 @@ failed to run header_filter_by_lua*: header_filter_by_lua(nginx.conf:47):2: Some --- no_error_log [alert] --- curl_error eval -qr/curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(28\) Remote peer returned unexpected data|curl: \(52\) Empty reply from server|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(56\) ngtcp2_conn_writev_stream returned error: ERR_CLOSING|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(28\) Remote peer returned unexpected data|curl: \(52\) Empty reply from server|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -494,7 +494,7 @@ failed to run header_filter_by_lua*: unknown reason --- no_error_log [alert] --- curl_error eval -qr/curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(28\) Remote peer returned unexpected data|curl: \(52\) Empty reply from server|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(56\) ngtcp2_conn_writev_stream returned error: ERR_CLOSING|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(28\) Remote peer returned unexpected data|curl: \(52\) Empty reply from server|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -510,7 +510,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -526,7 +526,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -542,7 +542,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -558,7 +558,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -574,7 +574,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -594,7 +594,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -614,7 +614,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -630,7 +630,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -646,7 +646,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -662,7 +662,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -696,7 +696,7 @@ GET /lua --- error_log eval qr/API disabled in the context of header_filter_by_lua\*|http3 requests are not supported without content-length header/ms --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -720,7 +720,7 @@ if (defined $ENV{TEST_NGINX_USE_HTTP3}) { $err_log; --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -736,7 +736,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -752,7 +752,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -801,7 +801,7 @@ in function 'error' in function 'bar' in function 'foo' --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -821,7 +821,7 @@ GET /lua?a=1&b=2 --- error_log eval qr/failed to load external Lua file ".*?test2\.lua": cannot open .*? No such file or directory/ --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -870,7 +870,7 @@ failed to load inlined Lua code: header_filter_by_lua(nginx.conf:41):2: unexpect --- no_error_log no_such_error --- curl_error eval -qr/curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly: INTERNAL_ERROR \(err 2\)/ +qr/curl: \(56\) ngtcp2_conn_writev_stream returned error: ERR_CLOSING|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)/ @@ -901,7 +901,7 @@ failed to load inlined Lua code: header_filter_by_lua(nginx.conf:49):2: unexpect --- no_error_log no_such_error --- curl_error eval -qr/curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly: INTERNAL_ERROR \(err 2\)/ +qr/curl: \(56\) ngtcp2_conn_writev_stream returned error: ERR_CLOSING|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)/ @@ -927,4 +927,4 @@ failed to load inlined Lua code: header_filter_by_lua(...90123456789012345678901 --- no_error_log [alert] --- curl_error eval -qr/curl: \(56\) Failure when receiving data from the peer|curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly: INTERNAL_ERROR \(err 2\)/ +qr/curl: \(56\) ngtcp2_conn_writev_stream returned error: ERR_CLOSING|curl: \(56\) Failure when receiving data from the peer|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)/ diff --git a/t/091-coroutine.t b/t/091-coroutine.t index 16930ed3c0..fb57d59a02 100644 --- a/t/091-coroutine.t +++ b/t/091-coroutine.t @@ -763,7 +763,7 @@ GET /lua --- error_log API disabled in the context of header_filter_by_lua* --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ @@ -1701,7 +1701,7 @@ GET /t "in function 'co'" ] --- curl_error eval -qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 was not closed cleanly|curl: \(95\) HTTP\/3 stream 0 reset by server/ +qr/curl: \(52\) Empty reply from server|curl: \(92\) HTTP\/2 stream 1 reset by server \(error 0x2 INTERNAL_ERROR\)|curl: \(95\) HTTP\/3 stream 0 reset by server/ diff --git a/t/166-ssl-client-hello.t b/t/166-ssl-client-hello.t index 4372d0d1f8..c2a76ae43c 100644 --- a/t/166-ssl-client-hello.t +++ b/t/166-ssl-client-hello.t @@ -3437,7 +3437,7 @@ qr/test completed/, GET /t --- ignore_response --- curl_error eval -qr/Connection time/ +qr/Failed to connect to .* port .* after .* ms: Could not connect to server/ --- grep_error_log eval: qr/(client hello: cosocket test start|client hello: received memc reply: VERSION|client hello: cosocket test done|cert by: test start)/ --- grep_error_log_out eval [