class HypertrackV3::Engine::WebhookParser
Public Class Methods
call(env)
click to toggle source
# File lib/hypertrack_v3.rb, line 222 def self.call(env) request = parse_request(env) case request.headers['x_amz_sns_message_type'] when 'SubscriptionConfirmation' self.register_with_hypertrack request when 'Notification' self.dispatch request else HypertrackV3.log_error( "invalid message-type header", { message_type: request.header['x_amz_sns_messate_type'], }.to_json ) self.serve(400, {error: "invalid message-type header"}) end end
client()
click to toggle source
# File lib/hypertrack_v3.rb, line 137 def self.client @@client ||= Faraday.new do |conn| conn.use Faraday::Response::Logger, HypertrackV3.logger, bodies: true conn.use :instrumentation conn.adapter Faraday.default_adapter end end
dispatch(request)
click to toggle source
# File lib/hypertrack_v3.rb, line 168 def self.dispatch(request) if (cached = Rails.cache.fetch('/hypertrack_v3/subscription_arn')) != request.headers['x_amz_sns_subscription_arn'] HypertrackV3.log_error( "invalid subscription-arn header", { subscription_arn: { request: request.header, cache: cached, } }.to_json ) return self.serve(400, {error: "invalid subscription-arn header"}) end if (cached = Rails.cache.fetch("/hypertrack_v3/#{request.headers['x_amz_sns_message_id']}")).present? HypertrackV3.log_error( "Message Id already seen", { sns_message_id: { request: request.headers['x_amz_sns_message_id'], cache: cached, } } ) return self.serve(400) end Rails.cache.write( "/hypertrack_v3/#{request.headers['x_amz_sns_message_id']}", true, expires_in: 1.hour ) begin data = JSON.parse(request.body, object_class: OpenStruct) rescue JSON::ParserError => err HypertrackV3.log_exception(err) end res = true data.each do |datum| if @@hooks.include? datum.type.to_sym res &= @@hooks[datum.type.to_sym].(datum.device_id, datum.data, datum.created_at, datum.recorded_at) else res = false end end self.serve(res ? 200 : 400) end
parse_request(env)
click to toggle source
# File lib/hypertrack_v3.rb, line 241 def self.parse_request(env) OpenStruct.new({ headers: env.select {|k,v| k.to_s.start_with? 'HTTP_'} .collect {|key, val| [key.to_s.sub(/^HTTP_/, '').downcase, val]}.to_h, params: env['rack.request.query_hash'], body: env['rack.input']&.read }) end
register_hook(name, callable)
click to toggle source
# File lib/hypertrack_v3.rb, line 216 def self.register_hook(name, callable) raise RegisterHookError("Invalid name argument: #{name}") unless @@hooks.keys.include? name.to_sym raise RegisterHookError("Invalid callable argument: #{callable}") unless callable.respond_to? :call @@hooks[name.to_sym] = callable end
register_with_hypertrack(request)
click to toggle source
# File lib/hypertrack_v3.rb, line 155 def self.register_with_hypertrack(request) register_data = JSON.parse(request.body) resp = self.client.get register_data["SubscribeURL"] data = Nokogiri::XML(resp.body) data.remove_namespaces! token = data.at_xpath('//SubscriptionArn')&.content return self.serve(400, {error: 'SubscriptionArn not found'}) if token.empty? Rails.cache.write('/hypertrack_v3/subscription_arn', token, expires_in: 100.years) self.serve(200) end
serve(code, params={})
click to toggle source
# File lib/hypertrack_v3.rb, line 250 def self.serve(code, params={}) [ code, {"Content-Type" => "application/json; charset=utf-8"}, [params.to_json] ] end