From d3eac3848e9028fdb7292796305b8ed103db7f91 Mon Sep 17 00:00:00 2001 From: Sam Ford <1584702+samford@users.noreply.github.com> Date: Sun, 2 Jun 2024 22:52:58 -0400 Subject: [PATCH 1/2] Curl#curl_headers: Work with 8 exit_status I recently noticed that ~23 `livecheck` blocks using the `HeaderMatch` strategy were failing. Looking into it, these fail when using a `HEAD` request and retry with `GET` but the resulting response with the headers we want is simply discarded because the `exit_status` from curl is 8 ("weird server reply"). This resolves the issue by adding a special case for this exit status, so `#curl_headers` will return the headers in this scenario. --- Library/Homebrew/utils/curl.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 4b3389f6a8..592b9eb9da 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -223,7 +223,7 @@ module Utils ) # 22 means a non-successful HTTP status code, not a `curl` error, so we still got some headers. - if result.success? || result.exit_status == 22 + if result.success? || result.exit_status == 8 || result.exit_status == 22 parsed_output = parse_curl_output(result.stdout) if request_args.empty? @@ -235,7 +235,7 @@ module Utils next if (400..499).cover?(parsed_output.fetch(:responses).last&.fetch(:status_code).to_i) end - return parsed_output if result.success? + return parsed_output if result.success? || result.exit_status == 8 end result.assert_success! From 8236a70771bd7a7d12ae0fe5cb39e954745164cc Mon Sep 17 00:00:00 2001 From: Sam Ford <1584702+samford@users.noreply.github.com> Date: Mon, 3 Jun 2024 21:49:44 -0400 Subject: [PATCH 2/2] Curl: Add constants for used curl errors Co-authored-by: Mike McQuaid --- Library/Homebrew/utils/curl.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 592b9eb9da..7c3a0f8b2e 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -12,6 +12,13 @@ module Utils include SystemCommand::Mixin extend SystemCommand::Mixin + # Error returned when the server sent data curl could not parse. + CURL_WEIRD_SERVER_REPLY_EXIT_CODE = 8 + + # Error returned when `--fail` is used and the HTTP server returns an error + # code that is >= 400. + CURL_HTTP_RETURNED_ERROR_EXIT_CODE = 22 + # This regex is used to extract the part of an ETag within quotation marks, # ignoring any leading weak validator indicator (`W/`). This simplifies # ETag comparison in `#curl_check_http_content`. @@ -26,7 +33,10 @@ module Utils # the status code and any following descriptive text (e.g. `Not Found`). HTTP_STATUS_LINE_REGEX = %r{^HTTP/.* (?\d+)(?: (?[^\r\n]+))?} - private_constant :ETAG_VALUE_REGEX, :HTTP_RESPONSE_BODY_SEPARATOR, :HTTP_STATUS_LINE_REGEX + private_constant :CURL_WEIRD_SERVER_REPLY_EXIT_CODE, + :CURL_HTTP_RETURNED_ERROR_EXIT_CODE, + :ETAG_VALUE_REGEX, :HTTP_RESPONSE_BODY_SEPARATOR, + :HTTP_STATUS_LINE_REGEX module_function @@ -222,8 +232,10 @@ module Utils **options ) - # 22 means a non-successful HTTP status code, not a `curl` error, so we still got some headers. - if result.success? || result.exit_status == 8 || result.exit_status == 22 + # We still receive usable headers with certain non-successful exit + # statuses, so we special case them below. + if result.success? || + [CURL_WEIRD_SERVER_REPLY_EXIT_CODE, CURL_HTTP_RETURNED_ERROR_EXIT_CODE].include?(result.exit_status) parsed_output = parse_curl_output(result.stdout) if request_args.empty? @@ -235,7 +247,8 @@ module Utils next if (400..499).cover?(parsed_output.fetch(:responses).last&.fetch(:status_code).to_i) end - return parsed_output if result.success? || result.exit_status == 8 + return parsed_output if result.success? || + result.exit_status == CURL_WEIRD_SERVER_REPLY_EXIT_CODE end result.assert_success!