CloudApp-REST

 view release on metacpan or  search on metacpan

lib/CloudApp/REST.pm  view on Meta::CPAN

package CloudApp::REST;

use Moose;
use MooseX::Types::URI qw(Uri);

use LWP::UserAgent;
use HTTP::Request;
use JSON::XS;
use Module::Load;
use Data::Dumper;

=head1 NAME

CloudApp::REST - Perl Interface to the CloudApp REST API

=head1 VERSION

Version 0.02

=cut

our $VERSION = '0.02';

has useragent => (
    is       => 'ro',
    required => 0,
    isa      => 'LWP::UserAgent',
    lazy     => 1,
    default  => sub {
        my $self = shift;
        my $ua   = LWP::UserAgent->new;
        $ua->agent($self->agent_name);
        $ua->proxy('http', $self->proxy) if $self->proxy;
        return $ua;
    },
    clearer => '_reset_useragent',
                 );

has debug => (is => 'rw', required => 0, isa => 'Bool', default => 0);

has agent_name => (is => 'rw', required => 0, isa => 'Str', default => __PACKAGE__ . "/" . $VERSION);
has private_base_url => (is => 'rw', required => 0, isa => Uri, coerce => 1, default => sub { to_Uri('http://my.cl.ly/') });
has public_base_url  => (is => 'rw', required => 0, isa => Uri, coerce => 1, default => sub { to_Uri('http://cl.ly/') });
has fileupload_url   => (is => 'rw', required => 0, isa => Uri, coerce => 1, default => sub { to_Uri('http://f.cl.ly') });

has auth_netloc => (is => 'rw', required => 0, isa => 'Str', default => 'my.cl.ly:80');
has auth_realm  => (is => 'rw', required => 0, isa => 'Str', default => 'Application');

has email => (is => 'rw', required => 0, isa => 'Str');
has username => (is => 'rw', required => 0, isa => 'Str', trigger => sub { shift->email(shift) });
has password => (is => 'rw', required => 0, isa => 'Str');

has proxy => (is => 'rw', required => 0, isa => Uri, coerce => 1);

=head1 SYNOPSIS

This is a Perl Interface to the CloudApp REST API.  You can find more information about
CloudApp at L<http://www.getcloudapp.com/>.

Here's an example on how to retrieve the last 5 items:

  use CloudApp::REST;
  
  my $cl = CloudApp::REST->new;
  
  $cl->email('email@example.com');
  $cl->password('my_supersafe_secret');

lib/CloudApp/REST.pm  view on Meta::CPAN


=over 4

=item I<uri =E<gt> $uri>

The URI that is requested, eg. C<http://my.cl.ly/items?page=1&per_page=5>.

=item I<method =E<gt> $method>

The HTTP method of the request type.  If the parameter C<params> to L</_get_response>
is set, C<method> is ignored and set to C<POST>, otherwise to the value of C<method>.  Defaults
to C<GET> in all other cases.

=item I<params =E<gt> \%params>

If C<params> is set, the keys and values are used as C<POST> parameters with their values,
the HTTP method is set to C<POST>.

If C<params> has a key C<file>, this method tries to upload that file.  However, it is not
checked if the file exists (you need to do this by yourself if you use this method directly).

=item I<noredirect =E<gt> $bool>

If C<noredirect> is set to a true value, this method won't follow any redirects.

=back

I<Some notes:>

=over 4

=item

After each call, the current user agent instance is destroyed.  This is done to
reset the redirect status so that the next request won't contain auth data
unless required.

=item

This method handles all HTTP status codes that are considered as C<successful>
(all C<2xx> codes) and the codes C<302> and C<303>.  If other status codes are returned,
the request is considered an error and the method dies.

=back

=cut

sub _get_response {
    my $self   = shift;
    my $params = shift;

    my $uri    = $params->{uri} || die "No URI given!";
    my $method = $params->{method};
    my %body   = $params->{params} ? %{ $params->{params} } : ();

    $self->useragent->requests_redirectable([]) if $params->{noredirect};

    my $res;
    unless (exists $body{file}) {
        $self->_debug("New request, URI is $uri");
        my $req = HTTP::Request->new;
        $req->header(Accept => 'application/json');
        $req->content_type('application/json');
        $req->uri($uri);

        $req->method('GET');
        if (%body) {
            $self->_debug("Have content, method will be POST");

            my $body_json = encode_json \%body;
            $req->content($body_json);
            $req->method('POST');
        }
        if (defined $method && $method) {
            $self->_debug("Explicit method $method");
            $req->method($method);
        }

        $res = $self->useragent->request($req);
    } else {
        my $file = delete $body{file};
        $res = $self->useragent->post($uri, [%body, file => [$file]], Content_Type => 'form-data');
    }

    $self->_reset_useragent;

    if ($res->is_success) {
        $self->_debug("Request successful: " . $res->code);
        $self->_debug("Content: '" . $res->content . "'");
        if ($res->content !~ /^\s*$/) {
            return decode_json($res->content);
        } else {
            return undef;
        }
    } elsif ($res->code == 303 || $res->code == 302) {
        $self->authenticate;
        my $location = to_Uri($res->header('Location'));
        my %params = map { $_ => $location->query_param($_) } $location->query_param;
        return $self->_get_response({ uri => $res->header('Location'), noredirect => 1 });
    } else {
        die "Request error: " . $res->status_line . Dumper($res);
    }
}

=head2 _debug

Parameters:

=over

=item C<@msgs>

=back

Small debug message handler that C<warn>s C<@msgs> joined with a line break.  Only prints if C<debug> set to C<true>.

=cut

sub _debug {
    my $self = shift;
    warn join("\n", @_) . "\n" if $self->debug;



( run in 0.809 second using v1.01-cache-2.11-cpan-39bf76dae61 )