1
0
Fork 0
mirror of https://github.com/mastodon/mastodon.git synced 2024-08-20 21:08:15 -07:00

Wrap common http-level errors into constant

This commit is contained in:
Matt Jankowski 2024-05-21 11:12:18 -04:00
parent 2ed13071ef
commit 70deaee948
23 changed files with 41 additions and 28 deletions

View file

@ -32,7 +32,7 @@ class ApplicationController < ActionController::Base
rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity
rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests
rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, with: :internal_server_error)
rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight, ActiveRecord::SerializationFailure, with: :service_unavailable rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight, ActiveRecord::SerializationFailure, with: :service_unavailable
rescue_from Seahorse::Client::NetworkingError do |e| rescue_from Seahorse::Client::NetworkingError do |e|

View file

@ -20,14 +20,14 @@ module Api::ErrorHandling
render json: { error: 'Record not found' }, status: 404 render json: { error: 'Record not found' }, status: 404
end end
rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do
render json: { error: 'Remote data could not be fetched' }, status: 503
end
rescue_from OpenSSL::SSL::SSLError do rescue_from OpenSSL::SSL::SSLError do
render json: { error: 'Remote SSL certificate could not be verified' }, status: 503 render json: { error: 'Remote SSL certificate could not be verified' }, status: 503
end end
rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS) do
render json: { error: 'Remote data could not be fetched' }, status: 503
end
rescue_from Mastodon::NotPermittedError do rescue_from Mastodon::NotPermittedError do
render json: { error: 'This action is not allowed' }, status: 403 render json: { error: 'This action is not allowed' }, status: 403
end end

View file

@ -80,12 +80,12 @@ module SignatureVerification
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature'] fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature']
rescue SignatureVerificationError => e rescue SignatureVerificationError => e
fail_with! e.message fail_with! e.message
rescue HTTP::Error, OpenSSL::SSL::SSLError => e
fail_with! "Failed to fetch remote data: #{e.message}"
rescue Mastodon::UnexpectedResponseError rescue Mastodon::UnexpectedResponseError
fail_with! 'Failed to fetch remote data (got unexpected reply from server)' fail_with! 'Failed to fetch remote data (got unexpected reply from server)'
rescue Stoplight::Error::RedLight rescue Stoplight::Error::RedLight
fail_with! 'Fetching attempt skipped because of recent connection failure' fail_with! 'Fetching attempt skipped because of recent connection failure'
rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
fail_with! "Failed to fetch remote data: #{e.message}"
end end
def request_body def request_body

View file

@ -13,7 +13,7 @@ class MediaProxyController < ApplicationController
rescue_from ActiveRecord::RecordInvalid, with: :not_found rescue_from ActiveRecord::RecordInvalid, with: :not_found
rescue_from Mastodon::UnexpectedResponseError, with: :not_found rescue_from Mastodon::UnexpectedResponseError, with: :not_found
rescue_from Mastodon::NotPermittedError, with: :not_found rescue_from Mastodon::NotPermittedError, with: :not_found
rescue_from HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, with: :internal_server_error rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, with: :internal_server_error)
def show def show
with_redis_lock("media_download:#{params[:id]}") do with_redis_lock("media_download:#{params[:id]}") do

View file

@ -279,7 +279,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
media_attachment.download_file! media_attachment.download_file!
media_attachment.download_thumbnail! media_attachment.download_thumbnail!
media_attachment.save media_attachment.save
rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError rescue *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id) RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id)
rescue Seahorse::Client::NetworkingError => e rescue Seahorse::Client::NetworkingError => e
Rails.logger.warn "Error storing media attachment: #{e}" Rails.logger.warn "Error storing media attachment: #{e}"

View file

@ -35,7 +35,7 @@ class AccountAlias < ApplicationRecord
def set_uri def set_uri
target_account = ResolveAccountService.new.call(acct) target_account = ResolveAccountService.new.call(acct)
self.uri = ActivityPub::TagManager.instance.uri_for(target_account) unless target_account.nil? self.uri = ActivityPub::TagManager.instance.uri_for(target_account) unless target_account.nil?
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS
# Validation will take care of it # Validation will take care of it
end end

View file

@ -57,7 +57,7 @@ class AccountMigration < ApplicationRecord
def set_target_account def set_target_account
self.target_account = ResolveAccountService.new.call(acct, skip_cache: true) self.target_account = ResolveAccountService.new.call(acct, skip_cache: true)
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error, Addressable::URI::InvalidURIError rescue Webfinger::Error, Mastodon::Error, *Mastodon::HTTP_CONNECTION_ERRORS
# Validation will take care of it # Validation will take care of it
end end

View file

@ -26,7 +26,7 @@ module Remotable
public_send(:"#{attachment_name}=", ResponseWithLimit.new(response, limit)) public_send(:"#{attachment_name}=", ResponseWithLimit.new(response, limit))
end end
rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" } Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" }
public_send(:"#{attachment_name}=", nil) if public_send(:"#{attachment_name}_file_name").present? public_send(:"#{attachment_name}=", nil) if public_send(:"#{attachment_name}_file_name").present?
raise e unless suppress_errors raise e unless suppress_errors

View file

@ -32,7 +32,7 @@ class Form::Redirect
def set_target_account def set_target_account
@target_account = ResolveAccountService.new.call(acct, skip_cache: true) @target_account = ResolveAccountService.new.call(acct, skip_cache: true)
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error, Addressable::URI::InvalidURIError rescue Webfinger::Error, Mastodon::Error, *Mastodon::HTTP_CONNECTION_ERRORS
# Validation will take care of it # Validation will take care of it
end end

View file

@ -67,7 +67,7 @@ class RemoteFollow
def acct_resource def acct_resource
@acct_resource ||= webfinger!("acct:#{acct}") @acct_resource ||= webfinger!("acct:#{acct}")
rescue Webfinger::Error, HTTP::ConnectionError rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS
nil nil
end end

View file

@ -127,13 +127,13 @@ class ActivityPub::ProcessAccountService < BaseService
begin begin
@account.avatar_remote_url = image_url('icon') || '' unless skip_download? @account.avatar_remote_url = image_url('icon') || '' unless skip_download?
@account.avatar = nil if @account.avatar_remote_url.blank? @account.avatar = nil if @account.avatar_remote_url.blank?
rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError rescue *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadAvatarWorker.perform_in(rand(30..600).seconds, @account.id) RedownloadAvatarWorker.perform_in(rand(30..600).seconds, @account.id)
end end
begin begin
@account.header_remote_url = image_url('image') || '' unless skip_download? @account.header_remote_url = image_url('image') || '' unless skip_download?
@account.header = nil if @account.header_remote_url.blank? @account.header = nil if @account.header_remote_url.blank?
rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError rescue *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadHeaderWorker.perform_in(rand(30..600).seconds, @account.id) RedownloadHeaderWorker.perform_in(rand(30..600).seconds, @account.id)
end end
@account.statuses_count = outbox_total_items if outbox_total_items.present? @account.statuses_count = outbox_total_items if outbox_total_items.present?
@ -276,7 +276,7 @@ class ActivityPub::ProcessAccountService < BaseService
total_items = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil total_items = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil
has_first_page = collection.is_a?(Hash) && collection['first'].present? has_first_page = collection.is_a?(Hash) && collection['first'].present?
@collections[type] = [total_items, has_first_page] @collections[type] = [total_items, has_first_page]
rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::LengthValidationError rescue *Mastodon::HTTP_CONNECTION_ERRORS
@collections[type] = [nil, nil] @collections[type] = [nil, nil]
end end

View file

@ -109,7 +109,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
media_attachment.download_file! if media_attachment.remote_url_previously_changed? media_attachment.download_file! if media_attachment.remote_url_previously_changed?
media_attachment.download_thumbnail! if media_attachment.thumbnail_remote_url_previously_changed? media_attachment.download_thumbnail! if media_attachment.thumbnail_remote_url_previously_changed?
media_attachment.save media_attachment.save
rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError rescue *Mastodon::HTTP_CONNECTION_ERRORS
RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id) RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id)
rescue Seahorse::Client::NetworkingError => e rescue Seahorse::Client::NetworkingError => e
Rails.logger.warn "Error storing media attachment: #{e}" Rails.logger.warn "Error storing media attachment: #{e}"

View file

@ -29,7 +29,7 @@ class FetchLinkCardService < BaseService
end end
attach_card if @card&.persisted? attach_card if @card&.persisted?
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError, ActiveRecord::RecordInvalid => e rescue *Mastodon::HTTP_CONNECTION_ERRORS, EncodingError, ActiveRecord::RecordInvalid => e
Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" } Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" }
nil nil
end end

View file

@ -12,7 +12,7 @@ class FetchResourceService < BaseService
return if url.blank? return if url.blank?
process(url) process(url)
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
Rails.logger.debug { "Error fetching resource #{@url}: #{e}" } Rails.logger.debug { "Error fetching resource #{@url}: #{e}" }
nil nil
end end

View file

@ -115,7 +115,7 @@ class ImportService < BaseService
next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri) next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri)
status || ActivityPub::FetchRemoteStatusService.new.call(uri) status || ActivityPub::FetchRemoteStatusService.new.call(uri)
rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError rescue *Mastodon::HTTP_CONNECTION_ERRORS
nil nil
rescue => e rescue => e
Rails.logger.warn "Unexpected error when importing bookmark: #{e}" Rails.logger.warn "Unexpected error when importing bookmark: #{e}"

View file

@ -57,7 +57,7 @@ class Keys::ClaimService < BaseService
return unless json.present? && json['publicKeyBase64'].present? return unless json.present? && json['publicKeyBase64'].present?
@result = Result.new(@target_account, @device_id, key_id: json['id'], key: json['publicKeyBase64'], signature: json.dig('signature', 'signatureValue')) @result = Result.new(@target_account, @device_id, key_id: json['id'], key: json['publicKeyBase64'], signature: json.dig('signature', 'signatureValue'))
rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e rescue *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::Error => e
Rails.logger.debug { "Claiming one-time key for #{@target_account.acct}:#{@device_id} failed: #{e}" } Rails.logger.debug { "Claiming one-time key for #{@target_account.acct}:#{@device_id} failed: #{e}" }
nil nil
end end

View file

@ -72,7 +72,7 @@ class Keys::QueryService < BaseService
@devices = as_array(json['items']).map do |device| @devices = as_array(json['items']).map do |device|
Device.new(device_id: device['id'], name: device['name'], identity_key: device.dig('identityKey', 'publicKeyBase64'), fingerprint_key: device.dig('fingerprintKey', 'publicKeyBase64'), claim_url: device['claim']) Device.new(device_id: device['id'], name: device['name'], identity_key: device.dig('identityKey', 'publicKeyBase64'), fingerprint_key: device.dig('fingerprintKey', 'publicKeyBase64'), claim_url: device['claim'])
end end
rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e rescue *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::Error => e
Rails.logger.debug { "Querying devices for #{@account.acct} failed: #{e}" } Rails.logger.debug { "Querying devices for #{@account.acct} failed: #{e}" }
nil nil
end end

View file

@ -44,7 +44,7 @@ class ProcessMentionsService < BaseService
if mention_undeliverable?(mentioned_account) if mention_undeliverable?(mentioned_account)
begin begin
mentioned_account = ResolveAccountService.new.call(Regexp.last_match(1)) mentioned_account = ResolveAccountService.new.call(Regexp.last_match(1))
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS
mentioned_account = nil mentioned_account = nil
end end
end end

View file

@ -22,7 +22,7 @@ class SoftwareUpdateCheckService < BaseService
Request.new(:get, "#{api_url}?version=#{version}").add_headers('Accept' => 'application/json', 'User-Agent' => 'Mastodon update checker').perform do |res| Request.new(:get, "#{api_url}?version=#{version}").add_headers('Accept' => 'application/json', 'User-Agent' => 'Mastodon update checker').perform do |res|
return Oj.load(res.body_with_limit, mode: :strict) if res.code == 200 return Oj.load(res.body_with_limit, mode: :strict) if res.code == 200
end end
rescue HTTP::Error, OpenSSL::SSL::SSLError, Oj::ParseError rescue *Mastodon::HTTP_CONNECTION_ERRORS, Oj::ParseError
nil nil
end end

View file

@ -10,7 +10,7 @@ class VerifyLinkService < BaseService
return unless link_back_present? return unless link_back_present?
field.mark_verified! field.mark_verified!
rescue OpenSSL::SSL::SSLError, HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, IPAddr::AddressFamilyError => e rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
Rails.logger.debug { "Error fetching link #{@url}: #{e}" } Rails.logger.debug { "Error fetching link #{@url}: #{e}" }
nil nil
end end

View file

@ -21,7 +21,7 @@ class RefollowWorker
# Schedule re-follow # Schedule re-follow
begin begin
FollowService.new.call(follower, target_account, reblogs: reblogs, notify: notify, languages: languages, bypass_limit: true) FollowService.new.call(follower, target_account, reblogs: reblogs, notify: notify, languages: languages, bypass_limit: true)
rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, Mastodon::UnexpectedResponseError, HTTP::Error, OpenSSL::SSL::SSLError rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, *Mastodon::HTTP_CONNECTION_ERRORS
next next
end end
end end

View file

@ -35,4 +35,17 @@ module Mastodon
super() super()
end end
end end
HTTP_CONNECTION_ERRORS = [
Addressable::URI::InvalidURIError,
HTTP::ConnectionError,
HTTP::Error,
HTTP::TimeoutError,
IPAddr::AddressFamilyError,
Mastodon::HostValidationError,
Mastodon::LengthValidationError,
Mastodon::PrivateNetworkAddressError,
Mastodon::UnexpectedResponseError,
OpenSSL::SSL::SSLError,
].freeze
end end

View file

@ -305,7 +305,7 @@ module Mastodon::CLI
begin begin
code = Request.new(:head, account.uri).perform(&:code) code = Request.new(:head, account.uri).perform(&:code)
rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, Mastodon::PrivateNetworkAddressError rescue *Mastodon::HTTP_CONNECTION_ERRORS
skip_domains << account.domain skip_domains << account.domain
end end