view release on metacpan or search on metacpan
- Fix DNS bucket name checking for non-valid DNS bucket nams (GH #4)
- Fix URI escaping for filenames to avoid infinite loop on spaces (GH #5)
0.11 2015-08-31
- Fix signed_url to URI escape the Signature param value (GH #3)
0.10 2015-06-23
- dist changes related to kwalitee (no functional changes)
0.051 2015-05-23
- default size to 0 when not set in content-length (GH #1)
0.050 2014-10-23
New maintainer leejo
- Add lib/AWS/S3/Request/GetPreSignedUrl.pm to MANIFEST
- Various changes in dist related to issue tracking, testing, etc
0.040 2014-10-23
Work done by leejo
- Add signed_url method to AWS::S3::File and tests
- Fix load / hash order bugs in AWS::S3::Signer
lib/AWS/S3/Bucket.pm view on Meta::CPAN
my $type = 'GetFileInfo';
my $parser = $s->_get_property( $type, key => $key )
or return;
my $res = $parser->response;
confess "Cannot get file: ", $res->as_string, " " unless $res->is_success;
return AWS::S3::File->new(
bucket => $s,
key => $key || undef,
size => $res->header( 'content-length' ) || 0,
contenttype => $res->header( 'content-type' ) || 'application/octet-stream',
etag => $res->header( 'etag' ) || undef,
lastmodified => $res->header( 'last-modified' ) || undef,
is_encrypted => ( $res->header( 'x-amz-server-side-encryption' ) || '' ) eq 'AES256' ? 1 : 0,
);
} # end file()
sub add_file {
my ( $s, %args ) = @_;
lib/AWS/S3/File.pm view on Meta::CPAN
required => 1,
weak_ref => 0,
);
has 'size' => (
is => 'ro',
isa => 'Int',
required => 0,
default => sub {
my $self = shift;
return length ${$self->contents};
}
);
has 'etag' => (
is => 'ro',
isa => 'Str',
required => 0,
);
has 'owner' => (
lib/AWS/S3/HTTPRequest.pm view on Meta::CPAN
s3 => $s->s3,
method => $method,
uri => $uri,
content => $content ? \$content : undef,
headers => [ $headers->flatten ],
);
$headers->header( 'Authorization' => $signer->auth_header );
$headers->header( 'Date' => $signer->date );
$headers->header( 'Host' => URI->new( $uri )->host );
$headers->header( 'content-length' => $signer->content_length ) if $content;
$headers->header( 'content-type' => $signer->content_type ) if $content;
my $request = HTTP::Request->new( $method, $uri, $headers, $content );
return $request;
} # end http_request()
__PACKAGE__->meta->make_immutable;
lib/AWS/S3/Roles/Bucket.pm view on Meta::CPAN
$uri = "$protocol://$1.$endpoint$2";
} # end if()
return $uri;
}
sub is_dns_bucket {
my ( $s,$bucket ) = @_;
# https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
return 0 if ( length( $bucket ) < 3 or length( $bucket ) > 63 );
return 0 if $bucket =~ /^(?:\d{1,3}\.){3}\d{1,3}$/;
# DNS bucket names can contain lowercase letters, numbers, and hyphens
# so anything outside this range we say isn't a valid DNS bucket
return $bucket =~ /[^a-z0-9-\.]/ ? 0 : 1;
}
1;
lib/AWS/S3/Signer.pm view on Meta::CPAN
return '' unless $s->content;
return encode_base64( md5( ${ $s->content } ), '' );
}
);
has 'content' => (
is => 'ro',
isa => 'Maybe[ScalarRef]',
);
has 'content_length' => (
is => 'ro',
isa => 'Int',
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() );
lib/AWS/S3/Signer/V4.pm view on Meta::CPAN
sub parse_host {
my $self = shift;
my $host = shift;
my $region = shift;
# this entire thing should probably refactored into its own
# distribution, a la https://github.com/zirkelc/amazon-s3-url
# https://docs.aws.amazon.com/prescriptive-guidance/latest/defining-bucket-names-data-lakes/faq.html
# Only lowercase letters, numbers, dashes, and dots are allowed in S3 bucket names.
# Bucket names must be three to 63 characters in length,
# must begin and end with a number or letter,
# and cannot be in an IP address format.
my $bucket_re = '[a-z0-9][a-z0-9\-\.]{1,61}[a-z0-9]';
my $domain_re = 'amazonaws\.com';
my $region_re = '(?:af|ap|ca|eu|il|me|mx|sa|us)-[a-z]+-\d';
my ( $service, $url_style );
# listed in order of appearance found in the docs:
# https://community.aws/content/2biM1C0TkMkvJ2BLICiff8MKXS9/format-and-parse-amazon-s3-url?lang=en
t/010_basic.t view on Meta::CPAN
contents => \$contents,
), "Added file $_";
}# end for()
# Make sure they all worked:
my $counted = 0;
foreach my $key ( sort keys %info )
{
my $contents = $info{$key};
ok my $file = $bucket->file($key), "bucket.file($key) returned a file";
is $file->size, length($contents), 'file.size is correct';
is ${$file->contents}, $contents, 'file.contents is correct';
my $expiration_date = time() + 3600;
my $url = $file->signed_url( $expiration_date );
is( $file->signed_url( $expiration_date ),$url,'signed_url same' ) for 1 .. 10;
warn "--->$url";
my $res = $s3->ua->get( $url );
ok( $res->is_success,'get signed_url' );
isnt( $res->code,403,'not forbidden' );
last if $counted++ > 4;
}# end for()
t/aws/s3/bucket.t view on Meta::CPAN
use warnings;
package Mocked::HTTP::Response;
use Moose;
extends 'HTTP::Response';
sub content { shift->{_msg}; }
sub code { 200 }
sub is_success { 1 }
sub header { $_[1] =~ /content-length/i ? 1 : 'header' }
1;
package main;
use Test::More;
use Test::Exception;
use FindBin qw/ $Script /;
use Carp 'confess';
$SIG{__DIE__} = \&confess;
t/aws/s3/file.t view on Meta::CPAN
use warnings;
package Mocked::HTTP::Response;
use Moose;
extends 'HTTP::Response';
sub content { shift->{_msg}; }
sub code { 200 }
sub is_success { 1 }
sub header { $_[1] =~ /content-length/i ? 1 : 'header' }
1;
package main;
use Test::More;
use Test::Deep;
use URI::Escape qw/ uri_escape /;
use Carp 'confess';
t/aws/s3/file_iterator.t view on Meta::CPAN
use warnings;
package Mocked::HTTP::Response;
use Moose;
extends 'HTTP::Response';
sub content { shift->{_msg}; }
sub code { 200 }
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';
t/aws/s3/http_request.t view on Meta::CPAN
method => 'POST',
path => '/bar/baz',
content => 'Hello World!'
),
'AWS::S3::HTTPRequest'
);
isa_ok( my $http_request_with_content = $request_with_content->http_request, 'HTTP::Request' );
my $header = $http_request_with_content->headers;
is( $header->header( 'content-type' ), 'text/plain', '... and content-type got set' );
is( $header->header( 'content-length' ), 12, '... and content-length got set' );
is( $header->header( 'host' ), 's3.baz.com', '... and host got set' );
done_testing();
t/aws/s3/signer.t view on Meta::CPAN
bucket_name
uri
headers
date
string_to_sign
canonicalized_amz_headers
canonicalized_resource
content_type
content_md5
content
content_length
signature
/,
);
note( "attributes" );
isa_ok( $signer->s3,'AWS::S3' );
is( $signer->method,'HEAD','method' );
is( $signer->bucket_name,'maibucket','bucket_name' );
isa_ok( $signer->uri,'URI' );
t/aws/s3/signer.t view on Meta::CPAN
is(
$signer->string_to_sign,
"HEAD\nXrY7u+Ae7tCTyyK7j1rNww==\ntext/plain\n".$signer->date."\n/maibucket/boz",
'string_to_sign'
);
is( $signer->canonicalized_amz_headers,'','canonicalized_amz_headers' );
is( $signer->canonicalized_resource,'/maibucket/boz','canonicalized_resource' );
is( $signer->content_type,'text/plain','content_type' );
is( $signer->content_md5,'XrY7u+Ae7tCTyyK7j1rNww==','content_md5' );
is( ${ $signer->content },'hello world','content' );
is( $signer->content_length,11,'content_length' );
like( $signer->signature,qr/^.{28}$/,'signature' );
note( "methods" );
like( $signer->auth_header,qr/AWS foo:.{28}/,'auth_header' );
done_testing();
t/aws/s3/signer/v4.t view on Meta::CPAN
is( $request->method, 'POST', 'request method correct' );
is( $request->header('Host'), 'iam.amazonaws.com', 'host correct' );
is( $request->header('X-Amz-Date'), '20140101T060000Z', 'timestamp correct' );
is(
$request->content,
'Action=ListUsers&Version=2010-05-08',
'payload correct'
);
is(
$request->header('Authorization'),
'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20140101/us-east-1/iam/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=0233049369ae675cea7616efa5d2e5216c37a4b1496a36595f32181f078e3549',
'signature correct'
);
$request = GET( 'https://iam.amazonaws.com?Action=ListUsers&Version=2010-05-08',
Date => '1 January 2014 01:00:00 -0500' );
my $expected =
'https://iam.amazonaws.com?Action=ListUsers&Version=2010-05-08&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIDEXAMPLE%2F20140101%2Fus-east-1%2Fiam%2Faws4_request&X-Amz-Date=20140101T060000Z&X-Amz-SignedHeaders=host&X-Amz-Signature=9d0b832ec5c5...
is( $signer->signed_url($request),
t/aws/s3/signer/v4.t view on Meta::CPAN
Date => '1 January 2014 01:00:00 -0500'
);
is( $signer->signed_url($request), $expected, 'domain bucket url' );
$request = POST('https://cognito-identity.us-east-1.amazonaws.com',
Date => '1 January 2014 01:00:00 -0500');
$signer->sign($request);
is($request->header('Authorization'),'AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20140101/us-east-1/cognito-identity/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=047c9335c6a34448efc59c2a1813711602e208dcb42ae95cd3b88...
exit 0;