AWS-S3

 view release on metacpan or  search on metacpan

README.markdown  view on Meta::CPAN

    <a href='https://travis-ci.org/leejo/AWS-S3?branch=master'><img src='https://travis-ci.org/leejo/AWS-S3.svg?branch=master' /></a>
    <a href='https://coveralls.io/r/leejo/AWS-S3?branch=master'><img src='https://coveralls.io/repos/leejo/AWS-S3/badge.png?branch=master' alt='Coverage Status' /></a>
</div>

# SYNOPSIS

    use AWS::S3;

    my $s3 = AWS::S3->new(
      access_key_id     => 'E654SAKIASDD64ERAF0O',
      secret_access_key => 'LgTZ25nCD+9LiCV6ujofudY1D6e2vfK0R4GLsI4H',
      session_token     => 'IQob3JpJZ2luXJ2VjJEL7//////////wE...',
      region            => 'eu-west-1', # set to relevant AWS region
      honor_leading_slashes => 0, # set to allow leading slashes in bucket names, defaults to 0
    );

    # Add a bucket:
    my $bucket = $s3->add_bucket(
      name    => 'foo-bucket',
    );

README.markdown  view on Meta::CPAN

# CONSTRUCTOR

Call `new()` with the following parameters.

## access\_key\_id

Required.  String.

Provided by Amazon, this is your access key id.

## secret\_access\_key

Required.  String.

Provided by Amazon, this is your secret access key.

## secure

Optional.  Boolean.

Default is `0`

## endpoint

Optional.  String.

Default is `s3.amazonaws.com`

README.markdown  view on Meta::CPAN


Optional. Boolean to set if bucket names should include any leading slashes
when sent to S3 - defaults to zero

# PUBLIC PROPERTIES

## access\_key\_id

String.  Read-only

## secret\_access\_key

String.  Read-only.

## secure

Boolean.  Read-only.

## endpoint

String.  Read-only.

## ua

[LWP::UserAgent](https://metacpan.org/pod/LWP%3A%3AUserAgent) object.  Read-only.

lib/AWS/S3.pm  view on Meta::CPAN

use IO::Socket::INET;
use Class::Load 'load_class';
use Log::Any qw( $LOG );

use AWS::S3::ResponseParser;
use AWS::S3::Owner;
use AWS::S3::Bucket;

our $VERSION = '2.00';

has [qw/access_key_id secret_access_key/] => ( is => 'ro', isa => 'Str' );

has 'session_token' => (
    is      => 'ro',
    isa     => 'Maybe[Str]',
    lazy    => 1,
    default => sub { $ENV{AWS_SESSION_TOKEN} },
);

has 'region' => (
    is      => 'ro',
    isa     => 'Maybe[Str]',
    lazy    => 1,
    default => sub { $ENV{AWS_REGION} },
);

has 'secure' => (
    is      => 'ro',
    isa     => 'Bool',
    lazy    => 1,
    default => 0
);

has 'endpoint' => (
    is      => 'ro',
    isa     => 'Str',
    lazy    => 1,

lib/AWS/S3.pm  view on Meta::CPAN

=for html
<a href='https://travis-ci.org/leejo/AWS-S3?branch=master'><img src='https://travis-ci.org/leejo/AWS-S3.svg?branch=master' /></a>
<a href='https://coveralls.io/r/leejo/AWS-S3?branch=master'><img src='https://coveralls.io/repos/leejo/AWS-S3/badge.png?branch=master' alt='Coverage Status' /></a>

=head1 SYNOPSIS

  use AWS::S3;

  my $s3 = AWS::S3->new(
    access_key_id     => 'E654SAKIASDD64ERAF0O',
    secret_access_key => 'LgTZ25nCD+9LiCV6ujofudY1D6e2vfK0R4GLsI4H',
    session_token     => 'IQob3JpJZ2luXJ2VjJEL7//////////wE...',
    region            => 'eu-west-1', # set to relevant AWS region
    honor_leading_slashes => 0, # set to allow leading slashes in bucket names, defaults to 0
  );

  # Add a bucket:
  my $bucket = $s3->add_bucket(
    name    => 'foo-bucket',
  );

lib/AWS/S3.pm  view on Meta::CPAN

=head1 CONSTRUCTOR

Call C<new()> with the following parameters.

=head2 access_key_id

Required.  String.

Provided by Amazon, this is your access key id.

=head2 secret_access_key

Required.  String.

Provided by Amazon, this is your secret access key.

=head2 secure

Optional.  Boolean.

Default is C<0>

=head2 endpoint

Optional.  String.

Default is C<s3.amazonaws.com>

lib/AWS/S3.pm  view on Meta::CPAN


Optional. Boolean to set if bucket names should include any leading slashes
when sent to S3 - defaults to zero

=head1 PUBLIC PROPERTIES

=head2 access_key_id

String.  Read-only

=head2 secret_access_key

String.  Read-only.

=head2 secure

Boolean.  Read-only.

=head2 endpoint

String.  Read-only.

=head2 ua

L<LWP::UserAgent> object.  Read-only.

lib/AWS/S3/File.pm  view on Meta::CPAN


    if ( my $msg = $response->friendly_error() ) {
        die $msg;
    }    # end if()
}    # end _set_contents()

sub signed_url {
    my $s       = shift;
    my $expires = shift || 3600;

    # expiry for v4 signature is in seconds, not epoch time
    if ( $expires > time ) {
        $expires -= time;
    }

	my $key = $s->key;

	if ( ! $s->bucket->s3->honor_leading_slashes ) {
		$key =~ s!^/!!;
	}

lib/AWS/S3/File.pm  view on Meta::CPAN


Deletes the file from Amazon S3.

=head2 update()

Update contents and/or contenttype of the file.

=head2 signed_url( $expiry_time )

Will return a signed URL for public access to the file. $expiry_time should be a
Unix seconds since epoch, and will default to now + 1 hour is not passed.

Note that the Signature parameter value will be URI encoded to prevent reserved
characters (+, =, etc) causing a bad request.

=head1 SEE ALSO

L<The Amazon S3 API Documentation|http://docs.amazonwebservices.com/AmazonS3/latest/API/>

L<AWS::S3>

lib/AWS/S3/Roles/Bucket.pm  view on Meta::CPAN

package AWS::S3::Roles::Bucket;

use Moose::Role;

sub bucket_uri {
    my ( $s,$path ) = @_;

    $path      //= $s->bucket;
    my $protocol = $s->s3->secure ? 'https' : 'http';
    my $endpoint = $s->s3->endpoint;
    my $uri = "$protocol://$endpoint/$path";
    if ( $path =~ m{^([^/?]+)(.*)} && $s->is_dns_bucket( $1 ) ) {
        $uri = "$protocol://$1.$endpoint$2";
    }    # end if()

    return $uri;
}

sub is_dns_bucket {

lib/AWS/S3/Roles/Request.pm  view on Meta::CPAN

    is       => 'ro',
    isa      => 'Str',
    required => 1,
);

has 'protocol' => (
    is      => 'ro',
    isa     => 'Str',
    lazy    => 1,
    default => sub {
        shift->s3->secure ? 'https' : 'http';
    }
);

has 'endpoint' => (
    is      => 'ro',
    isa     => 'Str',
    lazy    => 1,
    default => sub {
        shift->s3->endpoint;
    }

lib/AWS/S3/Roles/Request.pm  view on Meta::CPAN

);

has 'signerv4' => (
    is       => 'ro',
    isa      => 'AWS::S3::Signer::V4',
    lazy     => 1,
    default  => sub {
        my $s = shift;
        AWS::S3::Signer::V4->new(
            -access_key => $s->s3->access_key_id,
            -secret_key => $s->s3->secret_access_key,
        );
    }
);

sub _send_request {
    my ( $s, $method, $uri, $headers, $content ) = @_;
    $LOG->debug('Making AWS request', {method => $method, uri => "$uri"});

    my $req = HTTP::Request->new( $method => $uri );
    $req->content( $content ) if $content;

lib/AWS/S3/Signer.pm  view on Meta::CPAN

    lazy     => 1,
    default  => sub { length( ${ shift->content } ) }
);

has 'signature' => (
    is       => 'ro',
    isa      => 'Str',
    lazy     => 1,
    default  => sub {
        my $s    = shift;
        my $hmac = Digest::HMAC_SHA1->new( $s->s3->secret_access_key );
        $hmac->add( $s->string_to_sign() );
        return encode_base64( $hmac->digest, '' );
    }
);

sub auth_header {
    my $s = shift;

    return 'AWS ' . $s->s3->access_key_id . ':' . $s->signature;
}    # end auth_header()

lib/AWS/S3/Signer/V4.pm  view on Meta::CPAN


AWS::S3::Signer::V4 - Create a version4 signature for Amazon Web Services

=head1 SYNOPSIS

 use AWS::S3::Signer::V4;
 use HTTP::Request::Common;
 use LWP;

 my $signer = AWS::S3::Signer::V4->new(-access_key => 'AKIDEXAMPLE',
                                   -secret_key => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY');
 my $ua     = LWP::UserAgent->new();

 # Example POST request
 my $request = POST('https://iam.amazonaws.com',
		    [Action=>'ListUsers',
		     Version=>'2010-05-08']);
 $signer->sign($request);
 my $response = $ua->request($request);

 # Example GET request

lib/AWS/S3/Signer/V4.pm  view on Meta::CPAN


=head1 DESCRIPTION

This module implement's Amazon Web Service's Signature version 4
(http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).

=head1 METHODS

=over 4

=item $signer = AWS::S3::Signer::V4->new(-access_key => $account_id,-secret_key => $private_key);

Create a signing object using your AWS account ID and secret key. You
may also use the temporary security tokens received from Amazon's STS
service, either by passing the access and secret keys derived from the
token, or by passing a VM::EC2::Security::Token produced by the
VM::EC2 module.

Arguments:

 Argument name       Argument Value
 -------------       --------------
 -access_key         An AWS access key (account ID)

 -secret_key         An AWS secret key

 -security_token     A VM::EC2::Security::Token object

 -service            An AWS service

 -region             An AWS region


If a security token is provided, it overrides any values given for
-access_key or -secret_key.

If the environment variables EC2_ACCESS_KEY and/or EC2_SECRET_KEY are
set, their contents are used as defaults for -access_key and
-secret_key.

If -service and/or -region is not provided, they are automtically determined
according to endpoint.

=cut

sub new {
    my $self = shift;
    my %args = @_;

    my ( $id, $secret, $token, $region, $service );
    if ( ref $args{-security_token}
        && $args{-security_token}->can('access_key_id') )
    {
        $id     = $args{-security_token}->accessKeyId;
        $secret = $args{-security_token}->secretAccessKey;
    }

    $id ||= $args{-access_key} || $ENV{EC2_ACCESS_KEY}
      or croak
"Please provide -access_key parameter or define environment variable EC2_ACCESS_KEY";
    $secret ||= $args{-secret_key} || $ENV{EC2_SECRET_KEY}
      or croak
"Please provide -secret_key or define environment variable EC2_SECRET_KEY";
    $region  = $args{-region}  || $ENV{EC2_REGION};
    $service = $args{-service} || $ENV{EC2_SERVICE};

    return bless {
        access_key => $id,
        secret_key => $secret,
        region     => $region,
        region     => $args{-region},
        service    => $args{-service},
        (
            defined( $args{-security_token} )
            ? ( security_token => $args{-security_token} )
            : ()
        ),
      },
      ref $self || $self;
}

sub access_key { shift->{access_key} }
sub secret_key { shift->{secret_key} }

=item $signer->sign($request [,$region] [,$payload_sha256_hex])

Given an HTTP::Request object, add the headers required by AWS and
then sign it with a version 4 signature by adding an "Authorization"
header.

The request must include a URL from which the AWS endpoint and service
can be derived, such as "ec2.us-east-1.amazonaws.com." In some cases
(e.g. S3 bucket operations) the endpoint does not indicate the
region. In this case, the region can be forced by passing a defined
value for $region. The current date and time will be added to the
request using an "X-Amz-Date header." To force the date and time to a
fixed value, include the "Date" header in the request.

The request content, or "payload" is retrieved from the HTTP::Request
object by calling its content() method.. Under some circumstances the
payload is not included directly in the request, but is in an external
file that will be uploaded as the request is executed. In this case,
you must pass a second argument containing the results of running
sha256_hex() (from the Digest::SHA module) on the content.

The method returns a true value if successful. On errors, it will
throw an exception.

=item $url = $signer->signed_url($request)

This method will generate a signed GET URL for the request. The URL
will include everything needed to perform the request.

lib/AWS/S3/Signer/V4.pm  view on Meta::CPAN

=item my $url $signer->signed_url($request_or_uri [,$expires] [,$verb])

Pass an HTTP::Request, a URI object, or just a plain URL string
containing the proper endpoint and parameters needed for an AWS REST
API Call. This method will return an appropriately signed request as a
URI object, which can be shared with non-AWS users for the purpose of,
e.g., accessing an object in a private S3 bucket.

Pass an optional $expires argument to indicate that the URL will only
be valid for a finite period of time. The value of the argument is in
seconds.

Pass an optional verb which is useful for HEAD requests, this defaults to GET.

=cut

sub signed_url {
    my $self = shift;
    my ( $arg1, $expires, $verb ) = @_;
    my ( $request, $uri );

lib/AWS/S3/Signer/V4.pm  view on Meta::CPAN

    return $uri if $uri->query_param('X-Amz-Signature');

    my $scope = $self->_scope($request);

    $uri->query_param( 'X-Amz-Algorithm'  => $self->_algorithm );
    $uri->query_param( 'X-Amz-Credential' => $self->access_key . '/' . $scope );
    $uri->query_param( 'X-Amz-Date'       => $self->_datetime($request) );
    $uri->query_param( 'X-Amz-Expires'    => $expires ) if $expires;
    $uri->query_param( 'X-Amz-SignedHeaders' => 'host' );

# If there was a security token passed, we need to supply it as part of the authorization
# because AWS requires it to validate IAM Role temporary credentials.

    if ( defined( $self->{security_token} ) ) {
        $uri->query_param( 'X-Amz-Security-Token' => $self->{security_token} );
    }

# Since we're providing auth via query parameters, we need to include UNSIGNED-PAYLOAD
# http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
# it seems to only be needed for S3.

    if ( $scope =~ /\/s3\/aws4_request$/ ) {
        $self->_sign( $request, undef, 'UNSIGNED-PAYLOAD' );
    }
    else {

lib/AWS/S3/Signer/V4.pm  view on Meta::CPAN


    unless ( $request->header('host') ) {
        my $host = $request->uri->host;
        $request->header( host => $host );
    }

    my $scope = $self->_scope( $request, $region );
    my ( $date, $service );
    ( $date, $region, $service ) = $self->_parse_scope($scope);

    my $secret_key = $self->secret_key;
    my $access_key = $self->access_key;
    my $algorithm  = $self->_algorithm;

    my ( $hashed_request, $signed_headers ) =
      $self->_hash_canonical_request( $request, $payload_sha256_hex );
    my $string_to_sign =
      $self->_string_to_sign( $datetime, $scope, $hashed_request );
    my $signature =
      $self->_calculate_signature( $secret_key, $service, $region, $date,
        $string_to_sign );
    $request->header( Authorization =>
"$algorithm Credential=$access_key/$scope, SignedHeaders=$signed_headers, Signature=$signature"
    );
}

sub _zulu_time {
    my $self     = shift;
    my $request  = shift;
    my $date     = $request->header('Date');

lib/AWS/S3/Signer/V4.pm  view on Meta::CPAN

    return ( $request_digest, $signed_headers );
}

sub _string_to_sign {
    my $self = shift;
    my ( $datetime, $credential_scope, $hashed_request ) = @_;
    return join( "\n",
        'AWS4-HMAC-SHA256', $datetime, $credential_scope, $hashed_request );
}

=item $signing_key = AWS::S3::Signer::V4->signing_key($secret_access_key,$service_name,$region,$date)

Return just the signing key in the event you wish to roll your own signature.

=cut

sub signing_key {
    my $self = shift;
    my ( $kSecret, $service, $region, $date ) = @_;
    my $kDate    = hmac_sha256( $date,          'AWS4' . $kSecret );
    my $kRegion  = hmac_sha256( $region,        $kDate );

t/010_basic.t  view on Meta::CPAN

use Carp 'confess';
$SIG{__DIE__} = \&confess;

plan skip_all => '$ENV{AWS_ACCESS_KEY_ID} && $ENV{AWS_SECRET_ACCESS_KEY} must both be defined to run this test'
	unless( $ENV{AWS_ACCESS_KEY_ID} && $ENV{AWS_SECRET_ACCESS_KEY} );

use_ok('AWS::S3');

my $s3 = AWS::S3->new(
  access_key_id     => $ENV{AWS_ACCESS_KEY_ID},
  secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY},
  session_token     => $ENV{AWS_SESSION_TOKEN},
  region            => $ENV{AWS_REGION},
);

isa_ok $s3->ua, 'LWP::UserAgent';

cleanup();

ok my $owner = $s3->owner(), "s3.owner returns a value";
isa_ok $owner, 'AWS::S3::Owner';

t/010_basic.t  view on Meta::CPAN

{

if(0) {
  # Try cloudfront integration if we've got it:
  eval { require AWS::CloudFront; require AWS::CloudFront::S3Origin; };
  die $@ if $@;
  unless( $@ )
  {
    my $cf = AWS::CloudFront->new(
      access_key_id     => $s3->access_key_id,
      secret_access_key => $s3->secret_access_key,
    );
    my $dist = $cf->add_distribution(
      Origin  => AWS::CloudFront::S3Origin->new(
        DNSName => $bucket->name . '.s3.amazonaws.com',
      )
    );
    $bucket->enable_cloudfront_distribution( $dist );
  }# end unless()
}

#  my $acl = $bucket->acl;
#  ok $bucket->acl( 'private' ), 'set bucket.acl to private';
#  is $acl, $bucket->acl, 'get bucket.acl returns private';

#  ok $bucket->location_constraint( 'us-east-1' ), 'set bucket.location_constraint to us-east-1';
#  is $bucket->location_constraint, 'us-east-1', 'get bucket.location returns us-east-1';
#  is $s3->bucket($bucket->name)->location_constraint, 'us-east-1', 'get bucket.location returns us-east-1 second time';

#  is $bucket->policy, '', 'get bucket.policy returns empty string';

  my $test_str = "This is the original value right here!"x20;
  my $filename = 'foo/bar.txt';
  ADD_FILE: {
    my $file = $bucket->add_file(
      key       => $filename,
      contents  => \$test_str
    );

t/aws/s3.t  view on Meta::CPAN


sub content { return shift->{_msg}; }

1;

package main;

use Test::More 'no_plan';
use Test::Deep;
use Test::Exception;
use Data::Section::Simple 'get_data_section';

use Carp 'confess';
$SIG{__DIE__} = \&confess;

use_ok('AWS::S3');

my $s3 = AWS::S3->new(
  access_key_id     => $ENV{AWS_ACCESS_KEY_ID}     // 'foo',
  secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY} // 'bar',
  endpoint          => 'bad.hostname.',
);

my $bucket_name = "aws-s3-test-" . int(rand() * 1_000_000) . '-' . time() . "-foo";

eval {
    my $bucket = $s3->add_bucket( name => $bucket_name, location => 'us-west-1' );
};

like(

t/aws/s3.t  view on Meta::CPAN

                307,
                'TEMPORARY REDIRECT',
                [ Location => 'http://example.org' ],
                '<fake>TemporaryRedirect</fake>'
            );
        }
        elsif ( $i == 2 ) {

            # the PUT is sent again, but to the forwarded location

            is( $req->method, 'PUT', 'redirected and second PUT request' );
            is( $req->uri->as_string, 'http://example.org', '... and to the correct URI' );

            $i++;
            return Mocked::HTTP::Response->new( 200, q{} );
        }
        else {
            # there is a call to ->bucket, which does ->buckets, which is empty.
            is( $req->method, 'GET', '->buckets with GET' );
            is( $req->uri->as_string, 'http://bad.hostname./', '... and with correct URI' );

            # we need to return XML in the body or xpc doesn't work
            return Mocked::HTTP::Response->new( 200,
                get_data_section('ListAllMyBucketsResult.xml') );
        }
    };

    my $bucket = $s3->add_bucket( name => 'bar' );
    isa_ok( $bucket, 'AWS::S3::Bucket' );
    is( $bucket->name, 'bar', '... and the right bucket got returned' );
};

# list all buckets and owner
for my $case ( qw(ListAllMyBucketsResult.xml ListAllMyBucketsResult-noxmlns.xml) ) {
    subtest "List all buckets and owner: $case" => sub {
        my $xml = get_data_section($case);

        local *LWP::UserAgent::Determined::request = sub {
            return Mocked::HTTP::Response->new( 200,$xml );
        };

        isa_ok( my $owner = $s3->owner,'AWS::S3::Owner' );
        is( $owner->id, 'bcaf1ffd86f41161ca5fb16fd081034f', '... and the owner id correct' );
        is( $owner->display_name, 'webfile', '... and the owner name is correct' );

        my @buckets = $s3->buckets;
        cmp_deeply( \@buckets,
            [ obj_isa('AWS::S3::Bucket'), obj_isa('AWS::S3::Bucket') ], '->buckets' );
        ok( ! $s3->bucket( 'does not exist' ),'!->bucket' );
        is( $s3->bucket( 'foo' )->name, 'foo', '->bucket' );
    };
}

{
    my $xml = get_data_section('error.xml');

    local *LWP::UserAgent::Determined::request = sub {
        return Mocked::HTTP::Response->new( 400,$xml );
    };

    throws_ok { $s3->add_bucket( name => 'too many buckets', location => 'us-west-1' ) }
    qr/TooManyBuckets/, 'add_bucket throws an error';
}
__DATA__
@@ ListAllMyBucketsResult.xml

t/aws/s3/bucket.t  view on Meta::CPAN

use FindBin qw/ $Script /;

use Carp 'confess';
$SIG{__DIE__} = \&confess;

use_ok('AWS::S3');

note( "construction" );
my $s3 = AWS::S3->new(
    access_key_id     => $ENV{AWS_ACCESS_KEY_ID}     // 'foo',
    secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY} // 'bar',
    endpoint          => $ENV{AWS_ENDPOINT}          // 's3.baz.com',
);

use_ok('AWS::S3::Bucket');

isa_ok(
    my $bucket = AWS::S3::Bucket->new(
        s3   => $s3,
        name => $ENV{AWS_TEST_BUCKET} // 'maibucket',
    ),

t/aws/s3/file.t  view on Meta::CPAN

use Carp 'confess';
$SIG{__DIE__} = \&confess;

use_ok('AWS::S3');

note( "construction" );

foreach my $leading_slashes ( 0,1 ) {
my $s3 = AWS::S3->new(
    access_key_id     => $ENV{AWS_ACCESS_KEY_ID}     // 'foo',
    secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY} // 'bar',
    endpoint          => $ENV{AWS_ENDPOINT}          // 's3.baz.com',
	honor_leading_slashes => $leading_slashes,
);

use_ok('AWS::S3::File');
use_ok('AWS::S3::Bucket');
use_ok('AWS::S3::Request::SetFileContents');

monkey_patch_module();

t/aws/s3/file_iterator.t  view on Meta::CPAN

sub is_success     { 1 }
sub header         { $_[1] =~ /content-length/i ? 1 : 'header' }

1;

package main;
use Test::More;
use Test::Deep;
use Test::Exception;
use FindBin qw/ $Script /;
use Data::Section::Simple 'get_data_section';

use Carp 'confess';
$SIG{__DIE__} = \&confess;

use_ok('AWS::S3');
use_ok('AWS::S3::FileIterator');
use_ok('AWS::S3::Bucket');

my $s3 = AWS::S3->new(
    access_key_id     => $ENV{AWS_ACCESS_KEY_ID}     // 'foo',
    secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY} // 'bar',
    endpoint          => $ENV{AWS_ENDPOINT}          // 's3.baz.com',
);

isa_ok(
    my $bucket = AWS::S3::Bucket->new(
        s3   => $s3,
        name => $ENV{AWS_TEST_BUCKET} // 'maibucket',
    ),
    'AWS::S3::Bucket'
);

t/aws/s3/file_iterator.t  view on Meta::CPAN

            page_size   => 1,
            bucket      => $bucket,
            marker      => 'foo',
            pattern     => qr/\d/,
        );
        is( $iterator2->marker,'foo','marker passed');
        is( $iterator2->pattern,qr/\d/,'pattern passed');
        is( $iterator2->prefix,undef,'!prefix' );
    }

    my $mocked_response = Mocked::HTTP::Response->new( 200,get_data_section('ListBucketResult.xml') );
    local *LWP::UserAgent::Determined::request = sub { $mocked_response };
    
    my @pages = $iterator->next_page; # to check wantarray
    cmp_deeply( \@pages,[ obj_isa('AWS::S3::File') ],'next_page returns one ::File' );
    is( $pages[0]->key,'img/my image.jpg','... and it is the one expected' );
    is( $iterator->next_page->[0]->key,'img/my-third-image.jpg','next_page second item' );
    is( $iterator->next_page->[0]->key,'img/my image.jpg','next_page new request, first item' );

    $mocked_response = Mocked::HTTP::Response->new( 200,get_data_section('EmptyResult') );
    ok( $iterator->next_page,'next_page second item' );
    ok( ! $iterator->next_page,'no more items' );
}

subtest 'advance to page X before processing' => sub {
	my $iterator = AWS::S3::FileIterator->new(
		page_number => 5,
		page_size   => 1,
		bucket      => $bucket,
        pattern     => qr/\d+/,
	);

    my $number_of_request;
    my $xml = get_data_section('LongResult');
    my $mocked_response = Mocked::HTTP::Response->new( 200,$xml );
    local *LWP::UserAgent::Determined::request = sub { $number_of_request++; return $mocked_response };

    is( $iterator->next_page->[0]->key,5,'start at file 5' );
    is( $iterator->next_page->[0]->key,6,'... file 6' );
    is( $iterator->next_page->[0]->key,7,'... file 7' );
    is( $iterator->next_page->[0]->key,8,'... file 8' );
    is( $iterator->next_page->[0]->key,9,'... file 9' );
    is( $iterator->next_page->[0]->key,0,'do a new request and get file 0' );
    is( $number_of_request,2,'did two requests' );

t/aws/s3/http_request.t  view on Meta::CPAN

use FindBin qw/ $Script /;

use Carp 'confess';
$SIG{__DIE__} = \&confess;

use_ok('AWS::S3');

note( "construction" );
my $s3 = AWS::S3->new(
    access_key_id     => $ENV{AWS_ACCESS_KEY_ID}     // 'foo',
    secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY} // 'bar',
    endpoint          => $ENV{AWS_ENDPOINT}          // 's3.baz.com',
);

use_ok('AWS::S3::HTTPRequest');

isa_ok(
    my $request = AWS::S3::HTTPRequest->new(
		s3     => $s3,
		method => 'POST',
		path   => '/foo/bar',

t/aws/s3/signer.t  view on Meta::CPAN

use Test::Deep;

use Carp 'confess';
$SIG{__DIE__} = \&confess;

use_ok('AWS::S3');

note( "construction" );
my $s3 = AWS::S3->new(
    access_key_id     => $ENV{AWS_ACCESS_KEY_ID}     // 'foo',
    secret_access_key => $ENV{AWS_SECRET_ACCESS_KEY} // 'bar',
    endpoint          => $ENV{AWS_ENDPOINT}          // 's3.baz.com',
);

use_ok('AWS::S3::Signer');

isa_ok(
    my $signer = AWS::S3::Signer->new(
        method  => 'HEAD',
        s3      => $s3,
        uri     => "http://maibucket.s3.baz.com/boz",

t/aws/s3/signer/v4.t  view on Meta::CPAN

use FindBin '$Bin';
use constant TEST_COUNT => 13;

use Test::More tests => TEST_COUNT;

use_ok('AWS::S3::Signer::V4');
use_ok('HTTP::Request::Common');

my $signer = AWS::S3::Signer::V4->new(
    -access_key => 'AKIDEXAMPLE',
    -secret_key => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
);
ok( $signer, 'AWS::S3::Signer::V4->new' );
my $request = POST(
    'https://iam.amazonaws.com',
    [ Action => 'ListUsers', Version => '2010-05-08' ],
    Date => '1 January 2014 01:00:00 -0500',
);
$signer->sign($request);

is( $request->method,         'POST',              'request method correct' );

t/aws/s3/signer/v4_parse_host.t  view on Meta::CPAN

use FindBin '$Bin';
use constant TEST_COUNT => 1169;

use Test::More tests => TEST_COUNT;
use Test::Deep;

use_ok('AWS::S3::Signer::V4');

my $signer = AWS::S3::Signer::V4->new(
    -access_key => 'AKIDEXAMPLE',
    -secret_key => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
);
isa_ok( $signer, 'AWS::S3::Signer::V4' );

# yes there is a bucket name here that matches a region name
# because inevitably someone will have done that
foreach my $bucket ( qw/
    foo
    eu-west-1
    1.ayeayeaye-wat-z
/ ) {



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