catstodon/app/workers/pubsubhubbub/confirmation_worker.rb
Akihiko Odaki 40e5d2303b Validate HTTP response length while receiving (#6891)
to_s method of HTTP::Response keeps blocking while it receives the whole
content, no matter how it is big. This means it may waste time to receive
unacceptably large files. It may also consume memory and disk in the
process. This solves the inefficency by checking response length while
receiving.
2018-03-26 14:02:10 +02:00

82 lines
1.9 KiB
Ruby

# frozen_string_literal: true
class Pubsubhubbub::ConfirmationWorker
include Sidekiq::Worker
include RoutingHelper
sidekiq_options queue: 'push', retry: false
attr_reader :subscription, :mode, :secret, :lease_seconds
def perform(subscription_id, mode, secret = nil, lease_seconds = nil)
@subscription = Subscription.find(subscription_id)
@mode = mode
@secret = secret
@lease_seconds = lease_seconds
process_confirmation
end
private
def process_confirmation
prepare_subscription
callback_get_with_params
logger.debug "Confirming PuSH subscription for #{subscription.callback_url} with challenge #{challenge}: #{@callback_response_body}"
update_subscription
end
def update_subscription
if successful_subscribe?
subscription.save!
elsif successful_unsubscribe?
subscription.destroy!
end
end
def successful_subscribe?
subscribing? && response_matches_challenge?
end
def successful_unsubscribe?
(unsubscribing? && response_matches_challenge?) || !subscription.confirmed?
end
def response_matches_challenge?
@callback_response_body == challenge
end
def subscribing?
mode == 'subscribe'
end
def unsubscribing?
mode == 'unsubscribe'
end
def callback_get_with_params
Request.new(:get, subscription.callback_url, params: callback_params).perform do |response|
@callback_response_body = response.body_with_limit
end
end
def callback_params
{
'hub.topic': account_url(subscription.account, format: :atom),
'hub.mode': mode,
'hub.challenge': challenge,
'hub.lease_seconds': subscription.lease_seconds,
}
end
def prepare_subscription
subscription.secret = secret
subscription.lease_seconds = lease_seconds
subscription.confirmed = true
end
def challenge
@_challenge ||= SecureRandom.hex
end
end