From 16f3a05e4565b70bcc57010b99034da9da231e56 Mon Sep 17 00:00:00 2001 From: Sam Ford <1584702+samford@users.noreply.github.com> Date: Mon, 8 May 2023 17:40:51 -0400 Subject: [PATCH 1/3] Strategy#page_headers: Update for #curl_headers `#curl_headers` was recently introduced into `Strategy#page_headers` but only the call was modified and the method wasn't updated to correctly work with the new return value, so all `HeaderMatch` checks immediately started failing with an error. This commit includes changes that return `#page_headers` to a working state. I've removed the `result.assert_success!` call because it prevents a few checks from being retried with `GET` (`firefox-cn`, `krisp`, `prepros`). --- Library/Homebrew/livecheck/strategy.rb | 5 ++--- Library/Homebrew/utils/curl.rb | 16 ++++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Library/Homebrew/livecheck/strategy.rb b/Library/Homebrew/livecheck/strategy.rb index 72df2f4934..d269cefdd9 100644 --- a/Library/Homebrew/livecheck/strategy.rb +++ b/Library/Homebrew/livecheck/strategy.rb @@ -182,16 +182,15 @@ module Homebrew headers = [] [:default, :browser].each do |user_agent| - output, _, status = curl_headers( + parsed_output = curl_headers( url, wanted_headers: ["location", "content-disposition"], use_homebrew_curl: homebrew_curl, user_agent: user_agent, **DEFAULT_CURL_OPTIONS, ) - next unless status.success? + next if parsed_output.blank? - parsed_output = parse_curl_output(output, max_iterations: MAX_PARSE_ITERATIONS) parsed_output[:responses].each { |response| headers << response[:headers] } break if headers.present? end diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 4b2d3b227f..963f4e650c 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -213,18 +213,18 @@ 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 - parsed_output = parse_curl_output(result.stdout) + next if !result.success? && result.exit_status != 22 - # If we didn't get any wanted header yet, retry using `GET`. - next if request_args.empty? && wanted_headers.any? && - parsed_output.fetch(:responses).none? { |r| (r.fetch(:headers).keys & wanted_headers).any? } + parsed_output = parse_curl_output(result.stdout) - return parsed_output if result.success? - end + # If we didn't get any wanted header yet, retry using `GET`. + next if request_args.empty? && wanted_headers.any? && + parsed_output.fetch(:responses).none? { |r| (r.fetch(:headers).keys & wanted_headers).any? } - result.assert_success! + return parsed_output if result.success? end + + nil end # Check if a URL is protected by CloudFlare (e.g. badlion.net and jaxx.io). From e493d0cb04acea102ab84126ec5be6e5b924aef8 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 9 May 2023 07:25:00 +0200 Subject: [PATCH 2/3] Rescue `ErrorDuringExecution` instead of changing `curl_headers` return type. --- Library/Homebrew/livecheck/strategy.rb | 19 +++++++++++-------- Library/Homebrew/utils/curl.rb | 16 ++++++++-------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Library/Homebrew/livecheck/strategy.rb b/Library/Homebrew/livecheck/strategy.rb index d269cefdd9..abe14e200f 100644 --- a/Library/Homebrew/livecheck/strategy.rb +++ b/Library/Homebrew/livecheck/strategy.rb @@ -182,14 +182,17 @@ module Homebrew headers = [] [:default, :browser].each do |user_agent| - parsed_output = curl_headers( - url, - wanted_headers: ["location", "content-disposition"], - use_homebrew_curl: homebrew_curl, - user_agent: user_agent, - **DEFAULT_CURL_OPTIONS, - ) - next if parsed_output.blank? + begin + parsed_output = curl_headers( + url, + wanted_headers: ["location", "content-disposition"], + use_homebrew_curl: homebrew_curl, + user_agent: user_agent, + **DEFAULT_CURL_OPTIONS, + ) + rescue ErrorDuringExecution + next + end parsed_output[:responses].each { |response| headers << response[:headers] } break if headers.present? diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 963f4e650c..4b2d3b227f 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -213,18 +213,18 @@ module Utils ) # 22 means a non-successful HTTP status code, not a `curl` error, so we still got some headers. - next if !result.success? && result.exit_status != 22 + if result.success? || result.exit_status == 22 + parsed_output = parse_curl_output(result.stdout) - parsed_output = parse_curl_output(result.stdout) + # If we didn't get any wanted header yet, retry using `GET`. + next if request_args.empty? && wanted_headers.any? && + parsed_output.fetch(:responses).none? { |r| (r.fetch(:headers).keys & wanted_headers).any? } - # If we didn't get any wanted header yet, retry using `GET`. - next if request_args.empty? && wanted_headers.any? && - parsed_output.fetch(:responses).none? { |r| (r.fetch(:headers).keys & wanted_headers).any? } + return parsed_output if result.success? + end - return parsed_output if result.success? + result.assert_success! end - - nil end # Check if a URL is protected by CloudFlare (e.g. badlion.net and jaxx.io). From 4b787fdee2ae3039906a377c3dc99a63bace0bf8 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 9 May 2023 07:40:15 +0200 Subject: [PATCH 3/3] Retry `curl_headers` on 400 codes. --- Library/Homebrew/utils/curl.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 4b2d3b227f..f7a34104e7 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -216,9 +216,14 @@ module Utils if result.success? || result.exit_status == 22 parsed_output = parse_curl_output(result.stdout) - # If we didn't get any wanted header yet, retry using `GET`. - next if request_args.empty? && wanted_headers.any? && - parsed_output.fetch(:responses).none? { |r| (r.fetch(:headers).keys & wanted_headers).any? } + if request_args.empty? + # If we didn't get any wanted header yet, retry using `GET`. + next if wanted_headers.any? && + parsed_output.fetch(:responses).none? { |r| (r.fetch(:headers).keys & wanted_headers).any? } + + # Some CDNs respond with 400 codes for `HEAD` but resolve with `GET`. + next if (400..499).cover?(parsed_output.fetch(:responses).last&.fetch(:status_code).to_i) + end return parsed_output if result.success? end