Class: Heroic::SNS::Endpoint

Inherits:
Object
  • Object
show all
Defined in:
lib/heroic/sns/endpoint.rb

Overview

Heroic::SNS::Endpoint is Rack middleware which intercepts messages from

Amazon's Simple Notification Service (SNS). It makes the parsed and
verified message available to your application in the Rack environment
under the 'sns.message' key. If an error occurred during message handling,
the error is available in the Rack environment in the 'sns.error' key.

Endpoint is to be initialized with a hash of options. It understands three
different options:

+:topic+ (or +:topics+) specifies a filter that defines what SNS topics
are handled by this endpoint ("on-topic"). You can supply any of the
following:
- a topic ARN as a String
- a list of topic ARNs as an Array of Strings
- a regular expression matching on-topic ARNs
- a Proc which takes a topic ARN as a String and returns true or false.
You *must* specify a topic filter. Use <code>Proc.new{true}</code> if
you insist on indiscriminately accepting all notifications.

+:auto_confirm+ determines how SubscriptionConfirmation messages are handled.
- If true, the subscription is confirmed and your app is not notified.
  This is the default.
- If false, the subscription is ignored and your app is not notified.
- If nil, the message is passed along to your app.

+:auto_resubscribe+ affects how on-topic UnsubscribeConfirmation messages are handled.
- If false, they are ignored and your app is also not notified.
  This is the default.
- If true, they topic is automatically re-subscribed by retrieving the URL in
  the `SubscribeURL` field of the SNS message, and your app is not notified.
- If nil, there is no special handling and the message is passed along to your
  app.

You can install this in your config.ru:
  use Heroic::SNS::Endpoint, :topics => /whatever/

For Rails, you can also install it in /config/initializers/sns_endpoint.rb:
  Rails.application.config.middleware.use Heroic::SNS::Endpoint, :topic => ...

Constant Summary collapse

DEFAULT_OPTIONS =
{ :auto_confirm => true, :auto_resubscribe => false }

Instance Method Summary collapse

Constructor Details

#initialize(app, opt = {}) ⇒ Endpoint

Returns a new instance of Endpoint.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/heroic/sns/endpoint.rb', line 56

def initialize(app, opt = {})
  @app = app
  options = DEFAULT_OPTIONS.merge(opt)
  @auto_confirm = options[:auto_confirm]
  @auto_resubscribe = options[:auto_resubscribe]
  if 1 < [:topic, :topics].count { |k| options.has_key?(k) }
    raise ArgumentError.new("supply zero or one of :topic, :topics")
  end
  @topic_filter = begin
    case a = options[:topic] || options[:topics]
    when String then Proc.new { |t| a == t }
    when Regexp then Proc.new { |t| a.match(t) }
    when Proc then a
    when Array
      unless a.all? { |e| e.is_a? String }
        raise ArgumentError.new("topic array must be strings")
      end
      Proc.new { |t| a.include?(t) }
    when nil
      raise ArgumentError.new("must specify a topic filter!")
    else
      raise ArgumentError.new("can't use topic filter of type #{a.class}")
    end
  end
end

Instance Method Details

#call(env) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/heroic/sns/endpoint.rb', line 82

def call(env)
  if topic_arn = env['HTTP_X_AMZ_SNS_TOPIC_ARN']
    if @topic_filter.call(topic_arn)
      call_on_topic(env)
    else
      call_off_topic(env)
    end
  else
    @app.call(env)
  end
end