Class: Heroic::SNS::Message
- Inherits:
-
Object
- Object
- Heroic::SNS::Message
- Defined in:
- lib/heroic/sns/message.rb
Overview
Encapsulates an SNS message. Since Endpoint takes care of authenticating the message, most of the time you will simply be interested in retrieving the subject and body from the message and acting on it.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#body ⇒ Object
The message payload.
- #hash ⇒ Object
-
#id ⇒ Object
A Universally Unique Identifier, unique for each message published.
-
#initialize(json) ⇒ Message
constructor
A new instance of Message.
-
#signature ⇒ Object
The message signature data, Base-64 decoded.
- #signature_version ⇒ Object
- #signing_cert_url ⇒ Object
-
#subject ⇒ Object
The message may not have a subject.
- #subscribe_url ⇒ Object
-
#timestamp ⇒ Object
The timestamp when the message was published, as a Time object.
-
#to_json ⇒ Object
Returns a JSON serialization of the message.
- #to_s ⇒ Object
-
#token ⇒ Object
The token is used to confirm subscriptions via the SNS API.
- #topic_arn ⇒ Object
-
#type ⇒ Object
The message type will be one of
SubscriptionConfirmation,UnsubscribeConfirmation, andNotification. - #unsubscribe_url ⇒ Object
-
#verify! ⇒ Object
Verifies the message signature.
Constructor Details
#initialize(json) ⇒ Message
Returns a new instance of Message.
29 30 31 32 33 |
# File 'lib/heroic/sns/message.rb', line 29 def initialize(json) @msg = ::JSON.parse(json) rescue JSON::ParserError => e raise Error.new("failed to parse message as JSON: #{e.message}") end |
Instance Method Details
#==(other) ⇒ Object
96 97 98 |
# File 'lib/heroic/sns/message.rb', line 96 def ==(other) other.is_a?(Message) && @msg == other.instance_variable_get(:@msg) end |
#body ⇒ Object
The message payload. As far as Amazon and this class are concerned, the message payload is just a string of bytes. If you are expecting, for example, a JSON object, you will need to pass this to a JSON parser.
78 79 80 |
# File 'lib/heroic/sns/message.rb', line 78 def body @msg['Message'] end |
#hash ⇒ Object
100 101 102 |
# File 'lib/heroic/sns/message.rb', line 100 def hash @msg.hash end |
#id ⇒ Object
A Universally Unique Identifier, unique for each message published. For a notification that Amazon SNS resends during a retry, the message ID of the original message is used.
48 49 50 |
# File 'lib/heroic/sns/message.rb', line 48 def id @msg['MessageId'] end |
#signature ⇒ Object
The message signature data, Base-64 decoded.
66 67 68 |
# File 'lib/heroic/sns/message.rb', line 66 def signature Base64::decode64(@msg['Signature']) end |
#signature_version ⇒ Object
57 58 59 |
# File 'lib/heroic/sns/message.rb', line 57 def signature_version @msg['SignatureVersion'] end |
#signing_cert_url ⇒ Object
61 62 63 |
# File 'lib/heroic/sns/message.rb', line 61 def signing_cert_url @msg['SigningCertURL'] end |
#subject ⇒ Object
The message may not have a subject.
71 72 73 |
# File 'lib/heroic/sns/message.rb', line 71 def subject @msg['Subject'] end |
#subscribe_url ⇒ Object
82 83 84 |
# File 'lib/heroic/sns/message.rb', line 82 def subscribe_url @msg['SubscribeURL'] end |
#timestamp ⇒ Object
The timestamp when the message was published, as a Time object.
53 54 55 |
# File 'lib/heroic/sns/message.rb', line 53 def Time.xmlschema(@msg['Timestamp']) end |
#to_json ⇒ Object
Returns a JSON serialization of the message. Note that it may not be identical to the serialization that was retrieved from the network.
114 115 116 |
# File 'lib/heroic/sns/message.rb', line 114 def to_json @msg.to_json end |
#to_s ⇒ Object
104 105 106 107 108 109 110 |
# File 'lib/heroic/sns/message.rb', line 104 def to_s string = "<SNSMessage:\n" @msg.each do |k,v| string << sprintf(" %s: %s\n", k, v.inspect) end string << ">" end |
#token ⇒ Object
The token is used to confirm subscriptions via the SNS API. If you visit the subscribe_url, you can ignore this field.
92 93 94 |
# File 'lib/heroic/sns/message.rb', line 92 def token @msg['Token'] end |
#topic_arn ⇒ Object
41 42 43 |
# File 'lib/heroic/sns/message.rb', line 41 def topic_arn @msg['TopicArn'] end |
#type ⇒ Object
The message type will be one of SubscriptionConfirmation, UnsubscribeConfirmation, and Notification.
37 38 39 |
# File 'lib/heroic/sns/message.rb', line 37 def type @msg['Type'] end |
#unsubscribe_url ⇒ Object
86 87 88 |
# File 'lib/heroic/sns/message.rb', line 86 def unsubscribe_url @msg['UnsubscribeURL'] end |
#verify! ⇒ Object
Verifies the message signature. Raises Error if it is not valid.
See: docs.aws.amazon.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/heroic/sns/message.rb', line 121 def verify! age = Time.now - raise Error.new("timestamp is in the future", self) if age < 0 raise Error.new("timestamp is too old", self) if age > MAXIMUM_ALLOWED_AGE if signature_version != '1' raise Error.new("unknown signature version: #{signature_version}", self) end if signing_cert_url !~ %r[^https://.*amazonaws\.com/] raise Error.new("signing certificate is not from amazonaws.com", self) end text = string_to_sign # will warn of invalid Type cert = CERTIFICATE_CACHE.get(signing_cert_url) digest = OpenSSL::Digest::SHA1.new unless cert.public_key.verify(digest, signature, text) raise Error.new("message signature is invalid", self) end end |