Amazon-SNS

 view release on metacpan or  search on metacpan

lib/Amazon/SNS.pm  view on Meta::CPAN

		Amazon::SNS::Topic->new({
			'sns' => $self,
			'arn' => $_->{'TopicArn'},
		})

	} @{$r->{'ListTopicsResult'}{'Topics'}[0]{'member'}};
}

sub Subscribe
{
	my ($self, $protocol, $topicarn, $endpoint) = @_;

	$self->dispatch({
		'Action'	=> 'Subscribe',
		'Protocol'	=> $protocol,
		'TopicArn'	=> $topicarn,
		'Endpoint'	=> $endpoint,
	});
}

sub Unsubscribe
{
	my ($self, $arn) = @_;

	$self->dispatch({
		'Action'		=> 'Unsubscribe',
		'SubscriptionArn'	=> $arn,
	});
}

sub dispatch
{
	my ($self, $args) = @_;

	$self->error(undef);

	$self->service('http://sns.eu-west-1.amazonaws.com')
		unless defined $self->service;

	# sanitize args
	do { delete $args->{$_} unless defined $args->{$_} } for (keys %$args);

	# add signature elements
	$args->{'Timestamp'} = $self->timestamp;
	$args->{'AWSAccessKeyId'} = $self->key;
	$args->{'SignatureVersion'} = 2;
	$args->{'SignatureMethod'} = 'HmacSHA256';
	$args->{'Version'} = '2010-03-31';

	if (defined($args->{'Attributes'}) and ref($args->{'Attributes'}) eq 'HASH') {
		foreach my $attr (keys %{$args->{'Attributes'}}) {
			$args->{$attr} = $args->{'Attributes'}->{$attr};
		}
		delete $args->{'Attributes'};
	}

	# build URI
	my $uri = URI->new($self->service);

	$uri->path('/');
	$uri->query(join('&', map { $_ . '=' . URI::Escape::uri_escape_utf8($args->{$_}, '^A-Za-z0-9\-_.~') } sort keys %$args ));

	# create signature
	$args->{'Signature'} = hmac_sha256_base64(join("\n", 'POST', $uri->host, $uri->path, $uri->query), $self->secret);

	# padding
	while (length($args->{'Signature'}) % 4) {
		$args->{'Signature'} .= '=';
	}

	# rewrite query string
	$uri->query(join('&', map { $_ . '=' . URI::Escape::uri_escape_utf8($args->{$_}, '^A-Za-z0-9\-_.~') } sort keys %$args ));

	my $response = LWP::UserAgent->new->post($self->service, 'Content' => $uri->query);

	$self->status_code($response->code);

	if ($response->is_success) {
		return XMLin($response->content,
				'SuppressEmpty' => 1,
#				'KeyAttr' => { },
				'ForceArray' => [ qw/ Topics member / ],
		);
	} else {
		print $response->content, "\n";
		$self->error(
			($response->content =~ /^<.+>/)
				? eval { XMLin($response->content)->{'Error'}{'Message'} || $response->status_line }
				: $response->status_line
		);
	}

	print STDERR 'ERROR: ', $self->error, "\n"
		if $self->debug;

	return undef;
}

sub timestamp {

	return sprintf("%04d-%02d-%02dT%02d:%02d:%02d.000Z", sub {
		($_[5]+1900, $_[4]+1, $_[3], $_[2], $_[1], $_[0])
	}->(gmtime(time)));
}


1;

package Amazon::SNS::Topic;

use strict;
use warnings;

use base qw(Class::Accessor);

use JSON;

__PACKAGE__->mk_accessors(qw/ sns arn /);

sub Publish
{
	my ($self, $msg, $subj) = @_;

	# XXX croak on invalid arn

	my $structure = undef;

	# support JSON payload
	if (ref($msg) eq 'HASH') {

		$structure = 'json';
		$msg = encode_json($msg);



( run in 1.927 second using v1.01-cache-2.11-cpan-5837b0d9d2c )