Net-Amazon-S3-0.991/0000775000175000017500000000000014264646670012775 5ustar branobranoNet-Amazon-S3-0.991/README0000644000175000017500000000073314264646670013656 0ustar branobranoThis archive contains the distribution Net-Amazon-S3, version 0.991: Use the Amazon S3 - Simple Storage Service This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. This README file was generated by Dist::Zilla::Plugin::Readme v6.025. Net-Amazon-S3-0.991/META.json0000644000175000017500000001370014264646670014415 0ustar branobrano{ "abstract" : "Use the Amazon S3 - Simple Storage Service", "author" : [ "Branislav Zahradn\u00edk " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.025, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Net-Amazon-S3", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" }, "suggests" : { "JSON::PP" : "2.27300" } }, "develop" : { "requires" : { "Test::EOL" : "0", "Test::More" : "0.88" } }, "runtime" : { "recommends" : { "VM::EC2::Security::CredentialCache" : "0" }, "requires" : { "Carp" : "0", "Data::Stream::Bulk::Callback" : "0", "DateTime::Format::HTTP" : "0", "Digest::HMAC_SHA1" : "0", "Digest::MD5" : "0", "Digest::MD5::File" : "0", "Digest::SHA" : "0", "Exporter::Tiny" : "0", "File::Find::Rule" : "0", "File::stat" : "0", "Getopt::Long" : "0", "HTTP::Date" : "0", "HTTP::Response" : "0", "HTTP::Status" : "0", "Hash::Util" : "0", "IO::File" : "1.14", "LWP" : "6.03", "LWP::UserAgent::Determined" : "0", "MIME::Base64" : "0", "MIME::Types" : "0", "Moose" : "0.85", "Moose::Meta::Class" : "0", "Moose::Object" : "0", "Moose::Role" : "0", "Moose::Util" : "0", "Moose::Util::TypeConstraints" : "0", "MooseX::Role::Parameterized" : "0", "MooseX::StrictConstructor" : "0.16", "MooseX::Types::DateTime::MoreCoercions" : "0.07", "Path::Class" : "0", "Pod::Usage" : "0", "Ref::Util" : "0", "Regexp::Common" : "0", "Safe::Isa" : "0", "Scalar::Util" : "0", "Sub::Override" : "0", "Term::Encoding" : "0", "Term::ProgressBar::Simple" : "0", "Test::Deep" : "v0.111.0", "Test::LWP::UserAgent" : "0", "Test::More" : "0", "Time::Piece" : "0", "URI" : "0", "URI::Escape" : "0", "URI::QueryParam" : "0", "XML::LibXML" : "0", "XML::LibXML::XPathContext" : "0", "constant" : "0", "namespace::clean" : "0", "parent" : "0", "sort" : "0", "strict" : "0", "warnings" : "0" } }, "test" : { "requires" : { "File::Temp" : "0", "FindBin" : "0", "HTTP::Request" : "0", "LWP::Simple" : "0", "Test::Deep" : "v0.111.0", "Test::Exception" : "0", "Test::MockTime" : "0", "Test::Warnings" : "0", "lib" : "0", "utf8" : "0", "vars" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/rustyconover/net-amazon-s3/issues" }, "repository" : { "type" : "git", "url" : "https://github.com/rustyconover/net-amazon-s3", "web" : "https://github.com/rustyconover/net-amazon-s3" } }, "version" : "0.991", "x_contributors" : [ "Aaron Crane ", "Ali Anari ", "Ali Zia ", "Ali ", "Branislav Zahradnik ", "Branislav Zahradn\u00edk ", "Christian Lackas ", "Conor Keegan ", "Douglas Sims ", "Dylan William Hardison ", "Eden Crane <>", "Emanuele Tomasi aka targzeta ", "Florian Schlichting ", "Gabriel Andrade ", "Gabriel Andrade ", "Gavin Carr ", "gregor herrmann ", "Haruka Iwao ", "Jun Kuriyama ", "Leo Lapworth ", "Leon Brocard ", "Michael Schout ", "Michal Josef \u0160pa\u010dek ", "Michele Beltrame ", "Michele Beltrame ", "Miquel Ruiz ", "Panu Ervamaa ", "Pavel A. Karoukin ", "Pedro Figueiredo ", "Pedro Figueiredo ", "Pedro Figueiredo ", "perlpong ", "Renato Santos ", "robert clarke ", "Robert Ward ", "rocketgithub ", "Rusty Conover ", "Rusty Conover ", "Rusty Conover ", "Rusty Conover ", "Sherwin Daganato ", "Slobodan Mis\u030ckovic\u0301 ", "Steven Berler ", "Struan Bartlett ", "Stuart Skelton ", "Tom Hukins ", "toritori0318 ", "Yanick Champoux " ], "x_generated_by_perl" : "v5.30.0", "x_serialization_backend" : "Cpanel::JSON::XS version 4.19", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } Net-Amazon-S3-0.991/CHANGES0000644000175000017500000002762514264646670014002 0ustar branobranoRevision history for Perl module Net::Amazon::S3: v0.991 2022-07-17 - Fix Signature V4 when uri contains tilde (issue #119, thanks marcusclip) - API->bucket now accepts optional region (issue #117) - Disable Signature V4 uri simplification for S3 service (issue #96) - Build user agent lazily 0.99 2021-12-05 - Client API doesn't check corrupted download anymore (using ETag == MD5) - fix broken Client::Object->head method (#112) (thanks Mortivor and fkoyer) - Support ranged download (#113) (thanks fkoyer) 0.98 2021-03-22 - document how to use buckets with dots, Signature V4, and HTTPS together - fix Net::Amazon::S3::Client::Object::exists (#94) - improve compatibility with DigitalOcean Spaces (#95) 0.97 2020-10-09 - presigned object access uri supports also PUT/DELETE methods (#89) 0.96 2020-10-07 - Signature V4 didn't work properly for services on non-standard port (issue #88) 0.95 2020-10-06 - bugfix release, with new test coverage - small cleanups 0.94 2020-09-27 - fix undefined method call in still untested methods (thanks Russell Jenkins) 0.93 2020-09-27 - fix syntax failures on perl < v5.22 (thanks cpantesters) 0.92 2020-09-26 - misc cleanups, more tests - Net::Amazon::S3::Client now can be constructed with same arguments as Net::Amazon::S3 - Support explicit ACL in bucket/object/upload creation - Support set_acl on Client::Bucket / Client::Object (issue #83) - Add support for bucket/object tagging (issue #44) 0.91 2020-08-19 23:25 +0 - fix regressions introduced by 0.90 - undeclared dependency - broken usage of hashref argument in N:A:S3 construction 0.90 2020-08-18 16:00 +0 - Support intelligent_tiering, glacier, and deep_archive storage classes (thanks Sherwin Daganato) - Object availability predicate (thanks Emanuele Tomasi) - fix default region handling (#77, #78, #80) - new authentication context architecture See Net::Amazon::S3::Authorization::IAM for future incompatiblity warning 0.89 Tue 11 Feb 2020 20:26:26 - fix signature v4 test (Ali Zia) 0.88 Sat 1 Feb 2020 21:29:52 - Allow passing headers from client to InitiateMultipartUpload request (Ali Zia) - sign uri with iam role (kuriyama) - Canned ACLs updated (ratsbane) 0.87 Mon 9 Dec 2019 19:53:42 GMT - Time::Piece fix from Eden Crane - eu-north-1 region (happy-barney) - drop hardcoded V2 in ListAllMyBuckets (happy-barney) - Fix setting of S3 XML document namespace (michal-josef-spacek) 0.86 Fri 12 Apr 2019 13:38:10 BST - Retry bucket HEAD few times see #51 (thanks Branislav Zahradník) - Support server side encryption also in Net::Amazon::S3::Bucket (thanks Branislav Zahradník) - Use session token if specified in Signature V4 as well #43 (thanks Branislav Zahradník) - Add website_redirect_location (thanks Gavin Carr) - Make keep_alive cache size configurable (thanks Michael Schout) - Pod::Weaver fixes (thanks Florian Schlichting) 0.85 Tue 28 Aug 2018 20:14:38 BST - Support standard_ia and onezone_ia storage classes (thanks Michele Beltrame) - run 'use_ok' on all modules (thanks Yanick Champoux) - spellings (thanks Gregor Herrmann) - LOTS of cleanup and refactoring (thanks Branislav Zahradník) 0.84 Mon 16 Jul 2018 17:49:10 BST - Put back credential cache code lost in Signature 4 patch (Branislav Zahradník) 0.83 Tue 10 Jul 2018 22:30:23 BST - All patches by Branislav Zahradník - Use Signature 4 by default only for amazonaws host (issue #29) - Relaxing constraint on owner id, accepting any string (issue #18) - Enable secure by default (issue #23) - Sanity object uris to avoid invalid signature (issue #28) 0.82 Sat 7 Jul 2018 14:28:06 BST - Use HEAD request to determine bucket region (patch by Branislav Zahradník) 0.81 Thu 28 Jun 2018 20:27:44 GMT (TRIAL RELEASE) - Restore CHANGES files format - Change path to new github repo - Add optional delimiter parameter to Net::Amazon::S3::Client::Bucket->list (patch by Christian Lackas) - Add expected and received ETag value if upload is detected as being incorrect. - Add support for all location constraints when creating buckets - making DateTime coercion optional for last_modified (something that might happen million of times without ever been used, in a rather expensive operation) (patch by Christian Lackas) - avoiding MD5 calculation of large files (chunked uploads) that are then never used (patch by Christian Lackas) - add ability to set use_virtual_host to use virtual host method of making requests which eliminate having to set the region endpoint of a bucket. (patch by Christian Lackas) - Add V4 support (patch by Branislav Zahradník) 0.80 Sun Apr 12 12:33:19 GMT 2015 - Fixed a bug in ETag validation (patch by Ali Anari) - Add support to set x-amz-metadata-directive when calling Net::Amazon::S3::copy_key - Add get_callback to Net::Amazon::S3::Client:Object - Add support for using IAM credentials when running on EC2, rather than hard coding access key and secret key. - Add support for aws_session_token in addition to access and secret key. - Remove code that determined if bucket can be used as a DNS Hostname as it was flawed. - Fix a bug where if a bucket contained a key 0 it would not be possible to be retrieved. - Add support for Net::Amazon::S3::Client::Bucket::delete_multi_object to handle more than 1,000 requests in one call. - Various test fixes from pnu. - Fix Moose enum problems (patch by tomhukins) - Allow content 'value' property to be ScalarRef for Net::Amazon::S3::HTTPRequest (patch by Struan Bartlett) - Add support for storage class when creating buckets along with user metadata (patch by Aaron Crane) - Add support for cache control header on Net::Amazon::S3::Client::Object (patch by toritori0318) - Support server side encryption (patch by Haruka Iwao) - Add support for multipart upload aborting (patch by Gabriel Andrade) 0.59 Sat Mar 17 09:36:38 GMT 2013 - Added support for security token authentication (patch by Miquel Ruiz) 0.58 Wed Nov 28 16:22:42 GMT 2012 - Added support for multi-part upload and multiple objects deletion (patch by Robert B. Clarke) 0.57 Sun Sep 16 22:38:38 BST 2012 - Added support for Content-disposition (initial patch by Michele Beltrame) - Added sync_up option to s3cl (patch by Leo Lapworth) - Dist::Zilla tidying 0.56 Sun Dec 18 22:22:32 GMT 2011 - Spelling error (RT #69817, patch from Fabrizio Regalli) - Added use_ok tests (RT #72856, suggested by Gregor Herrmann) - Added missing use URI::Escape (RT #72857, patch from Gregor Herrmann) - Bumped dependency on MooseX::StrictConstructor to 0.16 (RT #73229, suggested by Andrew Main) - Enforce dependency versions (RT #73193, suggested by Andrew Main) 0.55 Sat Dec 10 00:55:29 GMT 2011 - Replaced dependency on MooseX::Types::DateTimeX with MooseX::Types::DateTime::MoreCoercions (RT #72472). 0.54 Sat Mar 21 21:23:32 BST 2011 - Fix for a naked qw() warning (patch by David Wheeler) - Fixed path issues (patch by Pavel Karoukin) *WARNING* THIS MIGHT BREAK EXISTING APPS *WARNING* - Author and development information changes 0.53 Tue Mar 30 15:24:19 BST 2010 - fix authenticated urls to work with EU buckets (patch by Edmund von der Burg) - tiny POD fix (patch by Frank Wiegand) - add an exists method to Net::Amazon::S3::Client (suggested by David Golden) - fix max_keys when listing buckets (spotted by Andrew Bryan) - add content_encoding to Net::Amazon::S3::Object (suggested by Egor Korablev) - update s3cl: You need to use the module before you use it, added the mkbucket command, now you can run the help without your AWS secret key, add docs about the env variables you need to run s3cl (patches by Jesse Vincent) 0.52 Thu Jul 2 09:17:11 BST 2009 - increase version prerequisites for some modules so that they are known to work 0.51 Tue May 19 08:31:59 BST 2009 - use MooseX::Types::DateTimeX so that we work with latest Moose (noticed by Ted Zlatanov) 0.50 Wed Jan 21 10:42:00 GMT 2009 - add support for an expires header when putting an object to Net::Amazon::S3::Client::Object - make all the classes immutable - add query_string_authentication_uri() to Net::Amazon::S3::Client::Object, suggested by Meng Wong 0.49 Tue Jan 13 09:04:42 GMT 2009 - add support for listing a bucket with a prefix to Net::Amazon::S3::Client::Bucket 0.48 Thu Dec 4 09:24:23 GMT 2008 - be slightly less strict about bucket names: they can contain uppercase letters, Amazon just doesn't recommend it (noticed by Simon Elliott, fixes Brackup) 0.47 Tue Dec 2 08:03:39 GMT 2008 - fix listing with a prefix (spotted by Nobuo Danjou) 0.46 Mon Nov 24 08:53:18 GMT 2008 - refactor request creation into Net::Amazon::S3::Request and many subclasses - move to Moose - add Net::Amazon::S3::Client and subclasses 0.45 Wed Aug 20 17:06:49 BST 2008 - make add_key, head_key etc. return all the headers, not just the X-Amazon ones (patch by Andrew Hanenkamp) - require IO::File 1.14 (noticed by tsw) - remove DateTime::Format::Strptime prerequisite as it was not being used (noticed by Yen-Ming Lee) - do not try and parse non-XML errors (patch by lostlogic) - make it possible to store and delete the key "0" (patch by Joey Hess) - make it possible to store empty files (patch by BDOLAN) - add Copy support (patch by BDOLAN) - add s3cl for command-line access (patch by Leo Lapworth) 0.44 Thu Mar 27 08:35:59 GMT 2008 - fix bug with storing files consisting of "0" (thanks to Martin Atkins) 0.43 Sat Mar 1 10:55:54 GMT 2008 - add binmode() to support Windows (thanks to Gabriel Weinberg) 0.42 Thu Feb 28 06:39:59 GMT 2008 - add exponential backoff upon temporary errors with the new retry option 0.41 Fri Nov 30 10:42:26 GMT 2007 - fix the expensive tests (patch by BDOLAN) - added support for EU buckets (patch by BDOLAN) 0.40 Tue Oct 30 11:40:42 GMT 2007 - fix for content length with empty keys by Mark A. Hershberger - get_key and get_key_filename now return content_length - rewrote synopsis - added support for common prefix (thanks to Andy Grundman) 0.39 Sun Aug 19 14:47:01 BST 2007 - add add_key_filename and get_key_filename which send files directly from disk - good for large files (Jim Blomo) - support UTF8 keys (Jim Blomo) - switch back from Build.PL to Makefile.PL 0.38 Sun Mar 4 16:43:28 GMT 2007 - use http_proxy and https_proxy environment variables for proxy settings (Ask Bjoern Hansen) - don't add the Authorization header if one is already specified when making a request - good for allowing caching to resources that are public. (Ask Bjoern Hansen) 0.37 Fri Oct 13 19:14:57 BST 2006 - added support for ACLs (thanks to Gordon McCreight) 0.36 Sun Sep 10 16:30:39 BST 2006 - remove extra warning 0.35 Sun Sep 10 16:25:44 BST 2006 - added list_bucket_all to stop having to worrying about 'marker' 0.34 Sun Sep 10 07:27:06 BST 2006 - added next marker and more docs from Jesse Vincent 0.33 Sat Aug 26 16:26:37 BST 2006 - documentation and test cleanup from Jesse Vincent - use HTTP keep alive (patch by Scott Gifford) - remove ununused code in _make_request (patch by Scott Gifford) 0.32 Tue Apr 25 19:51:06 BST 2006 - fix bug with listing buckets with parameters (thanks to karjala) 0.31 Tue Apr 4 21:15:02 BST 2006 - many patches from Brad Fitzpatrick to make change the API, make return values sane, add err/errstr, make Bucket object - added a timeout option as suggested by Brad Dixon - it's the Brad release! 0.30 Mon Mar 20 20:20:29 GMT 2006 - initial release Net-Amazon-S3-0.991/bin/0000775000175000017500000000000014264646670013545 5ustar branobranoNet-Amazon-S3-0.991/bin/s3cl0000755000175000017500000003046614264646670014346 0ustar branobrano#!/usr/bin/env perl use strict; use warnings; use Getopt::Long; use Pod::Usage; use Path::Class; use File::Find::Rule; use Digest::MD5 qw(md5_hex); use Net::Amazon::S3; use MIME::Types qw(by_suffix); use Term::ProgressBar::Simple; # PODNAME: s3cl # ABSTRACT: Command line for Amazon s3 cloud storage my $s3; my %args; my %commands = ( mkbucket => \&mk_bucket, buckets => \&buckets, ls => \&ls, rm => \&rm, cp => \&cp, sync => \&sync, sync_up => \&sync_up, help => \&helper, ); main(); sub main { terminal(); get_options(); init_s3(); my $command = shift @ARGV || "help"; $commands{$command} or helper("Unknown command: $command"); $commands{$command}->(); } sub init_s3 { # TODO: read key_id and secret from config file? # use AppConfig; # TODO: probably nicer to put all of this in Net::Amazon::S3::CommandLine # and have simple call to that from here. my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'}; my $aws_secret_access_key = $ENV{'AWS_ACCESS_KEY_SECRET'}; $s3 = Net::Amazon::S3->new( { aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, retry => 1, } ); } sub sync { my $dest = $args{dest_or_source} || ''; helper("No destination supplied") if $dest eq ''; helper("Can not write to: $args{dest_or_source}") unless -w $dest; my $bucket = _get_bucket(); my $list = ls('data'); foreach my $key ( @{ $list->{keys} } ) { my $source = file( $key->{key} ); my $destination = file( $dest, $source ); $destination->dir->mkpath(); warn "$source -> $destination"; my $response = $bucket->get_key_filename( $source->stringify, 'GET', $destination->stringify ) or die $s3->err . ": " . $s3->errstr; } } sub sync_up { my $source = $args{dest_or_source} || ''; my $prefix = $args{prefix_or_key} || ''; my $acl_short = $args{acl_short}; helper("No source supplied") if $source eq ''; helper("Can not read directory: $args{dest_or_source}") unless -d $source; # Work out our local files my @files = File::Find::Rule->file()->in( ($source) ); my $progress = Term::ProgressBar::Simple->new( scalar(@files) ); my $bucket = _get_bucket(); # Get a list of all the remote files my $remote_file_list = $bucket->list_all( { prefix => $prefix } ) or die $s3->err . ": " . $s3->errstr; # Now hash, so we can look up a specific key to find the etag my %remote_files; foreach my $key_meta ( @{ $remote_file_list->{keys} } ) { my $key = $key_meta->{key}; $remote_files{$key} = $key_meta; } my $dir = dir($source); my $dir_string = $dir->stringify; my $mimetypes = MIME::Types->new; foreach my $f (@files) { my $file = file($f); my ( $mediatype, $encoding ) = by_suffix $file->basename(); # Assume plain text unless we can work i unless ($mediatype) { if ( -T $file ) { $mediatype = 'text/plain'; } else { $progress++; $progress->message("$f - NOT uploading"); warn "Not uploading: $file"; warn "Unknown mime type, submit patch to MIME::Types"; next; } } my $content = $file->slurp(); my $md5 = md5_hex($content); my $key = $file->stringify; $key =~ s/$dir_string//; # remove our local path for the dir $key =~ s{^/}{}; # remove the trailing slash $key = "$prefix$key"; # Add the prefix if there is one if ( my $remote = $remote_files{$key} ) { if ( $remote->{etag} eq $md5 ) { $progress->message("$key - $mediatype - not changed"); next; } } $bucket->add_key_filename( $key, $f, { content_type => $mediatype, }, ) or die $s3->err . ": " . $s3->errstr; if ($acl_short) { $bucket->set_acl( { key => $key, acl_short => $acl_short, } ) || die $s3->err . ": " . $s3->errstr; } $progress->message("$key - $mediatype - uploaded"); $progress++; } } sub cp { my $dest = $args{dest_or_source} || ''; helper("No destination supplied") if $dest eq ''; my $key = $args{prefix_or_key} || helper("No key supplied"); if ( -d $dest ) { # If we have a directory we need to add the file name $dest = file( $dest, file($key)->basename ); } my $bucket = _get_bucket(); unless ( $bucket->get_key_filename( "$key", 'GET', "$dest" ) ) { die $s3->err . ": " . $s3->errstr if $s3->err; die "Could not copy $key from bucket $args{bucket}"; } } sub ls { my $mode = shift || 'print'; my $bucket = _get_bucket(); my $ls_conf; $ls_conf->{prefix} = $args{prefix_or_key} if $args{prefix_or_key}; # list files in the bucket my $response = $bucket->list_all($ls_conf) or die $s3->err . ": " . $s3->errstr; return $response if $mode eq 'data'; foreach my $key ( @{ $response->{keys} } ) { my $key_last_modified = $key->{last_modified}; # 2008-07-14T22:31:10.000Z $key_last_modified =~ s/:\d{2}\.\d{3}Z$//; my $key_name = $key->{key}; my $key_size = $key->{size}; print "$key_size $key_last_modified $key_name\n"; } } sub rm { my $bucket = _get_bucket(); helper("Must have a :") unless $args{prefix_or_key}; my $res = "NO"; if ( $args{force} ) { $res = 'y'; } else { print "\nOnce deleted there is no way to retrieve this key again." . "\nAre you sure you want to delete $args{bucket}:$args{prefix_or_key}? y/N\n"; ( $res = ) =~ s/\n//; } if ( $res eq 'y' ) { # delete key in this bucket my $response = $bucket->delete_key( $args{prefix_or_key} ) or die $s3->err . ": " . $s3->errstr; } } sub mk_bucket { my $bucketname = $args{bucket}; my $bucket = $s3->add_bucket( { bucket => $bucketname, location_constraint => 'EU' } ) or die $s3->err . ": " . $s3->errstr; } sub buckets { my $response = $s3->buckets; my $num = scalar @{ $response->{buckets} || [] }; print "You have $num bucket"; print "s" if $num != 1; print ":\n"; foreach my $bucket ( @{ $response->{buckets} } ) { print '- ' . $bucket->bucket . "\n"; } } sub terminal { my $encoding = eval { require Term::Encoding; Term::Encoding::get_encoding(); } || "utf-8"; binmode STDOUT, ":encoding($encoding)"; } # TODO: Replace with AppConfig this is ick! sub get_options { my $help = 0; my $man = 0; my $force = 0; my $loc = "us-east-1"; my $bucket = ""; GetOptions( \%args, "bucket=s", "jurisdiction=s", "acl_short=s", "f|force" => \$force, "h|help|?" => \$help, "man" => \$man, ) or pod2usage(2); $args{force} = $force; foreach my $arg (@ARGV) { if ( $arg =~ /:/ ) { my ( $b, $rest ) = split( ":", $arg ); $args{bucket} = $b; $args{prefix_or_key} = $rest; } } # For cp / sync etc $args{dest_or_source} = $ARGV[2] if $ARGV[2]; pod2usage(1) if $help || @ARGV == 0; pod2usage( -verbose => 2 ) if $man; } sub _get_bucket { helper("No bucket supplied") unless $args{bucket}; my $bucket = $s3->bucket( $args{bucket} ); die $s3->err . ": " . $s3->errstr if $s3->err; helper("Could not get bucket $args{bucket}") unless $bucket; return $bucket; } sub helper { my $msg = shift; if ($msg) { pod2usage( -message => $msg, -exitval => 2 ); } exit; } =pod =encoding UTF-8 =head1 NAME s3cl - Command line for Amazon s3 cloud storage =head1 VERSION version 0.991 =head1 SYNOPSIS s3cl command [options] s3cl buckets s3cl mkbucket --bucket some_bucket_name --jurisdiction [EU|US] s3cl ls :[prefix] s3cl cp : /path/[filename] s3cl sync :[prefix] /path/ s3cl sync_up [--acl_short=public-read] :[prefix] /path/ s3cl rm : Options: -help brief help message -man full documentation We take NO responsibility for the costs incured through using this script. To run this script, you need to set a pair of environment variables: AWS_ACCESS_KEY_ID AWS_ACCESS_KEY_SECRET =head1 DESCRIPTION This program gives a command line interface to Amazons s3 storage service. It does not limit the number of requests (which may cost you more money than if you did it a different way!) and each request costs Money (although some costs from EC2 may be $0.0, check latest from Amazon costs page) - we take NO responsibility for your bill. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __DATA__ =head1 COMMANDS =over 4 =item B s3cl buckets List all buckets for this account. =item B s3cl mkbucket --bucket sombucketname [--jurisdiction [EU|US]] Create a new bucket, optionally specifying what jurisdiction it should be created in. =item B s3cl ls :[prefix] List contents of a bucket, the optional B can be partial, in which case all keys matching this as the start of the key name will be returned. If no B is supplied all keys of the bucket will be returned. =item B s3cl cp : target_file s3cl cp : target_directory Copy a single key from the bucket to the target file, or into the target_directory. =item B s3cl sync :[prefix] target_dir Downloads all files matching the prefix into a directory structure replicating that of the prefix and all 'sub-directories'. It will download ALL files - even if already on your local disk: http://www.amazon.com/gp/browse.html?node=16427261 # Data transfer "in" and "out" refers to transfer into and out # of Amazon S3. Data transferred between Amazon EC2 and # Amazon S3, is free of charge (i.e., $0.00 per GB), except # data transferred between Amazon EC2 and Amazon S3-Europe, # which will be charged at regular rates. =item B s3cl sync_up [--acl_short=public-read] :[prefix] /path/ Upload all the files below /path/ to S3, with an optional prefix at the start of the key name. The existing S3 files and meta data are fetched from S3 and the md5 (etag) is compaired to what is on the local disk, files are not upload if the content has not changed. Use --acl_short to set access control, options from L this is only applied when the file is uploaded. Each files content-type is worked out using L, if this does not match 'text/plain' is used for ASCII text files, otherwise a warning is issued and the file is NOT uploaded. Currently this does NOT remove old files from S3, and if there is any change to a file then the entire file will be reuploaded. =item B s3cl rm : Remove a key(file) from the bucket, removing a non-existent file is not classed as an error. Once removed the key (file) can not be restored - so use with care! =back =head1 ABOUT This module contains code modified from Amazon that contains the following notice (which is also applicicable to this code): # This software code is made available "AS IS" without # warranties of any kind. You may copy, display, modify and # redistribute the software code either by itself or as incorporated # into your code; provided that you do not remove any proprietary # notices. Your use of this software code is at your own risk and # you waive any claim against Amazon Digital Services, Inc. or its # affiliates with respect to your use of this software code. # (c) 2006 Amazon Digital Services, Inc. or its affiliates. =head1 AUTHOR Leo Lapworth - Part of the HinuHinu project =cut Net-Amazon-S3-0.991/cpanfile0000644000175000017500000000506214264646670014502 0ustar branobrano# This file is generated by Dist::Zilla::Plugin::CPANFile v6.025 # Do not edit this file directly. To change prereqs, edit the `dist.ini` file. requires "Carp" => "0"; requires "Data::Stream::Bulk::Callback" => "0"; requires "DateTime::Format::HTTP" => "0"; requires "Digest::HMAC_SHA1" => "0"; requires "Digest::MD5" => "0"; requires "Digest::MD5::File" => "0"; requires "Digest::SHA" => "0"; requires "Exporter::Tiny" => "0"; requires "File::Find::Rule" => "0"; requires "File::stat" => "0"; requires "Getopt::Long" => "0"; requires "HTTP::Date" => "0"; requires "HTTP::Response" => "0"; requires "HTTP::Status" => "0"; requires "Hash::Util" => "0"; requires "IO::File" => "1.14"; requires "LWP" => "6.03"; requires "LWP::UserAgent::Determined" => "0"; requires "MIME::Base64" => "0"; requires "MIME::Types" => "0"; requires "Moose" => "0.85"; requires "Moose::Meta::Class" => "0"; requires "Moose::Object" => "0"; requires "Moose::Role" => "0"; requires "Moose::Util" => "0"; requires "Moose::Util::TypeConstraints" => "0"; requires "MooseX::Role::Parameterized" => "0"; requires "MooseX::StrictConstructor" => "0.16"; requires "MooseX::Types::DateTime::MoreCoercions" => "0.07"; requires "Path::Class" => "0"; requires "Pod::Usage" => "0"; requires "Ref::Util" => "0"; requires "Regexp::Common" => "0"; requires "Safe::Isa" => "0"; requires "Scalar::Util" => "0"; requires "Sub::Override" => "0"; requires "Term::Encoding" => "0"; requires "Term::ProgressBar::Simple" => "0"; requires "Test::Deep" => "v0.111.0"; requires "Test::LWP::UserAgent" => "0"; requires "Test::More" => "0"; requires "Time::Piece" => "0"; requires "URI" => "0"; requires "URI::Escape" => "0"; requires "URI::QueryParam" => "0"; requires "XML::LibXML" => "0"; requires "XML::LibXML::XPathContext" => "0"; requires "constant" => "0"; requires "namespace::clean" => "0"; requires "parent" => "0"; requires "sort" => "0"; requires "strict" => "0"; requires "warnings" => "0"; recommends "VM::EC2::Security::CredentialCache" => "0"; on 'test' => sub { requires "File::Temp" => "0"; requires "FindBin" => "0"; requires "HTTP::Request" => "0"; requires "LWP::Simple" => "0"; requires "Test::Deep" => "v0.111.0"; requires "Test::Exception" => "0"; requires "Test::MockTime" => "0"; requires "Test::Warnings" => "0"; requires "lib" => "0"; requires "utf8" => "0"; requires "vars" => "0"; }; on 'configure' => sub { requires "ExtUtils::MakeMaker" => "0"; }; on 'configure' => sub { suggests "JSON::PP" => "2.27300"; }; on 'develop' => sub { requires "Test::EOL" => "0"; requires "Test::More" => "0.88"; }; Net-Amazon-S3-0.991/README.md0000644000175000017500000000436014264646670014255 0ustar branobrano# DESCRIPTION This module provides a Perlish interface to Amazon S3. From the developer blurb: "Amazon S3 is storage for the Internet. It is designed to make web-scale computing easier for developers. Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of web sites. The service aims to maximize benefits of scale and to pass those benefits on to developers". To find out more about S3, please visit: http://s3.amazonaws.com/ To use this module you will need to sign up to Amazon Web Services and provide an "Access Key ID" and " Secret Access Key". If you use this module, you will incurr costs as specified by Amazon. Please check the costs. If you use this module with your Access Key ID and Secret Access Key you must be responsible for these costs. I highly recommend reading all about S3, but in a nutshell data is stored in values. Values are referenced by keys, and keys are stored in buckets. Bucket names are global. Note: This is the legacy interface, please check out Net::Amazon::S3::Client instead. Development of this code happens here: https://github.com/rustyconover/net-amazon-s3 # LICENSE This module contains code modified from Amazon that contains the following notice: > This software code is made available "AS IS" without warranties of any > kind. You may copy, display, modify and redistribute the software > code either by itself or as incorporated into your code; provided that > you do not remove any proprietary notices. Your use of this software > code is at your own risk and you waive any claim against Amazon > Digital Services, Inc. or its affiliates with respect to your use of > this software code. (c) 2006 Amazon Digital Services, Inc. or its > affiliates. # AUTHOR * Leon Brocard and unknown Amazon Digital Services programmers. * Brad Fitzpatrick - return values, Bucket object. * Pedro Figueiredo - since 0.54. * Rusty Conover - since 0.80. * Leo Lapworth - since 0.81Net-Amazon-S3-0.991/lib/0000775000175000017500000000000014264646670013543 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/0000775000175000017500000000000014264646670014271 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/0000775000175000017500000000000014264646670015516 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/0000775000175000017500000000000014264646670016003 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Vendor/0000775000175000017500000000000014264646670017240 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Vendor/Generic.pm0000644000175000017500000000167214264646670021156 0ustar branobranopackage Net::Amazon::S3::Vendor::Generic; $Net::Amazon::S3::Vendor::Generic::VERSION = '0.991'; use Moose 0.85; # ABSTRACT: Generic S3 vendor extends 'Net::Amazon::S3::Vendor'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Vendor::Generic - Generic S3 vendor =head1 VERSION version 0.991 =head1 SYNOPSIS my $s3 = Net::Amazon::S3->new ( vendor => Net::Amazon::S3::Vendor::Generic->new ( host => ..., use_https => ...', use_virtual_host => ..., authorization_method => ..., default_region => ..., ), ... ); =head1 DESCRIPTION =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Vendor/Amazon.pm0000644000175000017500000000246414264646670021027 0ustar branobranopackage Net::Amazon::S3::Vendor::Amazon; $Net::Amazon::S3::Vendor::Amazon::VERSION = '0.991'; use Moose 0.85; # ABSTRACT: Amazon AWS specific behaviour extends 'Net::Amazon::S3::Vendor'; use Net::Amazon::S3::Signature::V4; has '+host' => ( default => 's3.amazonaws.com', ); has '+authorization_method' => ( default => sub { 'Net::Amazon::S3::Signature::V4' }, ); sub guess_bucket_region { my ($self, $bucket) = @_; $bucket->_head_region; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Vendor::Amazon - Amazon AWS specific behaviour =head1 VERSION version 0.991 =head1 SYNOPSIS my $s3 = Net::Amazon::S3->new ( vendor => Net::Amazon::S3::Vendor::Amazon->new, ... ); =head1 DESCRIPTION Amazon AWS vendor specification. Supports all L<< Net::Amazon::S3::Vendor >> constructor parameters although usually there is no reason to change it :-) Guess bucket region implementation uses bucket's HEAD region request. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request.pm0000644000175000017500000001145514264646670017775 0ustar branobranopackage Net::Amazon::S3::Request; $Net::Amazon::S3::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use Moose::Util::TypeConstraints; use Regexp::Common qw /net/; # ABSTRACT: Base class for request objects use Net::Amazon::S3::Constraint::ACL::Canned; enum 'LocationConstraint' => [ # https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region # https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html#API_CreateBucket_RequestSyntax 'af-south-1', 'ap-east-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-northeast-3', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'cn-north-1', 'cn-northwest-1', 'EU', 'eu-central-1', 'eu-north-1', 'eu-south-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'me-south-1', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-gov-east-1', 'us-gov-west-1', 'us-west-1', 'us-west-2', ]; subtype 'MaybeLocationConstraint' => as 'Maybe[LocationConstraint]' ; # maintain backward compatiblity with 'US' and 'EU' values my %location_constraint_alias = ( US => 'us-east-1', EU => 'eu-west-1', ); enum 'LocationConstraintAlias' => [ keys %location_constraint_alias ]; coerce 'LocationConstraint' => from 'LocationConstraintAlias' => via { $location_constraint_alias{$_} } ; coerce 'MaybeLocationConstraint' => from 'LocationConstraintAlias' => via { $location_constraint_alias{$_} } ; # To comply with Amazon S3 requirements, bucket names must: # Contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-) # Start with a number or letter # Be between 3 and 255 characters long # Not be in an IP address style (e.g., "192.168.5.4") subtype 'BucketName1' => as 'Str' => where { $_ =~ /^[a-zA-Z0-9._-]+$/; } => message { "Bucket name ($_) must contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)"; }; subtype 'BucketName2' => as 'BucketName1' => where { $_ =~ /^[a-zA-Z0-9]/; } => message { "Bucket name ($_) must start with a number or letter"; }; subtype 'BucketName3' => as 'BucketName2' => where { length($_) >= 3 && length($_) <= 255; } => message { "Bucket name ($_) must be between 3 and 255 characters long"; }; subtype 'BucketName' => as 'BucketName3' => where { $_ !~ /^$RE{net}{IPv4}$/; } => message { "Bucket name ($_) must not be in an IP address style (e.g., '192.168.5.4')"; }; has 's3' => ( is => 'ro', isa => 'Net::Amazon::S3', required => 1 ); has '_http_request_content' => ( is => 'ro', init_arg => undef, isa => 'Maybe[Str]', lazy => 1, builder => '_request_content', ); __PACKAGE__->meta->make_immutable; sub _request_content { ''; } sub _request_path { ''; } sub _request_headers { } sub _request_query_action { } sub _request_query_params { } sub _request_query_string { my ($self) = @_; my %query_params = $self->_request_query_params; my @parts = ( ($self->_request_query_action) x!! $self->_request_query_action, map "$_=${\ $self->s3->_urlencode( $query_params{$_} ) }", sort keys %query_params, ); return '' unless @parts; return '?' . join '&', @parts; } sub _http_request_path { my ($self) = @_; return $self->_request_path . $self->_request_query_string; } sub _http_request_headers { my ($self) = @_; return +{ $self->_request_headers }; } sub _build_signed_request { my ($self, %params) = @_; $params{path} = $self->_http_request_path unless exists $params{path}; $params{method} = $self->_http_request_method unless exists $params{method}; $params{headers} = $self->_http_request_headers unless exists $params{headers}; $params{content} = $self->_http_request_content unless exists $params{content} or ! defined $self->_http_request_content; # Although Amazon's Signature 4 test suite explicitely handles // it appears # it's inconsistent with their implementation so removing it here $params{path} =~ s{//+}{/}g; return Net::Amazon::S3::HTTPRequest->new( %params, s3 => $self->s3, $self->can( 'bucket' ) ? (bucket => $self->bucket) : (), ); } sub _build_http_request { my ($self, %params) = @_; return $self->_build_signed_request( %params )->http_request; } sub http_request { my $self = shift; return $self->_build_http_request; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request - Base class for request objects =head1 VERSION version 0.991 =head1 SYNOPSIS # do not instantiate directly =head1 DESCRIPTION This module is a base class for all the Net::Amazon::S3::Request::* classes. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Bucket.pm0000644000175000017500000004620314264646670017561 0ustar branobranopackage Net::Amazon::S3::Bucket; # ABSTRACT: convenience object for working with Amazon S3 buckets $Net::Amazon::S3::Bucket::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use Carp; use File::stat; use IO::File 1.14; has 'account' => ( is => 'ro', isa => 'Net::Amazon::S3', required => 1, handles => [qw[ err errstr ]], ); has 'bucket' => ( is => 'ro', isa => 'Str', required => 1 ); has 'creation_date' => ( is => 'ro', isa => 'Maybe[Str]', required => 0 ); has 'region' => ( is => 'ro', lazy => 1, predicate => 'has_region', default => sub { return $_[0]->account->vendor->guess_bucket_region ($_[0]); }, ); __PACKAGE__->meta->make_immutable; # returns bool sub add_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'value']); my $key = delete $args{key}; my $value = delete $args{value}; if ( ref($value) eq 'SCALAR' ) { $args{'Content-Length'} ||= -s $$value; $value = _content_sub($$value); } else { $args{'Content-Length'} ||= length $value; } my $acl; $acl = delete $args{acl_short} if exists $args{acl_short}; $acl = delete $args{acl} if exists $args{acl}; my $encryption = delete $args{encryption}; my %headers = %args; # we may get a 307 redirect; ask server to signal 100 Continue # before reading the content from CODE reference (_content_sub) $headers{expect} = '100-continue' if ref $value; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Add', key => $key, value => $value, (acl => $acl) x!! defined $acl, ((encryption => $encryption) x!! defined $encryption), headers => \%headers, ); return $response->is_success; } sub add_key_filename { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'value']); $args{value} = \ delete $args{value}; return $self->add_key (%args); } sub copy_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'source' ]); my $key = delete $args{key}; my $source = delete $args{source}; my $acl_short; if (%args) { if ( $args{acl_short} ) { $acl_short = $args{acl_short}; delete $args{acl_short}; } $args{Net::Amazon::S3::Constants->HEADER_METADATA_DIRECTIVE} ||= 'REPLACE'; } $args{Net::Amazon::S3::Constants->HEADER_COPY_SOURCE} = $source; my $encryption = delete $args{encryption}; my $acct = $self->account; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Add', value => '', key => $key, acl_short => $acl_short, (encryption => $encryption) x!! defined $encryption, headers => \%args, ); return unless $response->is_success; } sub edit_metadata { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); my $key = delete $args{key}; croak "Need some metadata to change" unless %args; return $self->copy_key ( key => $key, source => "/" . $self->bucket . "/" . $key, %args, ); } sub head_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); return $self->get_key (%args, method => 'HEAD', filename => undef); } sub query_string_authentication_uri { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'expires_at']); $args{method} = 'GET' unless exists $args{method}; my $request = Net::Amazon::S3::Operation::Object::Fetch::Request->new ( s3 => $self->account, bucket => $self, key => $args{key}, method => $args{method}, ); return $request->query_string_authentication_uri ($args{expires_at}); } sub get_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'method', 'filename']); $args{filename} = ${ delete $args{filename} } if ref $args{filename}; $args{method} ||= 'GET'; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Fetch', filename => $args{filename}, (range => $args{range}) x defined $args{range}, key => $args{key}, method => $args{method}, ); return unless $response->is_success; my $etag = $response->etag; my $return; foreach my $header ($response->headers->header_field_names) { $return->{ lc $header } = $response->header ($header); } $return->{content_length} = $response->content_length || 0; $return->{content_type} = $response->content_type; $return->{etag} = $etag; $return->{value} = $response->content; return $return; } sub get_key_filename { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_, ['key', 'method', 'filename']); $args{filename} = \ delete $args{filename}; return $self->get_key (%args); } # returns bool sub delete_multi_object { my $self = shift; my @objects = @_; return unless( scalar(@objects) ); # Since delete can handle up to 1000 requests, be a little bit nicer # and slice up requests and also allow keys to be strings # rather than only objects. my $last_result; while (scalar(@objects) > 0) { my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Objects::Delete', keys => [ map { ref ($_) ? $_->key : $_ } splice @objects, 0, ((scalar(@objects) > 1000) ? 1000 : scalar(@objects)) ] ); return unless $response->is_success; } return 1; } sub delete_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); croak 'must specify key' unless defined $args{key} && length $args{key}; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Delete', %args, ); return $response->is_success; } sub delete_bucket { my $self = shift; return $self->account->delete_bucket (bucket => $self, @_); } sub list { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_); return $self->account->list_bucket ($self, %args); } sub list_all { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_); return $self->account->list_bucket_all ($self, %args); } sub get_acl { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); my $response; if (defined $args{key}) { $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Acl::Fetch', %args, ); } else { delete $args{key}; $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Acl::Fetch', %args, ); } return unless $response->is_success; return $response->content; } sub set_acl { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); my $response; if (defined $args{key}) { $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Acl::Set', %args, ); } else { delete $args{key}; $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Acl::Set', %args, ); } return unless $response->is_success; return 1; } sub get_location_constraint { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments (\@_); my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Location', %args, ); return unless $response->is_success; return $response->location; } sub add_tags { my $self = shift; my %args = @_ == 1 ? %{ $_[0] } : @_; my $response; if (defined $args{key}) { $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Tags::Add', %args, ); } else { delete $args{key}; $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Tags::Add', %args, ); } return $response->is_success; } sub delete_tags { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_object (\@_); my $response; if (defined $args{key}) { $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Tags::Delete', %args, ); } else { delete $args{key}; $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Tags::Delete', %args, ); } return $response->is_success; } sub _content_sub { my $filename = shift; my $stat = stat($filename); my $remaining = $stat->size; my $blksize = $stat->blksize || 4096; croak "$filename not a readable file with fixed size" unless -r $filename and ( -f _ || $remaining ); my $fh = IO::File->new( $filename, 'r' ) or croak "Could not open $filename: $!"; $fh->binmode; return sub { my $buffer; # upon retries the file is closed and we must reopen it unless ( $fh->opened ) { $fh = IO::File->new( $filename, 'r' ) or croak "Could not open $filename: $!"; $fh->binmode; $remaining = $stat->size; } # warn "read remaining $remaining"; unless ( my $read = $fh->read( $buffer, $blksize ) ) { # warn "read $read buffer $buffer remaining $remaining"; croak "Error while reading upload content $filename ($remaining remaining) $!" if $! and $remaining; # otherwise, we found EOF $fh->close or croak "close of upload content $filename failed: $!"; $buffer ||= '' ; # LWP expects an emptry string on finish, read returns 0 } $remaining -= length($buffer); return $buffer; }; } sub _head_region { my ($self) = @_; my $protocol = $self->account->secure ? 'https' : 'http'; my $host = $self->account->host; my $path = $self->bucket; my @retry = (1, 2, (4) x 8); if ($self->account->use_virtual_host) { $host = "$path.$host"; $path = ''; } my $request_uri = "${protocol}://${host}/$path"; while (@retry) { my $request = HTTP::Request->new (HEAD => $request_uri); # Disable redirects my $requests_redirectable = $self->account->ua->requests_redirectable; $self->account->ua->requests_redirectable( [] ); my $response = $self->account->ua->request ($request); $self->account->ua->requests_redirectable( $requests_redirectable ); return $response->header (Net::Amazon::S3::Constants->HEADER_BUCKET_REGION) if $response->header (Net::Amazon::S3::Constants->HEADER_BUCKET_REGION); print STDERR "Invalid bucket head response; $request_uri\n"; print STDERR $response->as_string; sleep shift @retry; } die "Cannot determine bucket region; bucket=${\ $self->bucket }"; } sub _perform_operation { my ($self, $operation, %params) = @_; $self->account->_perform_operation ($operation => ( bucket => $self, %params, )); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Bucket - convenience object for working with Amazon S3 buckets =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3; my $bucket = $s3->bucket("foo"); ok($bucket->add_key("key", "data")); ok($bucket->add_key("key", "data", { content_type => "text/html", 'x-amz-meta-colour' => 'orange', })); # Enable server-side encryption ok($bucket->add_key("key", "data", { encryption => 'AES256', })); # the err and errstr methods just proxy up to the Net::Amazon::S3's # objects err/errstr methods. $bucket->add_key("bar", "baz") or die $bucket->err . $bucket->errstr; # fetch a key $val = $bucket->get_key("key"); is( $val->{value}, 'data' ); is( $val->{content_type}, 'text/html' ); is( $val->{etag}, 'b9ece18c950afbfa6b0fdbfa4ff731d3' ); is( $val->{'x-amz-meta-colour'}, 'orange' ); # fetch a part of the key $val = $bucket->get_key("key", { range => "bytes=1024-10240" }); # returns undef on missing or on error (check $bucket->err) is(undef, $bucket->get_key("non-existing-key")); die $bucket->errstr if $bucket->err; # fetch a key's metadata $val = $bucket->head_key("key"); is( $val->{value}, '' ); is( $val->{content_type}, 'text/html' ); is( $val->{etag}, 'b9ece18c950afbfa6b0fdbfa4ff731d3' ); is( $val->{'x-amz-meta-colour'}, 'orange' ); # delete a key ok($bucket->delete_key($key_name)); ok(! $bucket->delete_key("non-exist-key")); # delete the entire bucket (Amazon requires it first be empty) $bucket->delete_bucket; =head1 DESCRIPTION This module represents an S3 bucket. You get a bucket object from the Net::Amazon::S3 object. =head1 METHODS =head2 new Create a new bucket object. Expects a hash containing these two arguments: =over =item bucket =item account =back =head2 add_key Takes three positional parameters: =over =item key =item value =item configuration A hash of configuration data for this key. =over =item acl =item encryption =item any additional HTTP header =back See L for details =back Returns a boolean. =head2 add_key_filename Use this to upload a large file to S3. Takes three positional parameters: =over =item key =item filename =item configuration A hash of configuration data for this key. (See synopsis); =back Returns a boolean. =head2 copy_key Creates (or replaces) a key, copying its contents from another key elsewhere in S3. Takes the following parameters: =over =item key The key to (over)write =item source Where to copy the key from. Should be in the form C/I>/. =item conf Optional configuration hash. If present and defined, the configuration (ACL and headers) there will be used for the new key; otherwise it will be copied from the source key. =back =head2 edit_metadata Changes the metadata associated with an existing key. Arguments: =over =item key The key to edit =item conf The new configuration hash to use =back =head2 head_key KEY Takes the name of a key in this bucket and returns its configuration hash =head2 query_string_authentication_uri KEY, EXPIRES_AT my $uri = $bucket->query_string_authentication_uri ( key => 'foo', expires_at => time + 3_600, # valid for one hour ); my $uri = $bucket->query_string_authentication_uri ( key => 'foo', expires_at => time + 3_600, method => 'PUT', ); Returns uri presigned with your credentials. When used with Signature V4 you have to specify also HTTP method this presigned uri will be used for (default: C) Method provides authenticated uri only for direct object operations. Method follows API's L. Recognized positional arguments (mandatory). =over =item key =item expires_at Expiration time (epoch time). =back Optional arguments =over =item method Default: C Intended HTTP method this uri will be presigned for. Signature V2 doesn't use it but Signature V4 does. See L =back =head2 get_key $key_name [$method] Takes a key name and an optional HTTP method (which defaults to C. Fetches the key from AWS. On failure: Returns undef on missing content, throws an exception (dies) on server errors. On success: Returns a hashref of { content_type, etag, value, @meta } on success. Other values from the server are there too, with the key being lowercased. =head2 get_key_filename $key_name $method $filename Use this to download large files from S3. Takes a key name and an optional HTTP method (which defaults to C. Fetches the key from AWS and writes it to the filename. THe value returned will be empty. On failure: Returns undef on missing content, throws an exception (dies) on server errors. On success: Returns a hashref of { content_type, etag, value, @meta } on success =head2 delete_key $key_name Removes C<$key> from the bucket. Forever. It's gone after this. Returns true on success and false on failure =head2 delete_bucket Delete the current bucket object from the server. Takes no arguments. Fails if the bucket has anything in it. This is an alias for C<< $s3->delete_bucket($bucket) >> =head2 list List all keys in this bucket. see L for documentation of this method. =head2 list_all List all keys in this bucket without having to worry about 'marker'. This may make multiple requests to S3 under the hood. see L for documentation of this method. =head2 get_acl Takes one optional positional parameter =over =item key (optional) If no key is specified, it returns the acl for the bucket. =back Returns an acl in XML format. =head2 set_acl Takes a configuration hash_ref containing: =over =item acl_xml (cannot be used in conjunction with acl_short) An XML string which contains access control information which matches Amazon's published schema. There is an example of one of these XML strings in the tests for this module. =item acl_short (cannot be used in conjunction with acl_xml) You can use the shorthand notation instead of specifying XML for certain 'canned' types of acls. (from the Amazon API documentation) private: Owner gets FULL_CONTROL. No one else has any access rights. This is the default. public-read:Owner gets FULL_CONTROL and the anonymous principal is granted READ access. If this policy is used on an object, it can be read from a browser with no authentication. public-read-write:Owner gets FULL_CONTROL, the anonymous principal is granted READ and WRITE access. This is a useful policy to apply to a bucket, if you intend for any anonymous user to PUT objects into the bucket. authenticated-read:Owner gets FULL_CONTROL, and any principal authenticated as a registered Amazon S3 user is granted READ access. =item key (optional) If the key is not set, it will apply the acl to the bucket. =back Returns a boolean. =head2 get_location_constraint Retrieves the location constraint set when the bucket was created. Returns a string (eg, 'EU'), or undef if no location constraint was set. =head2 err The S3 error code for the last error the object ran into =head2 errstr A human readable error string for the last error the object ran into =head2 add_tags # Add tags for a bucket $s3->add_tags ({ bucket => 'bucket-name', tags => { tag1 => 'value-1', tag2 => 'value-2' }, }); # Add tags for an object $s3->add_tags ({ bucket => 'bucket-name', key => 'key', tags => { tag1 => 'value-1', tag2 => 'value-2' }, }); Takes configuration parameters =over =item key (optional, scalar) If key is specified, add tag(s) to object, otherwise on bucket. =item tags (mandatory, hashref) Set specified tags and their respective values. =item version_id (optional) Is specified (in conjunction with C) add tag(s) to versioned object. =back Returns C on success. Returns C and sets C/C otherwise. =head2 delete_tags # Add tags for a bucket $s3->delete_tags ({ bucket => 'bucket-name', }); # Add tags for an object $s3->delete_tags ({ bucket => 'bucket-name', key => 'key', version_id => $version_id, }); Takes configuration parameters =over =item key (optional, scalar) If key is specified, add tag(s) to object, otherwise on bucket. =item version_id (optional) Is specified (in conjunction with C) add tag(s) to versioned object. =back Returns C on success. Returns C and sets C/C otherwise. =head1 SEE ALSO L =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Constants.pm0000644000175000017500000000333714264646670020321 0ustar branobranopackage Net::Amazon::S3::Constants; # ABSTRACT: Misc constants used by S3 $Net::Amazon::S3::Constants::VERSION = '0.991'; use constant { HEADER_BUCKET_REGION => 'x-amz-bucket-region', HEADER_CANNED_ACL => 'x-amz-acl', HEADER_COPY_SOURCE => 'x-amz-copy-source', HEADER_DATE => 'x-amz-date', HEADER_DELETE_MARKER => 'x-amz-delete-marker', HEADER_GRANT_FULL_CONTROL => 'x-amz-grant-full-control', HEADER_GRANT_READ => 'x-amz-grant-read', HEADER_GRANT_READ_ACP => 'x-amz-grant-read-acp', HEADER_GRANT_WRITE => 'x-amz-grant-write', HEADER_GRANT_WRITE_ACP => 'x-amz-grant-write-acp', HEADER_ID_2 => 'x-amz-id-2', HEADER_METADATA_DIRECTIVE => 'x-amz-metadata-directive', HEADER_REQUEST_ID => 'x-amz-request-id', HEADER_SERVER_ENCRYPTION => 'x-amz-server-side-encryption', HEADER_VERSION_ID => 'x-amz-version-id', S3_NAMESPACE_URI => 'http://s3.amazonaws.com/doc/2006-03-01/', }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Constants - Misc constants used by S3 =head1 VERSION version 0.991 =head1 DESCRIPTION Module provides misc Amazon S3 string constants as symbols. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL.pod0000644000175000017500000000424114264646670017105 0ustar branobrano# ABSTRACT: Amazon S3 ACL support # PODNAME: Net::Amazon::S3::ACL __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::ACL - Amazon S3 ACL support =head1 VERSION version 0.991 =head1 DESCRIPTION Every S3 action supporting ACL specification in request supports C parameter. Parameter is backward compatible with former C. =over =item canned ACL $s3->action ( acl => Net::Amazon::S3::ACL::Canned->PRIVATE, ); Amazon S3 predefined grants are provided by builder methods, each representing corresponding canned ACL. =over =item PRIVATE =item PUBLIC_READ =item PUBLIC_READ_WRITE =item AWS_EXEC_READ =item AUTHENTICATED_READ =item BUCKET_OWNER_READ =item BUCKET_OWNER_FULL_CONTROL =item LOG_DELIVERY_WRITE =back See L for implementation details. See L in Amazon documentation. =item canned ACL (coerced) $s3->action ( acl => 'private', ); Earlier versions of L supported only textual canned ACL. To not break code that use it coercion to L is supported as well as C operation argument. C is deprecated now, only C is supported. C behaves like an C alias. In case when both are defined, C takes precedence. =item exact ACL set $s3->action ( acl => Net::Amazon::S3::ACL::Set ->grant_read (id => $canonical_user_id) ->grant_full_control (email => $email_address) , ); Exact ACL set provides interface to C header fields. See L for implementation details. =back =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Client.pm0000644000175000017500000001417114264646670017561 0ustar branobranopackage Net::Amazon::S3::Client; # ABSTRACT: An easy-to-use Amazon S3 client $Net::Amazon::S3::Client::VERSION = '0.991'; use Moose 0.85; use HTTP::Status qw(status_message); use MooseX::StrictConstructor 0.16; use Moose::Util::TypeConstraints; use Net::Amazon::S3; use Net::Amazon::S3::Constraint::Etag; use Net::Amazon::S3::Error::Handler::Confess; has 's3' => ( is => 'ro', isa => 'Net::Amazon::S3', required => 1, handles => [ 'ua', ], ); has error_handler_class => ( is => 'ro', lazy => 1, default => 'Net::Amazon::S3::Error::Handler::Confess', ); has error_handler => ( is => 'ro', lazy => 1, default => sub { $_[0]->error_handler_class->new (s3 => $_[0]->s3) }, ); has bucket_class => ( is => 'ro', init_arg => undef, lazy => 1, default => 'Net::Amazon::S3::Client::Bucket', ); around BUILDARGS => sub { my ($orig, $class) = (shift, shift); my $args = $class->$orig (@_); unless (exists $args->{s3}) { my $error_handler_class = delete $args->{error_handler_class}; my $error_handler = delete $args->{error_handler}; $args = { (error_handler_class => $error_handler_class) x!! defined $error_handler_class, (error_handler => $error_handler ) x!! defined $error_handler, s3 => Net::Amazon::S3->new ($args), } } $args; }; __PACKAGE__->meta->make_immutable; sub buckets { my $self = shift; my $s3 = $self->s3; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Buckets::List', ); return unless $response->is_success; my $owner_id = $response->owner_id; my $owner_display_name = $response->owner_displayname; my @buckets; foreach my $bucket ($response->buckets) { push @buckets, $self->bucket_class->new ( client => $self, name => $bucket->{name}, creation_date => $bucket->{creation_date}, owner_id => $owner_id, owner_display_name => $owner_display_name, ); } return @buckets; } sub create_bucket { my ( $self, %conf ) = @_; my $bucket = $self->bucket_class->new( client => $self, name => $conf{name}, ); $bucket->_create(%conf); return $bucket; } sub bucket { my ( $self, %conf ) = @_; return $self->bucket_class->new( client => $self, %conf, ); } sub _perform_operation { my ($self, $operation, %params) = @_; return $self->s3->_perform_operation ( $operation, error_handler => $self->error_handler, %params ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Client - An easy-to-use Amazon S3 client =head1 VERSION version 0.991 =head1 SYNOPSIS # Build Client instance my $client = Net::Amazon::S3::Client->new ( # accepts all Net::Amazon::S3's arguments aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, retry => 1, ); # or reuse an existing S3 connection my $client = Net::Amazon::S3::Client->new (s3 => $s3); # list all my buckets # returns a list of L objects my @buckets = $client->buckets; foreach my $bucket (@buckets) { print $bucket->name . "\n"; } # create a new bucket # returns a L object my $bucket = $client->create_bucket( name => $bucket_name, acl_short => 'private', location_constraint => 'us-east-1', ); # or use an existing bucket # returns a L object my $bucket = $client->bucket( name => $bucket_name ); =head1 DESCRIPTION The L module was written when the Amazon S3 service had just come out and it is a light wrapper around the APIs. Some bad API decisions were also made. The L, L and L classes are designed after years of usage to be easy to use for common tasks. These classes throw an exception when a fatal error occurs. It also is very careful to pass an MD5 of the content when uploaded to S3 and check the resultant ETag. WARNING: This is an early release of the Client classes, the APIs may change. =for test_synopsis no strict 'vars' =head1 CONSTRUCTOR =over =item s3 L<< Net::Amazon::S3 >> instance =item error_handler_class Error handler class name (package name), see L<< Net::Amazon::S3::Error::Handler >> for more. Overrides one available in C. Default: L<< Net::Amazon::S3::Error::Handler::Confess >> =item error_handler Instance of error handler class. =back =head1 METHODS =head2 new L can be constructed two ways. Historically it wraps S3 API instance use Net::Amazon::S3::Client; my $client = Net::Amazon::S3::Client->new ( s3 => .... # Net::Amazon::S3 instance ); =head2 new (since v0.92) Since v0.92 explicit creation of S3 API instance is no longer necessary. L's constructor accepts same parameters as L use Net::Amazon::S3::Client v0.92; my $client = Net::Amazon::S3::Client->new ( aws_access_key_id => ..., aws_secret_access_key => ..., ..., ); =head2 buckets # list all my buckets # returns a list of L objects my @buckets = $client->buckets; foreach my $bucket (@buckets) { print $bucket->name . "\n"; } =head2 create_bucket # create a new bucket # returns a L object my $bucket = $client->create_bucket( name => $bucket_name, acl_short => 'private', location_constraint => 'us-east-1', ); =head2 bucket # or use an existing bucket # returns a L object my $bucket = $client->bucket( name => $bucket_name ); =head2 bucket_class # returns string "Net::Amazon::S3::Client::Bucket" # subclasses will want to override this. my $bucket_class = $client->bucket_class =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Error/0000775000175000017500000000000014264646670017074 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Error/Handler.pm0000644000175000017500000000214114264646670021003 0ustar branobranopackage Net::Amazon::S3::Error::Handler; $Net::Amazon::S3::Error::Handler::VERSION = '0.991'; use Moose; # ABSTRACT: A base class for S3 response error handler has s3 => ( is => 'ro', isa => 'Net::Amazon::S3', required => 1, ); sub handle_error; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Error::Handler - A base class for S3 response error handler =head1 VERSION version 0.991 =head1 CONSTRUCTOR =over =item s3 Instance of L<< Net::Amazon::S3 >> =back =head1 METHODS =head2 handle_error ($response) =head2 handle_error ($response, $request) Method will receive instance of L<< Net::Amazon::S3::Response >> sub-class. Method should return false (or throw exception) in case of error, true otherwise. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Error/Handler/0000775000175000017500000000000014264646670020451 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Error/Handler/Confess.pm0000644000175000017500000000271714264646670022414 0ustar branobranopackage Net::Amazon::S3::Error::Handler::Confess; $Net::Amazon::S3::Error::Handler::Confess::VERSION = '0.991'; # ABSTRACT: An internal class to report errors via Carp::confess use Moose; use Carp; use HTTP::Status; extends 'Net::Amazon::S3::Error::Handler'; our @CARP_NOT = (__PACKAGE__); my %return_false = ( NoSuchKey => { 'Net::Amazon::S3::Operation::Object::Head::Response' => 1, }, NoSuchBucket => { 'Net::Amazon::S3::Operation::Object::Head::Response' => 1, }, '404' => { 'Net::Amazon::S3::Operation::Object::Head::Response' => 1, }, ); sub handle_error { my ($self, $response) = @_; return 1 unless $response->is_error; return 0 if exists $return_false{ $response->error_code } && exists $return_false{ $response->error_code }{ ref $response } ; Carp::confess ("${\ $response->error_code }: ${\ $response->error_message }"); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Error::Handler::Confess - An internal class to report errors via Carp::confess =head1 VERSION version 0.991 =head1 DESCRIPTION Carp::confess on error. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Error/Handler/Legacy.pm0000644000175000017500000000332214264646670022211 0ustar branobranopackage Net::Amazon::S3::Error::Handler::Legacy; $Net::Amazon::S3::Error::Handler::Legacy::VERSION = '0.991'; # ABSTRACT: An internal class to report errors like legacy API use Moose; extends 'Net::Amazon::S3::Error::Handler::Status'; use HTTP::Status; our @CARP_NOT = __PACKAGE__; my %croak_on_response = map +($_ => 1), ( 'Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Response', 'Net::Amazon::S3::Operation::Object::Acl::Fetch::Response', 'Net::Amazon::S3::Operation::Object::Fetch::Response', ); override handle_error => sub { my ($self, $response, $request) = @_; return super unless exists $croak_on_response{ref $response}; $self->s3->err (undef); $self->s3->errstr (undef); return 1 unless $response->is_error; return 0 if $response->http_response->code == HTTP::Status::HTTP_NOT_FOUND; $self->s3->err ("network_error"); $self->s3->errstr ($response->http_response->status_line); Carp::croak ("Net::Amazon::S3: Amazon responded with ${\ $self->s3->errstr }\n"); }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Error::Handler::Legacy - An internal class to report errors like legacy API =head1 VERSION version 0.991 =head1 DESCRIPTION Handle errors like L API does. Carp::croak in case of I, I, and I. set C / C only otherwise. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Error/Handler/Status.pm0000644000175000017500000000220414264646670022266 0ustar branobranopackage Net::Amazon::S3::Error::Handler::Status; $Net::Amazon::S3::Error::Handler::Status::VERSION = '0.991'; # ABSTRACT: An internal class to report response errors via err properties use Moose; extends 'Net::Amazon::S3::Error::Handler'; sub handle_error { my ($self, $response) = @_; $self->s3->err (undef); $self->s3->errstr (undef); return 1 unless $response->is_error; $self->s3->err ($response->error_code); $self->s3->errstr ($response->error_message); return 0; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Error::Handler::Status - An internal class to report response errors via err properties =head1 VERSION version 0.991 =head1 DESCRIPTION Propagate error code and error message via connection's C / C methods. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Error/Handler/X.pm0000644000175000017500000000276414264646670021225 0ustar branobranopackage Net::Amazon::S3::Error::Handler::X; $Net::Amazon::S3::Error::Handler::X::VERSION = '0.991'; # ABSTRACT: Throw error specific exception use Moose; extends 'Net::Amazon::S3::Error::Handler'; use Net::Amazon::S3::X; override handle_error => sub { my ($self, $response, $request) = @_; return 1 unless $response->is_error; my $exception = Net::Amazon::S3::X->build ( $response->error_code, request => $request, response => $response, ); die $exception; }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Error::Handler::X - Throw error specific exception =head1 VERSION version 0.991 =head1 DESCRIPTION Raise error specific exception. =head2 S3 error For S3 errors exception it raises is instance of C. AWS error code list can be found at L my $s3 = Net::Amazon::S3->new ( error_handler_class => 'Net::Amazon::S3::Error::Handler::X', ... ); eval { do s3 operation; 1 } or do { say 'access denied' if $@->$Safe::Isa::_isa ('Net::Amazon::S3::X::AccessDenied'); ... }; =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Signature.pm0000644000175000017500000000473414264646670020310 0ustar branobranopackage Net::Amazon::S3::Signature; # ABSTRACT: S3 Signature implementation base class $Net::Amazon::S3::Signature::VERSION = '0.991'; use Moose; has http_request => ( is => 'ro', isa => 'Net::Amazon::S3::HTTPRequest', ); sub _append_authorization_headers { my ($self, $request) = @_; my %headers = $self->http_request->s3->authorization_context->authorization_headers; while (my ($key, $value) = each %headers) { $self->_populate_default_header ($request, $key => $value); } (); } sub _append_authorization_query_params { my ($self, $request) = @_; my %headers = $self->http_request->s3->authorization_context->authorization_headers; while (my ($key, $value) = each %headers) { $self->_populate_default_query_param ($request, $key => $value); } (); } sub _populate_default_header { my ($self, $request, $key, $value) = @_; return unless defined $value; return if defined $request->header ($key); $request->header ($key => $value); (); } sub _populate_default_query_param { my ($self, $request, $key, $value) = @_; return unless defined $value; return if defined $request->uri->query_param ($key); $request->uri->query_param ($key => $value); (); } sub sign_request { my ($self, $request); return; } sub sign_uri { my ($self, $uri, $expires_at); return; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Signature - S3 Signature implementation base class =head1 VERSION version 0.991 =head1 METHODS =head2 new Signature class should accept HTTPRequest instance and determine every required parameter via this instance =head2 sign_request( $request ) Signature class should return authenticated request based on given parameter. Parameter can be modified. =head2 sign_uri( $request, $expires_at?, $method? ) Signature class should return authenticated uri based on given request. $expires_at is expiration time in seconds (epoch). Default and maximal allowed value may depend on signature version. Default request date is current time. Signature class should accept provided C<< X-Amz-Date >> header instead (if signing request) or query parameter (if signing uri) =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/0000775000175000017500000000000014264646670017743 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/0000775000175000017500000000000014264646670021334 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/Delete/0000775000175000017500000000000014264646670022536 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/Delete/Request.pm0000644000175000017500000000366514264646670024534 0ustar branobranopackage Net::Amazon::S3::Operation::Objects::Delete::Request; # ABSTRACT: An internal class to delete multiple objects from a bucket $Net::Amazon::S3::Operation::Objects::Delete::Request::VERSION = '0.991'; use Moose 0.85; use Carp qw/croak/; extends 'Net::Amazon::S3::Request::Bucket'; has 'keys' => ( is => 'ro', isa => 'ArrayRef', required => 1 ); with 'Net::Amazon::S3::Request::Role::HTTP::Header::Content_md5'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::POST'; with 'Net::Amazon::S3::Request::Role::Query::Action::Delete'; with 'Net::Amazon::S3::Request::Role::XML::Content'; __PACKAGE__->meta->make_immutable; sub _request_content { my ($self) = @_; return $self->_build_xml (Delete => [ { Quiet => 'true' }, map +{ Object => [ { Key => $_ } ] }, @{ $self->keys } ]); } sub BUILD { my ($self) = @_; croak "The maximum number of keys is 1000" if (scalar(@{$self->keys}) > 1000); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Objects::Delete::Request - An internal class to delete multiple objects from a bucket =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Objects::Delete::Request->new ( s3 => $s3, bucket => $bucket, keys => [$key1, $key2], ); =head1 DESCRIPTION This module deletes multiple objects from a bucket. Implements operation L<< DeleteObjects|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html >> =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/Delete/Response.pm0000644000175000017500000000171414264646670024673 0ustar branobranopackage Net::Amazon::S3::Operation::Objects::Delete::Response; # ABSTRACT: An internal class to handle delete multiple objects responses $Net::Amazon::S3::Operation::Objects::Delete::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Objects::Delete::Response - An internal class to handle delete multiple objects responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< DeleteObjects|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/List.pm0000644000175000017500000000174614264646670022613 0ustar branobranopackage Net::Amazon::S3::Operation::Buckets::List; # ABSTRACT: Internal class for service operation ListObjects $Net::Amazon::S3::Operation::Buckets::List::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Objects::List::Request; use Net::Amazon::S3::Operation::Objects::List::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Buckets::List - Internal class for service operation ListObjects =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< ListObjects|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/List/0000775000175000017500000000000014264646670022247 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/List/Request.pm0000644000175000017500000000333114264646670024233 0ustar branobranopackage Net::Amazon::S3::Operation::Objects::List::Request; # ABSTRACT: An internal class to list a bucket (List Objects Version 1) $Net::Amazon::S3::Operation::Objects::List::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use URI::Escape qw(uri_escape_utf8); extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::Query::Param::Delimiter'; with 'Net::Amazon::S3::Request::Role::Query::Param::Marker'; with 'Net::Amazon::S3::Request::Role::Query::Param::Max_keys'; with 'Net::Amazon::S3::Request::Role::Query::Param::Prefix'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::GET'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Objects::List::Request - An internal class to list a bucket (List Objects Version 1) =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Objects::List::Request->new( s3 => $s3, bucket => $bucket, delimiter => $delimiter, max_keys => $max_keys, marker => $marker, ); =head1 DESCRIPTION This module lists a bucket. Implements operation L<< ListObjects|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html >>. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/List/Response.pm0000644000175000017500000000615714264646670024412 0ustar branobranopackage Net::Amazon::S3::Operation::Objects::List::Response; # ABSTRACT: An internal class to list a bucket (List Objects Version 1) $Net::Amazon::S3::Operation::Objects::List::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; sub bucket { $_[0]->_data->{bucket}; } sub prefix { $_[0]->_data->{prefix}; } sub marker { $_[0]->_data->{marker}; } sub next_marker { $_[0]->_data->{next_marker}; } sub max_keys { $_[0]->_data->{max_keys}; } sub is_truncated { $_[0]->_data->{is_truncated}; } sub contents { @{ $_[0]->_data->{contents} }; } sub common_prefixes { @{ $_[0]->_data->{common_prefixes} }; } sub _parse_data { my ($self) = @_; my $xpc = $self->xpath_context; my $data = { bucket => scalar $xpc->findvalue ("/s3:ListBucketResult/s3:Name"), prefix => scalar $xpc->findvalue ("/s3:ListBucketResult/s3:Prefix"), marker => scalar $xpc->findvalue ("/s3:ListBucketResult/s3:Marker"), next_marker => scalar $xpc->findvalue ("/s3:ListBucketResult/s3:NextMarker"), max_keys => scalar $xpc->findvalue ("/s3:ListBucketResult/s3:MaxKeys"), is_truncated => scalar $xpc->findvalue ("/s3:ListBucketResult/s3:IsTruncated") eq 'true', contents => [], common_prefixes => [], }; for my $content ($xpc->findnodes ("/s3:ListBucketResult/s3:Contents")) { push @{ $data->{contents} }, { key => scalar $xpc->findvalue ("./s3:Key", $content), last_modified => scalar $xpc->findvalue ("./s3:LastModified", $content), etag => scalar $xpc->findvalue ("./s3:ETag", $content), size => scalar $xpc->findvalue ("./s3:Size", $content), storage_class => scalar $xpc->findvalue ("./s3:StorageClass", $content), owner => { id => $xpc->findvalue ("./s3:Owner/s3:ID", $content), displayname => $xpc->findvalue ("./s3:Owner/s3:DisplayName", $content), }, }; $data->{contents}[-1]{etag} =~ s/^"|"$//g; } for my $delimiter ($xpc->findnodes ("/s3:ListBucketResult/s3:Delimiter")) { $data->{delimiter} = $xpc->findvalue ('.', $delimiter); } if (defined $data->{delimiter}) { my $strip_delim = length $data->{delimiter}; for my $common_prefix ($xpc->findnodes ("/s3:ListBucketResult/s3:CommonPrefixes")) { my $prefix = $xpc->findvalue ('./s3:Prefix', $common_prefix); $prefix = substr $prefix, 0, -$strip_delim; push @{ $data->{common_prefixes} }, $prefix; } } return $data; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Objects::List::Response - An internal class to list a bucket (List Objects Version 1) =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< ListObjects|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html >>. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Objects/Delete.pm0000644000175000017500000000177014264646670023077 0ustar branobranopackage Net::Amazon::S3::Operation::Buckets::Delete; # ABSTRACT: Internal class for service operation DeleteObjects $Net::Amazon::S3::Operation::Buckets::Delete::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Objects::Delete::Request; use Net::Amazon::S3::Operation::Objects::Delete::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Buckets::Delete - Internal class for service operation DeleteObjects =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< DeleteObjects|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Buckets/0000775000175000017500000000000014264646670021343 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Buckets/List.pm0000644000175000017500000000172214264646670022614 0ustar branobranopackage Net::Amazon::S3::Operation::Buckets::List; # ABSTRACT: Internal class for service operation ListBuckets $Net::Amazon::S3::Operation::Buckets::List::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Buckets::List::Request; use Net::Amazon::S3::Operation::Buckets::List::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Buckets::List - Internal class for service operation ListBuckets =head1 VERSION version 0.991 Implements operation L<< ListBuckets|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Buckets/List/0000775000175000017500000000000014264646670022256 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Buckets/List/Request.pm0000644000175000017500000000307014264646670024242 0ustar branobranopackage Net::Amazon::S3::Operation::Buckets::List::Request; $Net::Amazon::S3::Operation::Buckets::List::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Service'; # ABSTRACT: An internal class to list all buckets with 'Net::Amazon::S3::Request::Role::HTTP::Method::GET'; __PACKAGE__->meta->make_immutable; # AWS routes request without specific region to us-east-1 # # https://docs.aws.amazon.com/general/latest/gr/rande.html sub http_request { my $self = shift; return $self->_build_http_request ( use_virtual_host => 0, region => $self->s3->vendor->default_region, ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Buckets::List::Request - An internal class to list all buckets =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Buckets::List::Request->new ( s3 => $s3, ); =head1 DESCRIPTION This module lists all buckets. Implements operation L<< ListBuckets|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html >> =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Buckets/List/Response.pm0000644000175000017500000000321714264646670024413 0ustar branobranopackage Net::Amazon::S3::Operation::Buckets::List::Response; # ABSTRACT: An internal class to process list all buckets response $Net::Amazon::S3::Operation::Buckets::List::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; sub owner_id { $_[0]->_data->{owner_id}; } sub owner_displayname { $_[0]->_data->{owner_displayname}; } sub buckets { @{ $_[0]->_data->{buckets} }; } sub _parse_data { my ($self) = @_; my $xpc = $self->xpath_context; my $data = { owner_id => $xpc->findvalue ("/s3:ListAllMyBucketsResult/s3:Owner/s3:ID"), owner_displayname => $xpc->findvalue ("/s3:ListAllMyBucketsResult/s3:Owner/s3:DisplayName"), buckets => [], }; foreach my $node ($xpc->findnodes ("/s3:ListAllMyBucketsResult/s3:Buckets/s3:Bucket")) { push @{ $data->{buckets} }, { name => $xpc->findvalue ("./s3:Name", $node), creation_date => $xpc->findvalue ("./s3:CreationDate", $node), }; } return $data; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Buckets::List::Response - An internal class to process list all buckets response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements S3 operation L<< ListBuckets|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/0000775000175000017500000000000014264646670021151 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Delete/0000775000175000017500000000000014264646670022353 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Delete/Request.pm0000644000175000017500000000253114264646670024340 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Delete::Request; # ABSTRACT: An internal class to delete an object $Net::Amazon::S3::Operation::Object::Delete::Request::VERSION = '0.991'; use Moose 0.85; use Moose::Util::TypeConstraints; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::DELETE'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Delete::Request - An internal class to delete an object =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Object::Delete::Request->new ( s3 => $s3, bucket => $bucket, key => $key, ); =head1 DESCRIPTION Implements operation L<< DeleteObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html >> This module deletes an object. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Delete/Response.pm0000644000175000017500000000166414264646670024514 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Delete::Response; # ABSTRACT: An internal class to handle object delete responses $Net::Amazon::S3::Operation::Object::Delete::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Delete::Response - An internal class to handle object delete responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< DeleteObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Restore/0000775000175000017500000000000014264646670022574 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Restore/Request.pm0000644000175000017500000000313214264646670024557 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Restore::Request; # ABSTRACT: An internal class implementing RestoreObject operation $Net::Amazon::S3::Operation::Object::Restore::Request::VERSION = '0.991'; use strict; use warnings; use Moose; use Moose::Util::TypeConstraints; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::POST'; with 'Net::Amazon::S3::Request::Role::Query::Action::Restore'; with 'Net::Amazon::S3::Request::Role::XML::Content'; enum 'Tier' => [ qw(Standard Expedited Bulk) ]; has 'days' => (is => 'ro', isa => 'Int', required => 1); has 'tier' => (is => 'ro', isa => 'Tier', required => 1); __PACKAGE__->meta->make_immutable; sub _request_content { my ($self) = @_; return $self->_build_xml (RestoreRequest => [ { Days => $self->days }, { GlacierJobParameters => [ { Tier => $self->tier }, ]}, ]); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Restore::Request - An internal class implementing RestoreObject operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<< RestoreObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Restore/Response.pm0000644000175000017500000000167314264646670024735 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Restore::Response; # ABSTRACT: An internal class to handle object restore responses $Net::Amazon::S3::Operation::Object::Restore::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Restore::Response - An internal class to handle object restore responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< RestoreObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Add/0000775000175000017500000000000014264646670021641 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Add/Request.pm0000644000175000017500000000361714264646670023634 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Add::Request; # ABSTRACT: An internal class to add an object to a bucket. $Net::Amazon::S3::Operation::Object::Add::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::ACL'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::Encryption'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::PUT'; has 'value' => ( is => 'ro', isa => 'Str|CodeRef|ScalarRef', required => 1 ); has 'headers' => ( is => 'ro', isa => 'HashRef', required => 0, default => sub { {} } ); __PACKAGE__->meta->make_immutable; sub _request_headers { my ($self) = @_; return %{ $self->headers }; } sub http_request { my $self = shift; return $self->_build_http_request( content => $self->value, ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Add::Request - An internal class to add an object to a bucket. =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Object::Add::Request->new ( s3 => $s3, bucket => $bucket, key => $key, value => $value, acl_short => $acl_short, headers => $conf, ); =head1 DESCRIPTION Implements operation L<< PutObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html >>. This module puts an object. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Add/Response.pm0000644000175000017500000000163514264646670024000 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Add::Response; # ABSTRACT: An internal class to handle object add response $Net::Amazon::S3::Operation::Object::Add::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Add::Response - An internal class to handle object add response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< PutObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html >>. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Add.pm0000644000175000017500000000172214264646670022177 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Add; # ABSTRACT: Internal class to perform PutObject operation $Net::Amazon::S3::Operation::Object::Add::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Add::Request; use Net::Amazon::S3::Operation::Object::Add::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Add - Internal class to perform PutObject operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< PutObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/0000775000175000017500000000000014264646670022047 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Delete/0000775000175000017500000000000014264646670023251 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Delete/Request.pm0000644000175000017500000000303214264646670025233 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Tags::Delete::Request; # ABSTRACT: Internal class to build PutObjectTagging requests $Net::Amazon::S3::Operation::Object::Tags::Delete::Request::VERSION = '0.991'; use Moose 0.85; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::DELETE'; with 'Net::Amazon::S3::Request::Role::Query::Action::Tagging'; with 'Net::Amazon::S3::Request::Role::Query::Param::Version_id'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Tags::Delete::Request - Internal class to build PutObjectTagging requests =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Bucket::Tags::Delete::Request->new ( s3 => $s3, bucket => $bucket, ); =head1 DESCRIPTION Implements a request part of an operation L =head1 PROPERIES =head2 version_id Optional. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Delete/Response.pm0000644000175000017500000000220114264646670025376 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Tags::Delete::Response; # ABSTRACT: An internal class to handle DeleteObjectTagging responses $Net::Amazon::S3::Operation::Object::Tags::Delete::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Tags::Delete::Response - An internal class to handle DeleteObjectTagging responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements a response part of an operation L =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Add/0000775000175000017500000000000014264646670022537 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Add/Request.pm0000644000175000017500000000314514264646670024526 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Tags::Add::Request; # ABSTRACT: Internal class to build PutObjectTagging request $Net::Amazon::S3::Operation::Object::Tags::Add::Request::VERSION = '0.991'; use Moose 0.85; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::Tags::Add'; with 'Net::Amazon::S3::Request::Role::Query::Param::Version_id'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Tags::Add::Request - Internal class to build PutObjectTagging request =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Bucket::Tags::Add::Request->new ( s3 => $s3, bucket => $bucket, key => $key, tags => { tag1 => 'val1', ... }, ); =head1 DESCRIPTION This module implements request of L operation. =head1 PROPERIES =head2 tags Mandattory. Hashref, key/value tag pairs =head2 version_id Optional. When specified tags on given version will be set. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Add/Response.pm0000644000175000017500000000215414264646670024673 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Tags::Add::Response; # ABSTRACT: An internal class to handle PutObjectTagging responses $Net::Amazon::S3::Operation::Object::Tags::Add::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Tags::Add::Response - An internal class to handle PutObjectTagging responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements a response part of an operation L =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Add.pm0000644000175000017500000000223614264646670023076 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Tags::Add; # ABSTRACT: Internal class to perform PutObjectTagging operation $Net::Amazon::S3::Operation::Object::Tags::Add::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Tags::Add::Request; use Net::Amazon::S3::Operation::Object::Tags::Add::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Tags::Add - Internal class to perform PutObjectTagging operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<> =head1 AUTHOR Branislav Zahradník . =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Tags/Delete.pm0000644000175000017500000000227114264646670023607 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Tags::Delete; # ABSTRACT: Internal class to perform DeleteObjectTagging operation $Net::Amazon::S3::Operation::Object::Tags::Delete::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Tags::Delete::Request; use Net::Amazon::S3::Operation::Object::Tags::Delete::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Tags::Delete - Internal class to perform DeleteObjectTagging operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<> =head1 AUTHOR Branislav Zahradník . =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Delete.pm0000644000175000017500000000175514264646670022717 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Delete; # ABSTRACT: Internal class to perform DeleteObject operation $Net::Amazon::S3::Operation::Object::Delete::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Delete::Request; use Net::Amazon::S3::Operation::Object::Delete::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Delete - Internal class to perform DeleteObject operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< DeleteObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Head.pm0000644000175000017500000000206214264646670022346 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Head; # ABSTRACT: Internal class to perform HeadObject operation $Net::Amazon::S3::Operation::Object::Head::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Head::Request; use Net::Amazon::S3::Operation::Object::Head::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Head - Internal class to perform HeadObject operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< HeadObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html >> =head1 COPYRIGHT AND LICENSE This module is part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Fetch/0000775000175000017500000000000014264646670022202 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Fetch/Request.pm0000644000175000017500000000362714264646670024176 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Fetch::Request; # ABSTRACT: An internal class to get an object $Net::Amazon::S3::Operation::Object::Fetch::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::HTTP::Method'; has 'range' => is => 'ro' => isa => 'Str' ; override _request_headers => sub { my ($self) = @_; return ( super, (Range => $self->range) x defined $self->range, ); }; __PACKAGE__->meta->make_immutable; sub query_string_authentication_uri { my ( $self, $expires, $query_form ) = @_; my $uri = URI->new( $self->_request_path ); $uri->query_form( %$query_form ) if $query_form; return $self->_build_signed_request( path => $uri->as_string, )->query_string_authentication_uri($expires); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Fetch::Request - An internal class to get an object =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Object::Fetch::Request->new ( s3 => $s3, bucket => $bucket, key => $key, method => 'GET', ); =head1 DESCRIPTION Implements operation L<< GetObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html >>. This module gets an object. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head2 query_string_authentication_uri This method returns query string authentication URI. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Fetch/Response.pm0000644000175000017500000000165014264646670024336 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Fetch::Response; # ABSTRACT: An internal class to handle object fetch response $Net::Amazon::S3::Operation::Object::Fetch::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Fetch::Response - An internal class to handle object fetch response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html >>. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/0000775000175000017500000000000014264646670022375 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Part.pm0000644000175000017500000000175614264646670023650 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Part; # ABSTRACT: Internal class to perform UploadPart operation $Net::Amazon::S3::Operation::Object::Part::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Upload::Part::Request; use Net::Amazon::S3::Operation::Object::Upload::Part::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Part - Internal class to perform UploadPart operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<< UploadPart|https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Complete.pm0000644000175000017500000000211314264646670024476 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Complete; # ABSTRACT: Internal class to perform CompleteMultipartUpload operation $Net::Amazon::S3::Operation::Object::Upload::Complete::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Upload::Complete::Request; use Net::Amazon::S3::Operation::Object::Upload::Complete::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Complete - Internal class to perform CompleteMultipartUpload operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< CompleteMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Part/0000775000175000017500000000000014264646670023303 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Part/Request.pm0000644000175000017500000000416614264646670025276 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Part::Request; # ABSTRACT: An internal class to put part of a multipart upload $Net::Amazon::S3::Operation::Object::Upload::Part::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::Query::Param::Upload_id'; with 'Net::Amazon::S3::Request::Role::Query::Param::Part_number'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::Copy_source'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::PUT'; has 'value' => ( is => 'ro', isa => 'Str|CodeRef|ScalarRef', required => 0 ); has 'headers' => ( is => 'ro', isa => 'HashRef', required => 0, default => sub { {} } ); __PACKAGE__->meta->make_immutable; sub _request_headers { my ($self) = @_; return %{ $self->headers }; } sub http_request { my $self = shift; return $self->_build_http_request( content => scalar( defined( $self->value ) ? $self->value : '' ), ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Part::Request - An internal class to put part of a multipart upload =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Object::Upload::Part::Request->new ( s3 => $s3, bucket => $bucket, key => $key, value => $value, acl_short => $acl_short, headers => $conf, part_number => $part_number, upload_id => $upload_id ); =head1 DESCRIPTION This module puts an object. Implements an operation L<< UploadPart|https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html >> =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Part/Response.pm0000644000175000017500000000171714264646670025443 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Part::Response; # ABSTRACT: Internal class to handle UploadPart operation's response $Net::Amazon::S3::Operation::Object::Upload::Part::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Part::Response - Internal class to handle UploadPart operation's response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<< UploadPart|https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Abort/0000775000175000017500000000000014264646670023444 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Abort/Request.pm0000644000175000017500000000351014264646670025427 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Abort::Request; # ABSTRACT: An internal class to abort a multipart upload $Net::Amazon::S3::Operation::Object::Upload::Abort::Request::VERSION = '0.991'; use Moose 0.85; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::Query::Param::Upload_id'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::DELETE'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Abort::Request - An internal class to abort a multipart upload =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Object::Upload::Abort::Request->new ( s3 => $s3, bucket => $bucket, key => $key upload_id => $upload_id, ); =head1 DESCRIPTION This module aborts a multipart upload. =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Abort::Request - An internal class to abort a multipart upload =head1 VERSION version 0.59 =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Pedro Figueiredo =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2013 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Abort/Response.pm0000644000175000017500000000175214264646670025603 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Abort::Response; # ABSTRACT: An internal class to handle abort multipart upload response $Net::Amazon::S3::Operation::Object::Upload::Abort::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Abort::Response - An internal class to handle abort multipart upload response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< AbortMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html >>. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Abort.pm0000644000175000017500000000206014264646670023776 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Abort; # ABSTRACT: Internal class to perform AbortMultipartUpload operation $Net::Amazon::S3::Operation::Object::Upload::Abort::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Upload::Abort::Request; use Net::Amazon::S3::Operation::Object::Upload::Abort::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Abort - Internal class to perform AbortMultipartUpload operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< AbortMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Create/0000775000175000017500000000000014264646670023600 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Create/Request.pm0000644000175000017500000000337514264646670025574 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Create::Request; #ABSTRACT: An internal class to begin a multipart upload $Net::Amazon::S3::Operation::Object::Upload::Create::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; has 'headers' => ( is => 'ro', isa => 'HashRef', required => 0, default => sub { {} } ); with 'Net::Amazon::S3::Request::Role::Query::Action::Uploads'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::ACL'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::Encryption'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::POST'; __PACKAGE__->meta->make_immutable; sub _request_headers { my ($self) = @_; return %{ $self->headers }; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Create::Request - An internal class to begin a multipart upload =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Object::Upload::Create::Request->new ( s3 => $s3, bucket => $bucket, keys => $key, ); =head1 DESCRIPTION Implement operation L<< CreateMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html >>. This module begins a multipart upload =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Create/Response.pm0000644000175000017500000000230414264646670025731 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Create::Response; # ABSTRACT: An internal class to handle create multipart upload response $Net::Amazon::S3::Operation::Object::Upload::Create::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; sub upload_id { $_[0]->_data->{upload_id}; } sub _parse_data { my ($self) = @_; my $xpc = $self->xpath_context; my $data = { upload_id => scalar $xpc->findvalue ("//s3:UploadId"), }; return $data; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Create::Response - An internal class to handle create multipart upload response =head1 VERSION version 0.991 =head1 DESCRIPTION Implement operation L<< CreateMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html >>. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Complete/0000775000175000017500000000000014264646670024145 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Complete/Request.pm0000644000175000017500000000421614264646670026134 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Complete::Request; # ABSTRACT: An internal class to complete a multipart upload $Net::Amazon::S3::Operation::Object::Upload::Complete::Request::VERSION = '0.991'; use Moose 0.85; use Carp qw/croak/; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::POST'; with 'Net::Amazon::S3::Request::Role::Query::Param::Upload_id'; with 'Net::Amazon::S3::Request::Role::XML::Content'; has 'etags' => ( is => 'ro', isa => 'ArrayRef', required => 1 ); has 'part_numbers' => ( is => 'ro', isa => 'ArrayRef', required => 1 ); __PACKAGE__->meta->make_immutable; sub _request_content { my ($self) = @_; return $self->_build_xml (CompleteMultipartUpload => [ map +{ Part => [ { PartNumber => $self->part_numbers->[$_] }, { ETag => $self->etags->[$_] }, ]}, 0 .. (@{$self->part_numbers} - 1) ]); } sub BUILD { my ($self) = @_; croak "must have an equally sized list of etags and part numbers" unless scalar(@{$self->part_numbers}) == scalar(@{$self->etags}); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Complete::Request - An internal class to complete a multipart upload =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Object::Upload::Complete::Request->new ( s3 => $s3, bucket => $bucket, etags => \@etags, part_numbers => \@part_numbers, ); =head1 DESCRIPTION This module completes a multipart upload. Implements operation L<< CompleteMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html >> =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Complete/Response.pm0000644000175000017500000000200214264646670026271 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Complete::Response; # ABSTRACT: An internal class to handle complete a multipart upload response $Net::Amazon::S3::Operation::Object::Upload::Complete::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Complete::Response - An internal class to handle complete a multipart upload response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< CompleteMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Parts/0000775000175000017500000000000014264646670023466 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Parts/Request.pm0000644000175000017500000000243214264646670025453 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Parts::Request; # ABSTRACT: List the parts in a multipart upload. $Net::Amazon::S3::Operation::Object::Upload::Parts::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::Query::Param::Upload_id'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::GET'; has 'headers' => ( is => 'ro', isa => 'HashRef', required => 0, default => sub { {} } ); __PACKAGE__->meta->make_immutable; sub _request_headers { my ($self) = @_; return %{ $self->headers }; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Parts::Request - List the parts in a multipart upload. =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<< ListParts|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Parts/Response.pm0000644000175000017500000000173714264646670025630 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Parts::Response; # ABSTRACT: An internal class to handle multipart upload parts list responses $Net::Amazon::S3::Operation::Object::Upload::Parts::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Parts::Response - An internal class to handle multipart upload parts list responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< ListParts|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Create.pm0000644000175000017500000000207114264646670024134 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Upload::Create; # ABSTRACT: Internal class to perform CreateMultipartUpload operation $Net::Amazon::S3::Operation::Object::Upload::Create::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Upload::Create::Request; use Net::Amazon::S3::Operation::Object::Upload::Create::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Upload::Create - Internal class to perform CreateMultipartUpload operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< CreateMultipartUpload|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Upload/Parts.pm0000644000175000017500000000201214264646670024015 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Parts::Complete; # ABSTRACT: Internal class to perform ListParts operation $Net::Amazon::S3::Operation::Object::Parts::Complete::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Upload::Parts::Request; use Net::Amazon::S3::Operation::Object::Upload::Parts::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Parts::Complete - Internal class to perform ListParts operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< ListParts|https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Restore.pm0000644000175000017500000000176614264646670023142 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Restore; # ABSTRACT: Internal class to perform RestoreObject operation $Net::Amazon::S3::Operation::Object::Restore::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Restore::Request; use Net::Amazon::S3::Operation::Object::Restore::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Restore - Internal class to perform RestoreObject operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< RestoreObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Fetch.pm0000644000175000017500000000173414264646670022543 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Fetch; # ABSTRACT: Internal class to perform PutObject operation $Net::Amazon::S3::Operation::Object::Fetch::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Fetch::Request; use Net::Amazon::S3::Operation::Object::Fetch::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Fetch - Internal class to perform PutObject operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Head/0000775000175000017500000000000014264646670022012 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Head/Request.pm0000644000175000017500000000220514264646670023775 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Head::Request; # ABSTRACT: An internal class to handle HeadObject request $Net::Amazon::S3::Operation::Object::Head::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::HEAD'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Head::Request - An internal class to handle HeadObject request =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< HeadObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html >>. =head1 COPYRIGHT AND LICENSE This module is part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Head/Response.pm0000644000175000017500000000177214264646670024153 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Head::Response; # ABSTRACT: An internal class to handle HeadObject response $Net::Amazon::S3::Operation::Object::Head::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Head::Response - An internal class to handle HeadObject response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< HeadObject|https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html >>. =head1 COPYRIGHT AND LICENSE This module is part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/0000775000175000017500000000000014264646670021650 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Set.pm0000644000175000017500000000176714264646670022752 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Acl::Set; # ABSTRACT: Internal class to perform PutObjectAcl operation $Net::Amazon::S3::Operation::Object::Acl::Set::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Acl::Set::Request; use Net::Amazon::S3::Operation::Object::Acl::Set::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Acl::Set - Internal class to perform PutObjectAcl operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< PutObjectAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectAcl.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Set/0000775000175000017500000000000014264646670022403 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Set/Request.pm0000644000175000017500000000364514264646670024377 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Acl::Set::Request; # ABSTRACT: An internal class to set an object's access control $Net::Amazon::S3::Operation::Object::Acl::Set::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; has 'acl_xml' => ( is => 'ro', isa => 'Maybe[Str]', required => 0 ); with 'Net::Amazon::S3::Request::Role::Query::Action::Acl'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::ACL'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::PUT'; __PACKAGE__->meta->make_immutable; sub _request_content { my ($self) = @_; return $self->acl_xml || ''; } sub BUILD { my ($self) = @_; unless ( $self->acl_xml || $self->acl ) { confess "need either acl_xml or acl"; } if ( $self->acl_xml && $self->acl ) { confess "can not provide both acl_xml and acl"; } } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Acl::Set::Request - An internal class to set an object's access control =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Object::Acl::Set::Request->new ( s3 => $s3, bucket => $bucket, key => $key, acl_short => $acl_short, acl_xml => $acl_xml, ); =head1 DESCRIPTION Implements operation L<< PutObjectAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectAcl.html >>. This module sets an object's access control. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Set/Response.pm0000644000175000017500000000167314264646670024544 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Acl::Set::Response; # ABSTRACT: An internal class to handle set object acl response $Net::Amazon::S3::Operation::Object::Acl::Set::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Acl::Set::Response - An internal class to handle set object acl response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< PutObjectAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectAcl.html >>. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Fetch/0000775000175000017500000000000014264646670022701 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Fetch/Request.pm0000644000175000017500000000271014264646670024665 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Acl::Fetch::Request; # ABSTRACT: An internal class to get an object's access control $Net::Amazon::S3::Operation::Object::Acl::Fetch::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Object'; with 'Net::Amazon::S3::Request::Role::Query::Action::Acl'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::GET'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Acl::Fetch::Request - An internal class to get an object's access control =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Object::Acl::Fetch::Request->new ( s3 => $s3, bucket => $bucket, key => $key, ); =head1 DESCRIPTION Implements operation L<< GetObjectAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html >>. This module gets an object's access control. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Fetch/Response.pm0000644000175000017500000000170414264646670025035 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Acl::Fetch::Response; # ABSTRACT: An internal class to handle fetch object acl response $Net::Amazon::S3::Operation::Object::Acl::Fetch::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Acl::Fetch::Response - An internal class to handle fetch object acl response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetObjectAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html >>. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Object/Acl/Fetch.pm0000644000175000017500000000200114264646670023226 0ustar branobranopackage Net::Amazon::S3::Operation::Object::Acl::Fetch; # ABSTRACT: Internal class to perform GetObjectAcl operation $Net::Amazon::S3::Operation::Object::Acl::Fetch::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Object::Acl::Fetch::Request; use Net::Amazon::S3::Operation::Object::Acl::Fetch::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Object::Acl::Fetch - Internal class to perform GetObjectAcl operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetObjectAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/0000775000175000017500000000000014264646670021160 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Delete/0000775000175000017500000000000014264646670022362 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Delete/Request.pm0000644000175000017500000000243414264646670024351 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Delete::Request; # ABSTRACT: An internal class to delete a bucket $Net::Amazon::S3::Operation::Bucket::Delete::Request::VERSION = '0.991'; use Moose 0.85; extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::DELETE'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Delete::Request - An internal class to delete a bucket =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Bucket::Delete::Request->new ( s3 => $s3, bucket => $bucket, ); =head1 DESCRIPTION This module deletes a bucket. Implements operation L<< DeleteBucket|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html >> =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Delete/Response.pm0000644000175000017500000000166314264646670024522 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Delete::Response; # ABSTRACT: An internal class to handle bucket delete responses $Net::Amazon::S3::Operation::Bucket::Delete::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Delete::Response - An internal class to handle bucket delete responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< DeleteBucket|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Location.pm0000644000175000017500000000200114264646670023255 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Location; # ABSTRACT: Internal class for service operation ListBuckets $Net::Amazon::S3::Operation::Bucket::Location::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Bucket::Location::Request; use Net::Amazon::S3::Operation::Bucket::Location::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Location - Internal class for service operation ListBuckets =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetBucketLocation|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/0000775000175000017500000000000014264646670022056 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete/0000775000175000017500000000000014264646670023260 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete/Request.pm0000644000175000017500000000273514264646670025253 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Tags::Delete::Request; # ABSTRACT: Internal class to build PutObjectTagging requests $Net::Amazon::S3::Operation::Bucket::Tags::Delete::Request::VERSION = '0.991'; use Moose 0.85; extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::DELETE'; with 'Net::Amazon::S3::Request::Role::Query::Action::Tagging'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Tags::Delete::Request - Internal class to build PutObjectTagging requests =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Bucket::Tags::Delete::Request->new ( s3 => $s3, bucket => $bucket, ); =head1 DESCRIPTION Implements a request part of an operation L =head1 PROPERIES =head2 tags Key/value tag pairs =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete/Response.pm0000644000175000017500000000220114264646670025405 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Tags::Delete::Response; # ABSTRACT: An internal class to handle DeleteBucketTagging responses $Net::Amazon::S3::Operation::Bucket::Tags::Delete::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Tags::Delete::Response - An internal class to handle DeleteBucketTagging responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements a response part of an operation L =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Add/0000775000175000017500000000000014264646670022546 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Add/Request.pm0000644000175000017500000000264714264646670024543 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Tags::Add::Request; # ABSTRACT: Internal class to build PutObjectTagging requests $Net::Amazon::S3::Operation::Bucket::Tags::Add::Request::VERSION = '0.991'; use Moose 0.85; extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::Tags::Add'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Tags::Add::Request - Internal class to build PutObjectTagging requests =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Bucket::Tags::Add::Request->new ( s3 => $s3, bucket => $bucket, tags => { tag1 => 'val1', ... }, ); =head1 DESCRIPTION Implements a request part of an operation L =head1 PROPERIES =head2 tags Key/value tag pairs =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Add/Response.pm0000644000175000017500000000215414264646670024702 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Tags::Add::Response; # ABSTRACT: An internal class to handle PutBucketTagging responses $Net::Amazon::S3::Operation::Bucket::Tags::Add::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Tags::Add::Response - An internal class to handle PutBucketTagging responses =head1 VERSION version 0.991 =head1 DESCRIPTION Implements a response part of an operation L =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Add.pm0000644000175000017500000000223614264646670023105 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Tags::Add; # ABSTRACT: Internal class to perform PutBucketTagging operation $Net::Amazon::S3::Operation::Bucket::Tags::Add::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Bucket::Tags::Add::Request; use Net::Amazon::S3::Operation::Bucket::Tags::Add::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Tags::Add - Internal class to perform PutBucketTagging operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<> =head1 AUTHOR Branislav Zahradník . =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete.pm0000644000175000017500000000227114264646670023616 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Tags::Delete; # ABSTRACT: Internal class to perform DeleteBucketTagging operation $Net::Amazon::S3::Operation::Bucket::Tags::Delete::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Bucket::Tags::Delete::Request; use Net::Amazon::S3::Operation::Bucket::Tags::Delete::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Tags::Delete - Internal class to perform DeleteBucketTagging operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements an operation L<> =head1 AUTHOR Branislav Zahradník . =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Location/0000775000175000017500000000000014264646670022730 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Location/Request.pm0000644000175000017500000000271014264646670024714 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Location::Request; # ABSTRACT: An internal class to get a bucket's location constraint $Net::Amazon::S3::Operation::Bucket::Location::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::Query::Action::Location'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::GET'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Location::Request - An internal class to get a bucket's location constraint =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Bucket::Location::Request->new ( s3 => $s3, bucket => $bucket, ); =head1 DESCRIPTION This module gets a bucket's location constraint. Implements operation L<< GetBucketLocation|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html >> =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Location/Response.pm0000644000175000017500000000272114264646670025064 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Location::Response; # ABSTRACT: An internal class to handle bucket location response $Net::Amazon::S3::Operation::Bucket::Location::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; sub location { $_[0]->_data->{location}; } sub _parse_data { my ($self) = @_; my $xpc = $self->xpath_context; my $data = { location => scalar $xpc->findvalue ("//s3:LocationConstraint"), }; # S3 documentation: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html # When the bucket's region is US East (N. Virginia), # Amazon S3 returns an empty string for the bucket's region $data->{location} = 'us-east-1' if defined $data->{location} && $data->{location} eq ''; return $data; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Location::Response - An internal class to handle bucket location response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetBucketLocation|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Create/0000775000175000017500000000000014264646670022363 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Create/Request.pm0000644000175000017500000000404314264646670024350 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Create::Request; # ABSTRACT: An internal class to create a bucket $Net::Amazon::S3::Operation::Bucket::Create::Request::VERSION = '0.991'; use Moose 0.85; extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::ACL'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::PUT'; with 'Net::Amazon::S3::Request::Role::XML::Content'; has location_constraint => ( is => 'ro', isa => 'MaybeLocationConstraint', coerce => 1, required => 0, ); __PACKAGE__->meta->make_immutable; sub _request_content { my ($self) = @_; my $content = ''; if (defined $self->location_constraint && $self->location_constraint ne 'us-east-1') { $content = $self->_build_xml ( CreateBucketConfiguration => [ { LocationConstraint => $self->location_constraint }, ] ); } return $content; } sub http_request { my $self = shift; return $self->_build_http_request ( region => 'us-east-1', ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Create::Request - An internal class to create a bucket =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Bucket::Create::Request->new( s3 => $s3, bucket => $bucket, acl_short => $acl_short, location_constraint => $location_constraint, )->http_request; =head1 DESCRIPTION This module creates a bucket. Implements operation L<< CreateBucket|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html >> =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Create/Response.pm0000644000175000017500000000166114264646670024521 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Create::Response; # ABSTRACT: An internal class to handle bucket create response $Net::Amazon::S3::Operation::Bucket::Create::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Create::Response - An internal class to handle bucket create response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< CreateBucket|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Delete.pm0000644000175000017500000000175514264646670022726 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Delete; # ABSTRACT: Internal class to perform DeleteBucket operation $Net::Amazon::S3::Operation::Bucket::Delete::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Bucket::Delete::Request; use Net::Amazon::S3::Operation::Bucket::Delete::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Delete - Internal class to perform DeleteBucket operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< DeleteBucket|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Create.pm0000644000175000017500000000175514264646670022727 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Create; # ABSTRACT: Internal class to perform CreateBucket operation $Net::Amazon::S3::Operation::Bucket::Create::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Bucket::Create::Request; use Net::Amazon::S3::Operation::Bucket::Create::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Create - Internal class to perform CreateBucket operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< CreateBucket|https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/0000775000175000017500000000000014264646670021657 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Set.pm0000644000175000017500000000176714264646670022761 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Acl::Set; # ABSTRACT: Internal class to perform PutBucketAcl operation $Net::Amazon::S3::Operation::Bucket::Acl::Set::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Bucket::Acl::Set::Request; use Net::Amazon::S3::Operation::Bucket::Acl::Set::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Acl::Set - Internal class to perform PutBucketAcl operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< PutBucketAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAcl.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Set/0000775000175000017500000000000014264646670022412 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Set/Request.pm0000644000175000017500000000364214264646670024403 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Acl::Set::Request; # ABSTRACT: An internal class to set a bucket's access control $Net::Amazon::S3::Operation::Bucket::Acl::Set::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use Carp (); extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::ACL'; has 'acl_xml' => ( is => 'ro', isa => 'Maybe[Str]', required => 0, ); with 'Net::Amazon::S3::Request::Role::Query::Action::Acl'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::PUT'; __PACKAGE__->meta->make_immutable; sub _request_content { my ($self) = @_; return $self->acl_xml || ''; } sub BUILD { my ($self) = @_; unless ($self->acl_xml || $self->acl) { Carp::confess "need either acl_xml or acl"; } if ($self->acl_xml && $self->acl) { Carp::confess "can not provide both acl_xml and acl"; } } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Acl::Set::Request - An internal class to set a bucket's access control =head1 VERSION version 0.991 =head1 SYNOPSIS my $request = Net::Amazon::S3::Operation::Bucket::Acl::Set::Request->new ( s3 => $s3, bucket => $bucket, acl_short => $acl_short, acl_xml => $acl_xml, ); =head1 DESCRIPTION Implements operation L<< PutBucketAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAcl.html >> This module sets a bucket's access control. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Set/Response.pm0000644000175000017500000000167114264646670024551 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Acl::Set::Response; # ABSTRACT: An internal class to handle bucket set acl response $Net::Amazon::S3::Operation::Bucket::Acl::Set::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Acl::Set::Response - An internal class to handle bucket set acl response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< PutBucketAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAcl.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch/0000775000175000017500000000000014264646670022710 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch/Request.pm0000644000175000017500000000266714264646670024707 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Request; # ABSTRACT: An internal class to get a bucket's access control $Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Request::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Bucket'; with 'Net::Amazon::S3::Request::Role::Query::Action::Acl'; with 'Net::Amazon::S3::Request::Role::HTTP::Method::GET'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Request - An internal class to get a bucket's access control =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Request->new ( s3 => $s3, bucket => $bucket, ); =head1 DESCRIPTION Implements operation L<< GetBucketAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketAcl.html >> This module gets a bucket's access control. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method returns a HTTP::Request object. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch/Response.pm0000644000175000017500000000170314264646670025043 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Response; # ABSTRACT: An internal class to handle fetch bucket acl response $Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Response::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::Response'; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Response - An internal class to handle fetch bucket acl response =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetBucketAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketAcl.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch.pm0000644000175000017500000000200114264646670023235 0ustar branobranopackage Net::Amazon::S3::Operation::Bucket::Acl::Fetch; # ABSTRACT: Internal class to perform GetBucketAcl operation $Net::Amazon::S3::Operation::Bucket::Acl::Fetch::VERSION = '0.991'; use strict; use warnings; use Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Request; use Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Response; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Operation::Bucket::Acl::Fetch - Internal class to perform GetBucketAcl operation =head1 VERSION version 0.991 =head1 DESCRIPTION Implements operation L<< GetBucketAcl|https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketAcl.html >> =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Constraint/0000775000175000017500000000000014264646670020127 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Constraint/Etag.pm0000644000175000017500000000137414264646670021350 0ustar branobranopackage Net::Amazon::S3::Constraint::Etag; # ABSTRACT: Moose constraint - Etag format $Net::Amazon::S3::Constraint::Etag::VERSION = '0.991'; use Moose::Util::TypeConstraints; type __PACKAGE__, where { $_ =~ /^[a-z0-9]{32}(?:-\d+)?$/ }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Constraint::Etag - Moose constraint - Etag format =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Constraint/ACL/0000775000175000017500000000000014264646670020526 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Constraint/ACL/Canned.pm0000644000175000017500000000213314264646670022251 0ustar branobranopackage Net::Amazon::S3::Constraint::ACL::Canned; # ABSTRACT: Moose constraint - valid Canned ACL constants $Net::Amazon::S3::Constraint::ACL::Canned::VERSION = '0.991'; use Moose::Util::TypeConstraints; # Current list at https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl enum __PACKAGE__, [ 'private', 'public-read', 'public-read-write', 'aws-exec-read', 'authenticated-read', 'bucket-owner-read', 'bucket-owner-full-control', 'log-delivery-write', ]; # Backward compatibility - create alias subtype 'AclShort', as __PACKAGE__; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Constraint::ACL::Canned - Moose constraint - valid Canned ACL constants =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/HTTPRequest.pm0000644000175000017500000001057114264646670020473 0ustar branobranopackage Net::Amazon::S3::HTTPRequest; $Net::Amazon::S3::HTTPRequest::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use HTTP::Date; use MIME::Base64 qw( encode_base64 ); use Moose::Util::TypeConstraints; use URI::Escape qw( uri_escape_utf8 ); use URI::QueryParam; use URI; use Net::Amazon::S3::Signature::V2; # ABSTRACT: Create a signed HTTP::Request my $METADATA_PREFIX = 'x-amz-meta-'; my $AMAZON_HEADER_PREFIX = 'x-amz-'; enum 'HTTPMethod' => [ qw(DELETE GET HEAD PUT POST) ]; with 'Net::Amazon::S3::Role::Bucket'; has '+bucket' => (required => 0); has 's3' => ( is => 'ro', isa => 'Net::Amazon::S3', required => 1 ); has 'method' => ( is => 'ro', isa => 'HTTPMethod', required => 1 ); has 'path' => ( is => 'ro', isa => 'Str', required => 1 ); has 'headers' => ( is => 'ro', isa => 'HashRef', required => 0, default => sub { {} } ); has 'content' => ( is => 'ro', isa => 'Str|CodeRef|ScalarRef', required => 0, default => '' ); has 'metadata' => ( is => 'ro', isa => 'HashRef', required => 0, default => sub { {} } ); has use_virtual_host => ( is => 'ro', isa => 'Bool', lazy => 1, default => sub { $_[0]->s3->use_virtual_host }, ); has authorization_method => ( is => 'ro', isa => 'Str', lazy => 1, default => sub { $_[0]->s3->authorization_method }, ); has region => ( is => 'ro', isa => 'Str', lazy => 1, default => sub { $_[0]->bucket->region }, ); has request_uri => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_uri', ); __PACKAGE__->meta->make_immutable; sub _build_uri { my ($self) = @_; my $path = $self->path; my $protocol = $self->s3->secure ? 'https' : 'http'; my $host = $self->s3->host; my $uri = "$protocol://$host/$path"; if ($self->use_virtual_host) { # use https://bucketname.s3.amazonaws.com instead of https://s3.amazonaws.com/bucketname # see http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html $uri =~ s{$host/(.*?)/}{$1.$host/}; } return $uri; } # make the HTTP::Request object sub _build_request { my $self = shift; my $method = $self->method; my $headers = $self->headers; my $content = $self->content; my $metadata = $self->metadata; my $http_headers = $self->_merge_meta( $headers, $metadata ); my $uri = $self->request_uri; my $http_request = HTTP::Request->new( $method, $uri, $http_headers, $content ); $http_request->content_length (0) if $self->s3->vendor->enforce_empty_content_length && ! $http_request->content_length ; return $http_request; } sub http_request { my $self = shift; my $request = $self->_build_request; $self->authorization_method->new( http_request => $self )->sign_request( $request ) unless $request->header( 'Authorization' ); return $request; } sub query_string_authentication_uri { my ( $self, $expires ) = @_; my $request = $self->_build_request; my $sign = $self->authorization_method->new( http_request => $self ); return $sign->sign_uri( $request, $expires ); } sub _merge_meta { my ( $self, $headers, $metadata ) = @_; $headers ||= {}; $metadata ||= {}; my $http_header = HTTP::Headers->new; while ( my ( $k, $v ) = each %$headers ) { $http_header->header( $k => $v ); } while ( my ( $k, $v ) = each %$metadata ) { $http_header->header( "$METADATA_PREFIX$k" => $v ); } return $http_header; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::HTTPRequest - Create a signed HTTP::Request =head1 VERSION version 0.991 =head1 SYNOPSIS my $http_request = Net::Amazon::S3::HTTPRequest->new( s3 => $self->s3, method => 'PUT', path => $self->bucket . '/', headers => $headers, content => $content, )->http_request; =head1 DESCRIPTION This module creates an HTTP::Request object that is signed appropriately for Amazon S3. =for test_synopsis no strict 'vars' =head1 METHODS =head2 http_request This method creates, signs and returns a HTTP::Request object. =head2 query_string_authentication_uri This method creates, signs and returns a query string authentication URI. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Role/0000775000175000017500000000000014264646670016704 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Role/Bucket.pm0000644000175000017500000000266514264646670020466 0ustar branobranopackage Net::Amazon::S3::Role::Bucket; # ABSTRACT: Bucket role $Net::Amazon::S3::Role::Bucket::VERSION = '0.991'; use Moose::Role; use Scalar::Util; use Safe::Isa (); around BUILDARGS => sub { my ($orig, $class, %params) = @_; # bucket can be optional in HTTPRequest if ($params{bucket}) { my $region = $params{region}; $region = $params{bucket}->region if $params{bucket} and Scalar::Util::blessed( $params{bucket} ) and ! $params{region} and $params{bucket}->has_region ; $params{bucket} = $params{bucket}->name if $params{bucket}->$Safe::Isa::_isa ('Net::Amazon::S3::Client::Bucket'); $params{bucket} = Net::Amazon::S3::Bucket->new( bucket => $params{bucket}, account => $params{s3}, (region => $region) x!! $region, ) if $params{bucket} and ! ref $params{bucket}; delete $params{region}; } $class->$orig( %params ); }; has bucket => ( is => 'ro', isa => 'Net::Amazon::S3::Bucket', required => 1, ); 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Role::Bucket - Bucket role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Role/ACL.pm0000644000175000017500000000254114264646670017641 0ustar branobranopackage Net::Amazon::S3::Role::ACL; # ABSTRACT: ACL specification $Net::Amazon::S3::Role::ACL::VERSION = '0.991'; use Moose::Role; use Moose::Util::TypeConstraints; use Carp (); use Net::Amazon::S3::ACL::Set; use Net::Amazon::S3::ACL::Canned; use Net::Amazon::S3::Constraint::ACL::Canned; has acl => ( is => 'ro', isa => union ([ 'Net::Amazon::S3::ACL::Set', 'Net::Amazon::S3::ACL::Canned', ]), required => 0, coerce => 1, ); around BUILDARGS => sub { my ($orig, $class) = (shift, shift); my $args = $class->$orig (@_); if (exists $args->{acl_short}) { my $acl_short = delete $args->{acl_short}; Carp::carp "'acl_short' parameter is ignored when 'acl' specified" if exists $args->{acl}; $args->{acl} = $acl_short unless exists $args->{acl}; } delete $args->{acl} unless defined $args->{acl}; return $args; }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Role::ACL - ACL specification =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Signature/0000775000175000017500000000000014264646670017744 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Signature/V4Implementation.pm0000644000175000017500000002377414264646670023514 0ustar branobranopackage Net::Amazon::S3::Signature::V4Implementation; # ABSTRACT: Implements the Amazon Web Services signature version 4, AWS4-HMAC-SHA256 (copy of Net::Amazon::Signature::V4) $Net::Amazon::S3::Signature::V4Implementation::VERSION = '0.991'; use strict; use warnings; use sort 'stable'; use Digest::SHA qw/sha256_hex hmac_sha256 hmac_sha256_hex/; use Time::Piece (); use URI::Escape; use URI; use URI::QueryParam; our $ALGORITHM = 'AWS4-HMAC-SHA256'; our $MAX_EXPIRES = 604800; # Max, 7 days our $X_AMZ_ALGORITHM = 'X-Amz-Algorithm'; our $X_AMZ_CONTENT_SHA256 = 'X-Amz-Content-Sha256'; our $X_AMZ_CREDENTIAL = 'X-Amz-Credential'; our $X_AMZ_DATE = 'X-Amz-Date'; our $X_AMZ_EXPIRES = 'X-Amz-Expires'; our $X_AMZ_SIGNEDHEADERS = 'X-Amz-SignedHeaders'; our $X_AMZ_SIGNATURE = 'X-Amz-Signature'; sub new { my $class = shift; my ( $access_key_id, $secret, $endpoint, $service ) = @_; my $self = { access_key_id => $access_key_id, secret => $secret, endpoint => $endpoint, service => $service, }; bless $self, $class; return $self; } sub sign { my ( $self, $request ) = @_; $request = $self->_augment_request( $request ); my $authz = $self->_authorization( $request ); $request->header( Authorization => $authz ); return $request; } sub sign_uri { my ( $self, $uri, $expires_in, $for_method ) = @_; my $request = $self->_augment_uri( $uri, $expires_in, $for_method ); my $signature = $self->_signature( $request ); $uri = $request->uri; my $query = $uri->query; $uri->query( undef ); $uri = $uri . '?' . $self->_sort_query_string( $query ); $uri .= "&$X_AMZ_SIGNATURE=$signature"; return $uri; } # _headers_to_sign: # Return the sorted lower case headers as required by the generation of canonical headers sub _headers_to_sign { my $req = shift; my @headers_to_sign = $req->uri->query_param( $X_AMZ_SIGNEDHEADERS ) ? $req->uri->query_param( $X_AMZ_SIGNEDHEADERS ) : $req->headers->header_field_names ; return sort { $a cmp $b } map { lc } @headers_to_sign } # _augment_request: # Append mandatory header fields sub _augment_request { my ( $self, $request ) = @_; $request->header($X_AMZ_DATE => $self->_format_amz_date( $self->_req_timepiece($request) )) unless $request->header($X_AMZ_DATE); $request->header($X_AMZ_CONTENT_SHA256 => sha256_hex($request->content)) unless $request->header($X_AMZ_CONTENT_SHA256); return $request; } # _augment_uri: # Append mandatory uri parameters sub _augment_uri { my ($self, $uri, $expires_in, $method) = @_; my $request = HTTP::Request->new( $method || GET => $uri ); $request->uri->query_param( $X_AMZ_DATE => $self->_format_amz_date( $self->_now ) ) unless $request->uri->query_param( $X_AMZ_DATE ); $request->uri->query_param( $X_AMZ_ALGORITHM => $ALGORITHM ) unless $request->uri->query_param( $X_AMZ_ALGORITHM ); $request->uri->query_param( $X_AMZ_CREDENTIAL => $self->_credential( $request ) ) unless $request->uri->query_param( $X_AMZ_CREDENTIAL ); $request->uri->query_param( $X_AMZ_EXPIRES => $expires_in || $MAX_EXPIRES ) unless $request->uri->query_param( $X_AMZ_EXPIRES ); $request->uri->query_param( $X_AMZ_EXPIRES => $MAX_EXPIRES ) if $request->uri->query_param( $X_AMZ_EXPIRES ) > $MAX_EXPIRES; $request->uri->query_param( $X_AMZ_SIGNEDHEADERS => 'host' ); return $request; } # _canonical_request: # Construct the canonical request string from an HTTP::Request. sub _canonical_request { my ( $self, $req ) = @_; my $creq_method = $req->method; my ( $creq_canonical_uri, $creq_canonical_query_string ) = ( $req->uri =~ m@([^?]*)\?(.*)$@ ) ? ( $1, $2 ) : ( $req->uri, '' ); $creq_canonical_uri =~ s@^https?://[^/]*/?@/@; # Documentation says "do not normalize URI paths for requests to Amazon S3" # https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html #$creq_canonical_uri = _simplify_uri( $creq_canonical_uri ); $creq_canonical_query_string = $self->_sort_query_string( $creq_canonical_query_string ); # Ensure Host header is present as its required if (!$req->header('host')) { my $host = $req->uri->_port ? $req->uri->host_port : $req->uri->host ; $req->header('Host' => $host); } my $creq_payload_hash = $req->header($X_AMZ_CONTENT_SHA256) # Signed uri doesn't have content || 'UNSIGNED-PAYLOAD'; # There's a bug in AMS4 which causes requests without x-amz-date set to be rejected # so we always add one if its not present. my $amz_date = $req->header($X_AMZ_DATE); my @sorted_headers = _headers_to_sign( $req ); my $creq_canonical_headers = join '', map { sprintf "%s:%s\x0a", lc, join ',', sort {$a cmp $b } _trim_whitespace($req->header($_) ) } @sorted_headers; my $creq_signed_headers = $self->_signed_headers( $req ); my $creq = join "\x0a", $creq_method, $creq_canonical_uri, $creq_canonical_query_string, $creq_canonical_headers, $creq_signed_headers, $creq_payload_hash; return $creq; } # _string_to_sign # Construct the string to sign. sub _string_to_sign { my ( $self, $req ) = @_; my $dt = $self->_req_timepiece( $req ); my $creq = $self->_canonical_request($req); my $sts_request_date = $self->_format_amz_date( $dt ); my $sts_credential_scope = join '/', $dt->strftime('%Y%m%d'), $self->{endpoint}, $self->{service}, 'aws4_request'; my $sts_creq_hash = sha256_hex( $creq ); my $sts = join "\x0a", $ALGORITHM, $sts_request_date, $sts_credential_scope, $sts_creq_hash; return $sts; } # _authorization # Construct the authorization string sub _signature { my ( $self, $req ) = @_; my $dt = $self->_req_timepiece( $req ); my $sts = $self->_string_to_sign( $req ); my $k_date = hmac_sha256( $dt->strftime('%Y%m%d'), 'AWS4' . $self->{secret} ); my $k_region = hmac_sha256( $self->{endpoint}, $k_date ); my $k_service = hmac_sha256( $self->{service}, $k_region ); my $k_signing = hmac_sha256( 'aws4_request', $k_service ); my $authz_signature = hmac_sha256_hex( $sts, $k_signing ); return $authz_signature; } sub _credential { my ( $self, $req ) = @_; my $dt = $self->_req_timepiece( $req ); my $authz_credential = join '/', $self->{access_key_id}, $dt->strftime('%Y%m%d'), $self->{endpoint}, $self->{service}, 'aws4_request'; return $authz_credential; } sub _signed_headers { my ( $self, $req ) = @_; my $authz_signed_headers = join ';', _headers_to_sign( $req ); return $authz_signed_headers; } sub _authorization { my ( $self, $req ) = @_; my $authz_signature = $self->_signature( $req ); my $authz_credential = $self->_credential( $req ); my $authz_signed_headers = $self->_signed_headers( $req ); my $authz = "$ALGORITHM Credential=$authz_credential,SignedHeaders=$authz_signed_headers,Signature=$authz_signature"; return $authz; } sub _simplify_uri { my $orig_uri = shift; my @parts = split /\//, $orig_uri; my @simple_parts = (); for my $part ( @parts ) { if ( ! length $part || $part eq '.' ) { } elsif ( $part eq '..' ) { pop @simple_parts; } else { push @simple_parts, $part; } } my $simple_uri = '/' . join '/', @simple_parts; $simple_uri .= '/' if $orig_uri =~ m@/$@ && $simple_uri !~ m@/$@; return $simple_uri; } sub _sort_query_string { my $self = shift; return '' unless $_[0]; my @params; for my $param ( split /&/, $_[0] ) { my ( $key, $value ) = map { tr/+/ /; uri_escape( uri_unescape( $_ ) ) } # escape all non-unreserved chars split /=/, $param; push @params, [$key, (defined $value ? $value : '')]; #push @params, [$key, $value]; } return join '&', map { join '=', grep defined, @$_ } sort { ( $a->[0] cmp $b->[0] ) || ( $a->[1] cmp $b->[1] ) } @params; } sub _trim_whitespace { return map { my $str = $_; $str =~ s/^\s*//; $str =~ s/\s*$//; $str } @_; } sub _str_to_timepiece { my $date = shift; if ( $date =~ m/^\d{8}T\d{6}Z$/ ) { # assume basic ISO 8601, as demanded by AWS return Time::Piece->strptime($date, '%Y%m%dT%H%M%SZ'); } else { # assume the format given in the AWS4 test suite $date =~ s/^.{5}//; # remove weekday, as Amazon's test suite contains internally inconsistent dates return Time::Piece->strptime($date, '%d %b %Y %H:%M:%S %Z'); } } sub _format_amz_date { my ($self, $dt) = @_; $dt->strftime('%Y%m%dT%H%M%SZ'); } sub _now { return scalar Time::Piece->gmtime; } sub _req_timepiece { my ($self, $req) = @_; my $x_date = $req->header($X_AMZ_DATE) || $req->uri->query_param($X_AMZ_DATE); my $date = $x_date || $req->header('Date'); if (!$date) { # No date set by the caller so set one up my $piece = $self->_now; $req->date($piece->epoch); return $piece } return _str_to_timepiece($date); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Signature::V4Implementation - Implements the Amazon Web Services signature version 4, AWS4-HMAC-SHA256 (copy of Net::Amazon::Signature::V4) =head1 VERSION version 0.991 =head1 DESCRIPTION This package clones L 0.19 adding support for signing URIs (GET request) Until https://github.com/Grinnz/Net-Amazon-Signature-V4/pull/5 will be merged we have to maintain our clone. =head1 Net::Amazon::Signature::S4 AUTHORS Tim Nordenfur, C<< >> Maintained by Dan Book, C<< >> =head2 sign( $request ) Signs a request with your credentials by appending the Authorization header. $request should be an HTTP::Request. The signed request is returned. =head2 sign_uri( $uri, $expires_in?, $for_method? ) Signs an uri with your credentials by appending the Authorization query parameters. C<< $expires_in >> integer value in range 1..604800 (1 second .. 7 days). C<< $expires_in >> default value is its maximum: 604800 C<< $for_method >> HTTP method this uri should be signed for, default C The signed uri is returned. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Signature/V2.pm0000644000175000017500000001167314264646670020577 0ustar branobranopackage Net::Amazon::S3::Signature::V2; # ABSTRACT: V2 signatures $Net::Amazon::S3::Signature::V2::VERSION = '0.991'; use Moose; use URI::Escape qw( uri_escape_utf8 ); use HTTP::Date qw[ time2str ]; use MIME::Base64 qw( encode_base64 ); use URI::QueryParam; use URI; use Net::Amazon::S3::Constants; use namespace::clean; extends 'Net::Amazon::S3::Signature'; my $AMAZON_HEADER_PREFIX = 'x-amz-'; sub enforce_use_virtual_host { 0; } sub sign_request { my ($self, $request) = @_; $self->_add_auth_header( $request ); } sub sign_uri { my ($self, $request, $expires) = @_; my $aws_access_key_id = $self->http_request->s3->aws_access_key_id; my $canonical_string = $self->_canonical_string( $request, $expires ); my $encoded_canonical = $self->_encode( $canonical_string ); my $uri = URI->new( $request->uri ); $uri->query_param( AWSAccessKeyId => $aws_access_key_id ); $uri->query_param( Expires => $expires ); $uri->query_param( Signature => $encoded_canonical ); $uri->as_string; } sub _add_auth_header { my ( $self, $request ) = @_; my $aws_access_key_id = $self->http_request->s3->aws_access_key_id; my $aws_secret_access_key = $self->http_request->s3->aws_secret_access_key; if ( not $request->headers->header('Date') ) { $request->header( Date => time2str(time) ); } $self->_append_authorization_headers ($request); my $canonical_string = $self->_canonical_string( $request ); my $encoded_canonical = $self->_encode( $canonical_string ); $request->header( Authorization => "AWS $aws_access_key_id:$encoded_canonical" ); } sub _canonical_string { my ( $self, $request, $expires ) = @_; my $method = $request->method; my $path = $self->http_request->path; my %interesting_headers = (); for my $key ($request->headers->header_field_names) { my $lk = lc $key; if ( $lk eq 'content-md5' or $lk eq 'content-type' or $lk eq 'date' or $lk =~ /^$AMAZON_HEADER_PREFIX/ ) { $interesting_headers{$lk} = $self->_trim( $request->header( $lk ) ); } } # these keys get empty strings if they don't exist $interesting_headers{'content-type'} ||= ''; $interesting_headers{'content-md5'} ||= ''; # just in case someone used this. it's not necessary in this lib. $interesting_headers{'date'} = '' if $interesting_headers{Net::Amazon::S3::Constants->HEADER_DATE}; # if you're using expires for query string auth, then it trumps date # (and x-amz-date) $interesting_headers{'date'} = $expires if $expires; my $buf = "$method\n"; foreach my $key ( sort keys %interesting_headers ) { if ( $key =~ /^$AMAZON_HEADER_PREFIX/ ) { $buf .= "$key:$interesting_headers{$key}\n"; } else { $buf .= "$interesting_headers{$key}\n"; } } # don't include anything after the first ? in the resource... $path =~ /^([^?]*)/; $buf .= "/$1"; # ...unless there any parameters we're interested in... if ( $path =~ /[&?](acl|torrent|location|uploads|delete)($|=|&)/ ) { $buf .= "?$1"; } elsif ( my %query_params = URI->new($path)->query_form ){ #see if the remaining parsed query string provides us with any query string or upload id if($query_params{partNumber} && $query_params{uploadId}){ #re-evaluate query string, the order of the params is important for request signing, so we can't depend on URI to do the right thing $buf .= sprintf("?partNumber=%s&uploadId=%s", $query_params{partNumber}, $query_params{uploadId}); } elsif($query_params{uploadId}){ $buf .= sprintf("?uploadId=%s",$query_params{uploadId}); } } return $buf; } # finds the hmac-sha1 hash of the canonical string and the aws secret access key and then # base64 encodes the result (optionally urlencoding after that). sub _encode { my ( $self, $str, $urlencode ) = @_; my $hmac = Digest::HMAC_SHA1->new($self->http_request->s3->aws_secret_access_key); $hmac->add($str); my $b64 = encode_base64( $hmac->digest, '' ); if ($urlencode) { return $self->_urlencode($b64); } else { return $b64; } } sub _urlencode { my ( $self, $unencoded ) = @_; return uri_escape_utf8( $unencoded, '^A-Za-z0-9_-' ); } sub _trim { my ( $self, $value ) = @_; $value =~ s/^\s+//; $value =~ s/\s+$//; return $value; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Signature::V2 - V2 signatures =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Signature/V4.pm0000644000175000017500000000547614264646670020605 0ustar branobranopackage Net::Amazon::S3::Signature::V4; # ABSTRACT: V4 signatures $Net::Amazon::S3::Signature::V4::VERSION = '0.991'; use Moose; use Net::Amazon::S3::Signature::V4Implementation; use Digest::SHA; use Ref::Util; use Net::Amazon::S3::Constants; use Net::Amazon::S3::Signature::V2; use namespace::clean; extends 'Net::Amazon::S3::Signature'; sub enforce_use_virtual_host { 1; } sub redirect_handler { my ($self, $http_request, $response, $ua, $h) = @_; my $region = $response->header(Net::Amazon::S3::Constants->HEADER_BUCKET_REGION) or return; # change the bucket region in request my $request = $response->request; $request->uri( $response->header( 'location' ) ); # sign the request again $request->headers->remove_header('Authorization'); $request->headers->remove_header(Net::Amazon::S3::Constants->HEADER_DATE); $http_request->_sign_request( $request, $region ); return $request; } sub _sign { my ($self, $region) = @_; return Net::Amazon::S3::Signature::V4Implementation->new( $self->http_request->s3->aws_access_key_id, $self->http_request->s3->aws_secret_access_key, $region || $self->http_request->region, 's3', ); } sub _host_to_region_host { my ($self, $sign, $request) = @_; my $host = $request->uri->host; return if $sign->{endpoint} eq 'us-east-1'; return unless $host =~ s/(?<=\bs3)(?=\.amazonaws\.com$)/"-" . $sign->{endpoint}/e; $request->uri->host( $host ); } sub sign_request { my ($self, $request, $region) = @_; my $sha = Digest::SHA->new( '256' ); if (Ref::Util::is_coderef( my $coderef = $request->content )) { while (length (my $snippet = $coderef->())) { $sha->add ($snippet); } $request->header( $Net::Amazon::S3::Signature::V4Implementation::X_AMZ_CONTENT_SHA256 => $sha->hexdigest ); } $self->_append_authorization_headers ($request); my $sign = $self->_sign( $region ); $self->_host_to_region_host( $sign, $request ); $sign->sign( $request ); return $request; } sub sign_uri { my ($self, $request, $expires_at) = @_; $self->_append_authorization_query_params ($request); my $sign = $self->_sign; $self->_host_to_region_host( $sign, $request ); return $sign->sign_uri( $request->uri, $expires_at - time, $request->method ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Signature::V4 - V4 signatures =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Authorization.pm0000644000175000017500000000156714264646670021210 0ustar branobranopackage Net::Amazon::S3::Authorization; $Net::Amazon::S3::Authorization::VERSION = '0.991'; use Moose 0.85; # ABSTRACT: Authorization context base class sub aws_access_key_id { } sub aws_secret_access_key { } sub aws_session_token { } sub authorization_headers { } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Authorization - Authorization context base class =head1 VERSION version 0.991 =head1 DESCRIPTION Authorization context provides an access to authorization information =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Authorization/0000775000175000017500000000000014264646670020643 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Authorization/IAM.pm0000644000175000017500000000502214264646670021604 0ustar branobranopackage Net::Amazon::S3::Authorization::IAM; $Net::Amazon::S3::Authorization::IAM::VERSION = '0.991'; # ABSTRACT: IAM authorization information use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Authorization::Basic'; has '+aws_access_key_id' => ( lazy => 1, default => sub { $_[0]->_credentials->accessKeyId }, ); has '+aws_secret_access_key' => ( lazy => 1, default => sub { $_[0]->_credentials->secretAccessKey }, ); has aws_session_token => ( is => 'ro', lazy => 1, default => sub { $_[0]->_credentials->sessionToken }, ); has _credentials => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_credentials', ); sub _build_credentials { eval "require VM::EC2::Security::CredentialCache" or die $@; my $creds = VM::EC2::Security::CredentialCache->get(); defined($creds) || die("Unable to retrieve IAM role credentials"); return $creds; } around authorization_headers => sub { my ($orig, $self) = @_; return +( $self->$orig, 'x-amz-security-token' => $self->aws_session_token, ); }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Authorization::IAM - IAM authorization information =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3; use Net::Amazon::S3::Authorization::IAM; # obtain instance credentials use VM::EC2::Security::CredentialCache; my $s3 = Net::Amazon::S3->new ( authorization_context => Net::Amazon::S3::Authorization::IAM->new, ... ); # or just provide your values my $s3 = Net::Amazon::S3->new ( authorization_context => Net::Amazon::S3::Authorization::IAM->new ( aws_access_key_id => ..., aws_secret_access_key => ..., aws_session_token => ..., ), ... ); =head1 DESCRIPTION Authorization context using instance session credentials. Unless specified authorization context obtains credentials via L<< VM::EC2::Security::CredentialCache >>. It is not listed as a L<< Net::Amazon::S3 >> dependency. =head1 INCOMPATIBILITY WARNING This module with its dependencies will be moved out and distributed separately without dependency from L. If you use IAM, please consider to add proper C statement into your code. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Authorization/Basic.pm0000644000175000017500000000224514264646670022223 0ustar branobranopackage Net::Amazon::S3::Authorization::Basic; $Net::Amazon::S3::Authorization::Basic::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Authorization'; # ABSTRACT: Basic authorization information has aws_access_key_id => ( is => 'ro', ); has aws_secret_access_key => ( is => 'ro', ); 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Authorization::Basic - Basic authorization information =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3; my $s3 = Net::Amazon::S3->new ( authorization_context => Net::Amazon::S3::Authorization::Basic->new ( aws_access_key_id => ..., aws_secret_access_key => ..., ), ... ); =head1 DESCRIPTION Basic authorization context for access_key / secret_key authorization. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Response.pm0000644000175000017500000001767014264646670020150 0ustar branobranopackage Net::Amazon::S3::Response; # ABSTRACT: Behaviour common to most S3 responses. $Net::Amazon::S3::Response::VERSION = '0.991'; use Moose; use Carp (); use XML::LibXML; use XML::LibXML::XPathContext; use Net::Amazon::S3::Constants; use namespace::clean; has http_response => ( is => 'ro', required => 1, handles => [ qw[ code ], qw[ message ], qw[ is_success ], qw[ is_redirect ], qw[ status_line ], qw[ content ], qw[ decoded_content ], qw[ header ], qw[ headers ], qw[ header_field_names ], ], ); has xml_document => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_xml_document', ); has xpath_context => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_xpath_context', ); has error_code => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_error_code', ); has error_message => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_error_message', ); has error_resource => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_error_resource', ); has error_request_id => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_error_request_id', ); has _data => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_data', ); sub _parse_data; sub connection { return $_[0]->header ('Connection'); } sub content_length { return $_[0]->http_response->content_length || 0; } sub content_type { return $_[0]->http_response->content_type; } sub date { return $_[0]->header ('Date'); } sub etag { return $_[0]->_decode_etag ($_[0]->header ('ETag')); } sub server { return $_[0]->header ('Server'); } sub delete_marker { return $_[0]->header (Net::Amazon::S3::Constants::HEADER_DELETE_MARKER); } sub id_2 { return $_[0]->header (Net::Amazon::S3::Constants::HEADER_ID_2); } sub request_id { return $_[0]->header (Net::Amazon::S3::Constants::HEADER_REQUEST_ID); } sub version_id { return $_[0]->header (Net::Amazon::S3::Constants::HEADER_VERSION_ID); } sub is_xml_content { my ($self) = @_; return $self->content_type =~ m:[/+]xml\b: && $self->decoded_content; } sub is_error { my ($self) = @_; return 1 if $self->http_response->is_error; return 1 if $self->findvalue ('/Error'); return; } sub is_internal_response { my ($self) = @_; my $header = $self->header ('Client-Warning'); return !! ($header && $header eq 'Internal response'); } sub findvalue { my ($self, @path) = @_; return '' unless $self->xpath_context; $self->xpath_context->findvalue (@path); } sub findnodes { my ($self, @path) = @_; return unless $self->xpath_context; $self->xpath_context->findnodes (@path); } sub _build_data { my ($self) = @_; return $self->is_success ? $self->_parse_data : undef ; } sub _build_error_code { my ($self) = @_; return unless $self->is_error; return $self->http_response->code unless $self->xpath_context; return $self->findvalue ('/Error/Code'); } sub _build_error_message { my ($self) = @_; return unless $self->is_error; return $self->http_response->message unless $self->xpath_context; return $self->findvalue ('/Error/Message'); } sub _build_error_resource { my ($self) = @_; return unless $self->is_error; return "${\ $self->http_response->request->uri }" unless $self->xpath_context; return $self->findvalue ('/Error/Resource'); } sub _build_error_request_id { my ($self) = @_; return unless $self->is_error; return $self->request_id unless $self->xpath_context; return $self->findvalue ('/Error/RequestId'); } sub _build_xml_document { my ($self) = @_; return unless $self->is_xml_content; # TODO: A 200 OK response can contain valid or invalid XML return XML::LibXML->new->parse_string ($self->http_response->decoded_content); } sub _build_xpath_context { my ($self) = @_; my $doc = $self->xml_document; return unless $doc; my $xpc = XML::LibXML::XPathContext->new ($doc); my $s3_ns = $doc->documentElement->lookupNamespaceURI || 'http://s3.amazonaws.com/doc/2006-03-01/'; $xpc->registerNs (s3 => $s3_ns); return $xpc; } sub _decode_etag { my ($self, $etag) = @_; $etag =~ s/ (?:^") | (?:"$) //gx; return $etag; } 1; __END__ =pod =encoding utf-8 =head1 NAME Net::Amazon::S3::Response - Behaviour common to most S3 responses. =head1 VERSION version 0.991 =head1 SYNOPSIS package Command::Response; extends 'Net::Amazon::S3::Response'; ... my $response = Command::Response->new ( http_response => $http_response, ); =head1 DESCRIPTION Response handler base class providing functionality common to most S3 responses. =head1 EXTENDING L provides methods to cache response data. =over =item _data Read-only accessor initialized by C<_build_data> =item _build_data Data builder, by default calls C<_parse_data> if response is success and provides valid XML document. =item _parse_data Abstract (undefined in parent) method to be implemented by children. =back =head1 METHODS =head2 Constructor Constructor accepts only one (required) parameter - C. It should act like L. =head2 Response classification methods =over =item is_success True if response is a success response, false otherwise. Successful response may contain invalid XML. =item is_redirect True if response is a redirect. =item is_error True if response is an error response, false otherwise. Response is considered to be an error either when response code is an HTTP error (4xx or 5xx) or response content is an error XML document. See also L<"S3 Error Response"|https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html> for more details. =item is_internal_response True if response is generated by user agent itself (eg: Cannot connect) =item is_xml_content True if response data is a valid XML document =back =head2 Error handling Apart error classifition L provides also common error data accessors. Error data are available only in case of error response. =over =item error_code Either content of C XML element or HTTP response code. =item error_message Either content of C XML element or HTTP response message. =item error_request_id Content of C XML element if available, C header if available, empty list otherwise. =item error_resource Content of c if available, request uri otherwise. =back =head2 Common Response Headers See L<"S3 Common Response Headers"|https://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html> for more details. =over =item content_length =item content_type =item connection =item etag ETag with trimmed leading/trailing quotes. =item server =item delete_marker =item request_id =item id_2 =item version_id =back =head2 XML Document parsing =over =item xml_document Lazy built instance of L. Available only if response is XML response and contains valid XML document. =item xpath_context Lazy built instance of L. Available only if response is XML response and contains valid XML document =back =head2 HTTP Response methods Further methods delegated to C. Refer L for description. =over =item code =item message =item status_line =item content =item decoded_content =item header =item headers =item header_field_names =back =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/X.pm0000644000175000017500000000226614264646670016554 0ustar branobranopackage Net::Amazon::S3::X; $Net::Amazon::S3::X::VERSION = '0.991'; # ABSTRACT: Net::Amazon::S3 exceptions use Moose; use Moose::Meta::Class; has request => ( is => 'ro', ); has response => ( is => 'ro', handles => [ 'error_code', 'error_message', 'http_response', ], ); my %exception_map; sub import { my ($class, @exceptions) = @_; for my $exception (@exceptions) { next if exists $exception_map{$exception}; Moose::Meta::Class->create ( $exception_map{$exception} = __PACKAGE__ . "::$exception", superclasses => [ __PACKAGE__ ], ); } } sub build { my ($self, $exception, @params) = @_; $self->import ($exception); $exception_map{$exception}->new (@params); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::X - Net::Amazon::S3 exceptions =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Utils.pm0000644000175000017500000000413014264646670017435 0ustar branobranopackage Net::Amazon::S3::Utils; # ABSTRACT: misc utils $Net::Amazon::S3::Utils::VERSION = '0.991'; sub parse_arguments { my ($self, $arguments, $positional, $aliases) = @_; my %args; $aliases = {} unless $aliases; push @$arguments, %{ pop @$arguments } if @$arguments && Ref::Util::is_plain_hashref ($arguments->[-1]); my %positional = map +($_ => 1), grep ! exists $args{$_}, @$positional; my $positional_count = scalar keys %positional; while (@$arguments > 1 && @$arguments > $positional_count) { my ($name, $value) = splice @$arguments, -2, 2; next if exists $args{$name}; $args{$name} = $value; $name = $aliases->{$name} if exists $aliases->{$name}; if (exists $positional{$name}) { $positional_count--; delete $positional{$name}; } } #die "Odd number of named arguments" # if @$arguments != $positional_count; for my $key (keys %$aliases) { next unless exists $args{$key}; my $value = delete $args{$key}; my $alias_for = $aliases->{$key}; $args{$alias_for} = $value unless exists $args{$alias_for}; } for my $name (@$positional) { next if exists $args{$name}; $args{$name} = shift @$arguments; } return %args; } sub parse_arguments_with_bucket { my ($self, $arguments) = @_; return $self->parse_arguments ($arguments, [qw[ bucket ]], { name => 'bucket' }); } sub parse_arguments_with_bucket_and_object { my ($self, $arguments) = @_; return $self->parse_arguments ($arguments, [qw[ bucket key ]], { name => 'bucket' }); } sub parse_arguments_with_object { my ($self, $arguments) = @_; return $self->parse_arguments ($arguments, [qw[ key ]], { name => 'bucket' }); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Utils - misc utils =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Features.pod0000644000175000017500000003500414264646670020265 0ustar branobrano# PODNAME:Net::Amazon::S3::Features # ABSTRACT: Features available in Net::Amazon::S3 =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Features - Features available in Net::Amazon::S3 =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __DATA__ =pod =encoding utf8 =head1 API COMPARISON Net::Amazon::S3 supports two APIs with different feature support. This document describes current behaviour. =head2 Error reporting Default error reporting method. =over =item set S3 err Operation returns expression evaluated as false and C<< err >> with C<< errstr >> are populated from response content See L, L =item set network error Populates S3 err with C<< network_error >> constant and S3 errstr with http status line (eg: C<< 404 Not Found >>) and throws. See L =item confess Operation throws using C<< confess >> See L =back =head2 Feature support For details see corresponding C<< api-operation >> / C<< client-operation >> test file List of L<"Amazon S3 Operations"|https://docs.aws.amazon.com/AmazonS3/latest/API/API_Operations_Amazon_Simple_Storage_Service.html> |-------------------------+---------------------------------+-----------------------------------| | operation | Net::Amazon::S3 (API) | Net::Amazon::S3::Client | |-------------------------+---------------------------------+-----------------------------------| | AbortMultipartUpload | ❌ | object->abort_multipart_upload | | returns | ❌ | http response | | errors | ❌ | confess | |-------------------------+---------------------------------+-----------------------------------| | CompleteMultipartUpload | ❌ | object->complete_multipart_upload | | returns | ❌ | http response | | errors | ❌ | confess | |-------------------------+---------------------------------+-----------------------------------| | CreateBucket | s3->add_bucket | client->create_bucket | | - with region | ✅ | ✅ | | returns | Bucket instance | Bucket instance | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | CreateMultipartUpload | ❌ | object->initiate_multipart_upload | | returns | ❌ | http response | | errors | ❌ | confess | |-------------------------+---------------------------------+-----------------------------------| | DeleteBucket | s3->delete_bucket | bucket->delete | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | DeleteBucketTagging | bucket->delete_tags | bucket->delete_tags | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | DeleteObject | bucket->delete_key | bucket->object->delete | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | DeleteObjects | bucket->delete_multi_object | bucket->delete_multi_object | | - auto chunks | ✅ | ✅ | | returns | boolean | HTTP::Response object | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | DeleteObjectTagging | bucket->delete_tags | bucket->object->delete_tags | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | GetBucketAcl | bucket->get_acl | bucket->acl | | returns | response body (XML) | response body (XML) | | | (undef on Not Found) | | | errors | set network error | confess | | | (none on Not Found) | | |-------------------------+---------------------------------+-----------------------------------| | GetBucketLocation | bucket->get_location_constraint | bucket->get_location_constraint | | returns | location (Str) | location (Str) | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | GetObject | bucket->get_key | bucket->object->get | | - into file | ✅, bucket->get_key_filename | ✅, bucket->object->get_filename | | - into callback | ❌ | ✅, bucket->object->get_callback | | returns | struct with value | value | | | (undef on Not Found) | | | errors | set network error | confess | | | (none on Not Found) | | |-------------------------+---------------------------------+-----------------------------------| | GetObjectAcl | bucket->get_acl | ❌ | | returns | response body (XML) | ❌ | | | (undef on Not Found) | ❌ | | errors | set network error | ❌ | | | (none on Not Found) | ❌ | |-------------------------+---------------------------------+-----------------------------------| | ListBuckets | s3->buckets | client->buckets | | returns | Bucket instances in struct | Bucket instances (list) | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | ListObjects | s3->list_bucket | bucket->list | | - common prefixes | ✅ | ❌ | | - list all | ✅, s3->list_bucket_all | ✅ | | returns | struct with list | iterator (Object list) | | errors | set S3 err | confess during iteration | |-------------------------+---------------------------------+-----------------------------------| | ListObjectsV2 | ❌ | ❌ | |-------------------------+---------------------------------+-----------------------------------| | ListParts | ❌ | ❌ | |-------------------------+---------------------------------+-----------------------------------| | PutBucketAcl | bucket->set_acl | bucket->set_acl | | - with canned acl | ✅, as acl | ✅, as acl | | - with explicit acl | ✅, as acl | ✅, as acl | | - with xml acl | ✅, as acl_xml | ✅, as acl_xml | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | PutBucketTagging | bucket->add_tags | bucket->add_tags | | - with canned acl | ✅, as acl | ✅, as acl | | - with explicit acl | ✅, as acl | ✅, as acl | | - with xml acl | ✅, as acl_xml | ✅, as acl_xml | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | PutObject | bucket->add_key | bucket->object->put | | returns | boolean | empty string | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | PutObjectAcl | bucket->set_acl | object->set_acl | | - with canned acl | ✅, as acl | ✅, as acl | | - with explicit acl | ✅, as acl | ✅, as acl | | - with xml acl | ✅, as acl_xml | ✅, as acl_xml | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | PutObjectTagging | bucket->add_tags | bucket->object->add_tags | | - with canned acl | ✅, as acl | ✅, as acl | | - with explicit acl | ✅, as acl | ✅, as acl | | - with xml acl | ✅, as acl_xml | ✅, as acl_xml | | returns | boolean | boolean | | errors | set S3 err | confess | |-------------------------+---------------------------------+-----------------------------------| | RestoreObject | ❌ | bucket->object->restore | | returns | ❌ | http response | | errors | ❌ | confess | |-------------------------+---------------------------------+-----------------------------------| | UploadPart | ❌ | bucket->object->put_part | | - from value | ❌ | ✅ | | - from file | ❌ | ❌ | | - from file chunk | ❌ | ❌ | | returns | ❌ | http response | | errors | ❌ | confess | |-------------------------+---------------------------------+-----------------------------------| | object-copy | bucket->copy_key | ❌ | | returns | boolean | ❌ | | errors | set S3 err | ❌ | |-------------------------+---------------------------------+-----------------------------------| | object-head | | ❌ | | returns | boolean | ❌ | | errors | set S3 err | ❌ | |-------------------------+---------------------------------+-----------------------------------| =head2 TODO plan (asorted, without time-plan) =over =item unify features Both APIs should support same set of operations =item support all AWS S3 operations and x-amz-* headers https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html =item add async API (AnyEvent / IO::Async) =back Net-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/0000775000175000017500000000000014264646670016402 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/Grantee.pm0000644000175000017500000000147614264646670020333 0ustar branobranopackage Net::Amazon::S3::ACL::Grantee; # ABSTRACT: Base class for misc ACL grantee representations $Net::Amazon::S3::ACL::Grantee::VERSION = '0.991'; use Moose; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::ACL::Grantee - Base class for misc ACL grantee representations =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/Set.pm0000644000175000017500000001074214264646670017475 0ustar branobranopackage Net::Amazon::S3::ACL::Set; # ABSTRACT: Representation of explicit ACL $Net::Amazon::S3::ACL::Set::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use Moose::Util::TypeConstraints; use Ref::Util (); use Safe::Isa (); use Net::Amazon::S3::Constants; use Net::Amazon::S3::ACL::Grantee::User; use Net::Amazon::S3::ACL::Grantee::Group; use Net::Amazon::S3::ACL::Grantee::Email; class_type 'Net::Amazon::S3::ACL::Set'; my %permission_map = ( full_control => Net::Amazon::S3::Constants::HEADER_GRANT_FULL_CONTROL, read => Net::Amazon::S3::Constants::HEADER_GRANT_READ, read_acp => Net::Amazon::S3::Constants::HEADER_GRANT_READ_ACP, write => Net::Amazon::S3::Constants::HEADER_GRANT_WRITE, write_acp => Net::Amazon::S3::Constants::HEADER_GRANT_WRITE_ACP, ); my %grantees_map = ( id => 'Net::Amazon::S3::ACL::Grantee::User', user => 'Net::Amazon::S3::ACL::Grantee::User', uri => 'Net::Amazon::S3::ACL::Grantee::Group', group => 'Net::Amazon::S3::ACL::Grantee::Group', email => 'Net::Amazon::S3::ACL::Grantee::Email', ); has _grantees => ( is => 'ro', default => sub { +{} }, ); sub build_headers { my ($self) = @_; my %headers; while (my ($header, $grantees) = each %{ $self->_grantees }) { $headers{$header} = join ', ', map $_->format_for_header, @$grantees; } %headers; } sub grant_full_control { my ($self, @grantees) = @_; $self->_grant (full_control => @grantees); } sub grant_read { my ($self, @grantees) = @_; $self->_grant (read => @grantees); } sub grant_read_acp { my ($self, @grantees) = @_; $self->_grant (read_acp => @grantees); } sub grant_write { my ($self, @grantees) = @_; $self->_grant (write => @grantees); } sub grant_write_acp { my ($self, @grantees) = @_; $self->_grant (write_acp => @grantees); } sub _grant { my ($self, $permission, @grantees) = @_; $self = $self->new unless ref $self; my $key = lc $permission; $key =~ tr/-/_/; die "Unknown permission $permission" unless exists $permission_map{$key}; return unless @grantees; my $list = $self->_grantees->{$permission_map{$key}} ||= []; while (@grantees) { my $type = shift @grantees; if ($type->$Safe::Isa::_isa ('Net::Amazon::S3::ACL::Grantee')) { push @{ $list }, $type; next; } die "Unknown grantee type $type" unless exists $grantees_map{$type}; die "Grantee type $type requires one argument" unless @grantees; my @grantee = (shift @grantees); @grantees = @{ $grantee[0] } if Ref::Util::is_plain_arrayref ($grantee[0]); push @{ $list }, map $grantees_map{$type}->new ($_), @grantee; } return $self; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::ACL::Set - Representation of explicit ACL =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3::ACL; $acl = Net::Amazon::S3::ACL->new ->grant_full_control ( id => 11112222333, id => 444455556666, uri => 'predefined group uri', email => 'email-address', ) ->grant_write ( ... ) ; =head1 DESCRIPTION Class representing explicit Amazon S3 ACL configuration. =head1 METHODS =head2 new Creates new instance. =head2 grant_full_control (@grantees) =head2 grant_read (@grantees) =head2 grant_read_acp (@grantees) =head2 grant_write (@grantees) =head2 grant_write_acp (@grantees) =head1 GRANTEES See also L<"Who Is a Grantee?"|https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#specifying-grantee> in Amazon S3 documentation. Each grant_* method accepts list of grantees either in key-value format or as an instance of C. =over =item canonical user ID ->grant_read ( id => 123, Net::Amazon::S3::ACL::Grantee::User->new (123), ) =item predefined group uri ->grant_read ( uri => 'http://...', Net::Amazon::S3::ACL::Grantee::Group->new ('http://...'), Net::Amazon::S3::ACL::Grantee::Group->ALL_USERS, ) =item email address ->grant_read ( email => 'foo@bar.baz', Net::Amazon::S3::ACL::Grantee::Email->new ('foo@bar.baz'), ); =back =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/Grantee/0000775000175000017500000000000014264646670017767 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/Grantee/Email.pm0000644000175000017500000000261714264646670021360 0ustar branobranopackage Net::Amazon::S3::ACL::Grantee::Email; # ABSTRACT: Represents user reference by email address for ACL $Net::Amazon::S3::ACL::Grantee::Email::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::ACL::Grantee'; has address => ( is => 'ro', isa => 'Str', required => 1, ); around BUILDARGS => sub { my ($orig, $class) = (shift, shift); unshift @_, 'address' if @_ == 1 && ! ref $_[0]; return $class->$orig (@_); }; sub format_for_header { my ($self) = @_; return "emailAddress=\"${\ $self->address }\""; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::ACL::Grantee::Email - Represents user reference by email address for ACL =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3::ACL::Grantee::Email; my $email = Net::Amazon::S3::ACL::Grantee::Email->new ('foo@bar.com'); my $email = Net::Amazon::S3::ACL::Grantee::Email->new (address => 'foo@bar.com'); =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/Grantee/User.pm0000644000175000017500000000246314264646670021246 0ustar branobranopackage Net::Amazon::S3::ACL::Grantee::User; # ABSTRACT: Represents user reference for ACL $Net::Amazon::S3::ACL::Grantee::User::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::ACL::Grantee'; has id => ( is => 'ro', isa => 'Str', required => 1, ); around BUILDARGS => sub { my ($orig, $class) = (shift, shift); unshift @_, 'id' if @_ == 1 && ! ref $_[0]; return $class->$orig (@_); }; sub format_for_header { my ($self) = @_; return "id=\"${\ $self->id }\""; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::ACL::Grantee::User - Represents user reference for ACL =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3::ACL::Grantee::User; my $user = Net::Amazon::S3::ACL::Grantee::User->new (123); my $user = Net::Amazon::S3::ACL::Grantee::User->new (id => 123); =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/Grantee/Group.pm0000644000175000017500000000350714264646670021424 0ustar branobranopackage Net::Amazon::S3::ACL::Grantee::Group; # ABSTRACT: Represents group reference for ACL $Net::Amazon::S3::ACL::Grantee::Group::VERSION = '0.991'; use Moose; extends 'Net::Amazon::S3::ACL::Grantee'; has group => ( is => 'ro', isa => 'Str', required => 1, ); around BUILDARGS => sub { my ($orig, $class) = (shift, shift); unshift @_, 'group' if @_ == 1 && ! ref $_[0]; return $class->$orig (@_); }; sub format_for_header { my ($self) = @_; return "uri=\"${\ $self->group }\""; } sub AUTHENTICATED_USERS { __PACKAGE__->new ('http://acs.amazonaws.com/groups/global/AuthenticatedUsers'); } sub ALL_USERS { __PACKAGE__->new ('http://acs.amazonaws.com/groups/global/AllUsers'); } sub LOG_DELIVERY { __PACKAGE__->new ('http://acs.amazonaws.com/groups/s3/LogDelivery'); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::ACL::Grantee::Group - Represents group reference for ACL =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3::ACL::Grantee::Group; my $group = Net::Amazon::S3::ACL::Grantee::Group->AUTHENTICATED_USERS; my $group = Net::Amazon::S3::ACL::Grantee::Group->ALL_USERS; my $group = Net::Amazon::S3::ACL::Grantee::Group->LOG_DELIVERY; my $group = Net::Amazon::S3::ACL::Grantee::Group->new ('http://...'); my $group = Net::Amazon::S3::ACL::Grantee::Group->new (group => 'http://...'); =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/ACL/Canned.pm0000644000175000017500000000473614264646670020140 0ustar branobranopackage Net::Amazon::S3::ACL::Canned; # ABSTRACT: Representation of canned ACL $Net::Amazon::S3::ACL::Canned::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use Moose::Util::TypeConstraints; use Net::Amazon::S3::Constraint::ACL::Canned; use Net::Amazon::S3::Constants; class_type 'Net::Amazon::S3::ACL::Canned'; coerce 'Net::Amazon::S3::ACL::Canned' => from 'Net::Amazon::S3::Constraint::ACL::Canned' => via { Net::Amazon::S3::ACL::Canned->new ($_) } ; around BUILDARGS => sub { my ($orig, $class) = (shift, shift); return +{ canned_acl => $_[0] } if @_ == 1 && ! ref $_[0]; return $class->$orig (@_); }; has canned_acl => ( is => 'ro', isa => 'Net::Amazon::S3::Constraint::ACL::Canned', required => 1, ); sub build_headers { my ($self) = @_; return +(Net::Amazon::S3::Constants->HEADER_CANNED_ACL => $self->canned_acl); } sub PRIVATE { __PACKAGE__->new ('private') } sub PUBLIC_READ { __PACKAGE__->new ('public-read') } sub PUBLIC_READ_WRITE { __PACKAGE__->new ('public-read-write') } sub AWS_EXEC_READ { __PACKAGE__->new ('aws-exec-read') } sub AUTHENTICATED_READ { __PACKAGE__->new ('authenticated-read') } sub BUCKET_OWNER_READ { __PACKAGE__->new ('bucket-owner-read') } sub BUCKET_OWNER_FULL_CONTROL { __PACKAGE__->new ('bucket-owner-full-control') } sub LOG_DELIVERY_WRITE { __PACKAGE__->new ('log-delivery-write') } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::ACL::Canned - Representation of canned ACL =head1 VERSION version 0.991 =head1 SYNOPSIS my $acl = Net::Amazon::S3::ACL::Canned->PRIVATE; my $acl = Net::Amazon::S3::ACL::Canned->PUBLIC_READ; =head1 DESCRIPTION Class representes predefined Amazon S3 canned ACL. =head1 FACTORY BUILDERS =head2 PRIVATE =head2 PUBLIC_READ =head2 PUBLIC_READ_WRITE =head2 AWS_EXEC_READ =head2 AUTHENTICATED_READ =head2 BUCKET_OWNER_READ =head2 BUCKET_OWNER_FULL_CONTROL =head2 LOG_DELIVER_WRITE =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This module is part of L. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Client/0000775000175000017500000000000014264646670017221 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Client/Bucket.pm0000644000175000017500000001675014264646670021003 0ustar branobranopackage Net::Amazon::S3::Client::Bucket; $Net::Amazon::S3::Client::Bucket::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use Data::Stream::Bulk::Callback; use MooseX::Types::DateTime::MoreCoercions 0.07 qw( DateTime ); # ABSTRACT: An easy-to-use Amazon S3 client bucket has 'client' => ( is => 'ro', isa => 'Net::Amazon::S3::Client', required => 1 ); has 'name' => ( is => 'ro', isa => 'Str', required => 1 ); has 'creation_date' => ( is => 'ro', isa => DateTime, coerce => 1, required => 0 ); has 'owner_id' => ( is => 'ro', isa => 'Str', required => 0 ); has 'owner_display_name' => ( is => 'ro', isa => 'Str', required => 0 ); has 'region' => ( is => 'ro', lazy => 1, predicate => 'has_region', default => sub { $_[0]->location_constraint }, ); __PACKAGE__->meta->make_immutable; sub _create { my ($self, %conf) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Create', (acl => $conf{acl}) x!! defined $conf{acl}, (acl_short => $conf{acl_short}) x!! defined $conf{acl_short}, (location_constraint => $conf{location_constraint}) x!! defined $conf{location_constraint}, ); return unless $response->is_success; return $response->http_response; } sub delete { my $self = shift; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Delete', ); return unless $response->is_success; return $response->http_response; } sub acl { my $self = shift; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Acl::Fetch', ); return if $response->is_error; return $response->http_response->content; } sub set_acl { my ($self, %params) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Acl::Set', %params, ); return $response->is_success; } sub add_tags { my ($self, %params) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Tags::Add', tags => $params{tags}, ); return $response->is_success; } sub delete_tags { my ($self, $conf) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Tags::Delete', ); return $response->is_success; } sub location_constraint { my $self = shift; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Location', ); return unless $response->is_success; return $response->location; } sub object_class { 'Net::Amazon::S3::Client::Object' } sub list { my ( $self, $conf ) = @_; $conf ||= {}; my $prefix = $conf->{prefix}; my $delimiter = $conf->{delimiter}; my $marker = undef; my $end = 0; return Data::Stream::Bulk::Callback->new( callback => sub { return undef if $end; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Objects::List', marker => $marker, prefix => $prefix, delimiter => $delimiter, ); return unless $response->is_success; my @objects; foreach my $node ($response->contents) { push @objects, $self->object_class->new ( client => $self->client, bucket => $self, key => $node->{key}, etag => $node->{etag}, size => $node->{size}, last_modified_raw => $node->{last_modified}, ); } return undef unless @objects; $end = 1 unless $response->is_truncated; $marker = $response->next_marker || $objects[-1]->key; return \@objects; } ); } sub delete_multi_object { my $self = shift; my @objects = @_; return unless( scalar(@objects) ); # Since delete can handle up to 1000 requests, be a little bit nicer # and slice up requests and also allow keys to be strings # rather than only objects. my $last_result; while (scalar(@objects) > 0) { my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Objects::Delete', keys => [ map { ref ($_) ? $_->key : $_ } splice @objects, 0, ((scalar(@objects) > 1000) ? 1000 : scalar(@objects)) ] ); $last_result = $response; last unless $response->is_success; } return $last_result->http_response; } sub object { my ( $self, %conf ) = @_; return $self->object_class->new( client => $self->client, bucket => $self, %conf, ); } sub _perform_operation { my ($self, $operation, %params) = @_; $self->client->_perform_operation ($operation => ( bucket => $self->name, %params, )); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Client::Bucket - An easy-to-use Amazon S3 client bucket =head1 VERSION version 0.991 =head1 SYNOPSIS # return the bucket name print $bucket->name . "\n"; # return the bucket location constraint print "Bucket is in the " . $bucket->location_constraint . "\n"; # return the ACL XML my $acl = $bucket->acl; # list objects in the bucket # this returns a L object which returns a # stream of L objects, as it may # have to issue multiple API requests my $stream = $bucket->list; until ( $stream->is_done ) { foreach my $object ( $stream->items ) { ... } } # or list by a prefix my $prefix_stream = $bucket->list( { prefix => 'logs/' } ); # returns a L, which can then # be used to get or put my $object = $bucket->object( key => 'this is the key' ); # delete the bucket (it must be empty) $bucket->delete; =head1 DESCRIPTION This module represents buckets. =for test_synopsis no strict 'vars' =head1 METHODS =head2 acl # return the ACL XML my $acl = $bucket->acl; =head2 add_tags $bucket->add_tags ( tags => { tag1 => 'val1', ... }, ) =head2 delete_tags $bucket->delete_tags; =head2 delete # delete the bucket (it must be empty) $bucket->delete; =head2 list # list objects in the bucket # this returns a L object which returns a # stream of L objects, as it may # have to issue multiple API requests my $stream = $bucket->list; until ( $stream->is_done ) { foreach my $object ( $stream->items ) { ... } } # or list by a prefix my $prefix_stream = $bucket->list( { prefix => 'logs/' } ); # you can emulate folders by using prefix with delimiter # which shows only entries starting with the prefix but # not containing any more delimiter (thus no subfolders). my $folder_stream = $bucket->list( { prefix => 'logs/', delimiter => '/' } ); =head2 location_constraint # return the bucket location constraint print "Bucket is in the " . $bucket->location_constraint . "\n"; =head2 name # return the bucket name print $bucket->name . "\n"; =head2 object # returns a L, which can then # be used to get or put my $object = $bucket->object( key => 'this is the key' ); =head2 delete_multi_object # delete multiple objects using a multi object delete operation # Accepts a list of L objects. $bucket->delete_multi_object($object1, $object2) =head2 object_class # returns string "Net::Amazon::S3::Client::Object" # allowing subclasses to add behavior. my $object_class = $bucket->object_class; =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Client/Object/0000775000175000017500000000000014264646670020427 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Client/Object/Range.pm0000644000175000017500000000423214264646670022020 0ustar branobranopackage Net::Amazon::S3::Client::Object::Range; # ABSTRACT: Object extension allowing to fetch part of an object $Net::Amazon::S3::Client::Object::Range::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; has 'object' => is => 'ro' => isa => 'Net::Amazon::S3::Client::Object' => required => 1 ; has 'range' => is => 'ro' => isa => 'Str' => required => 1 ; sub _get { my ($self, %args) = shift; my $response = $self->object->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Fetch', %args, method => 'GET', range => $self->range, ); return $response; } sub get { my $self = shift; return $self->_get->content; } sub get_decoded { my $self = shift; return $self->_get->decoded_content(@_); } sub get_callback { my ($self, $callback) = @_; return $self->_get (filename => $callback)->http_response; } sub get_filename { my ($self, $filename) = @_; return $self->_get (filename => $filename)->http_response; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Client::Object::Range - Object extension allowing to fetch part of an object =head1 VERSION version 0.991 =head1 SYNOPSIS my $value = $object->range ("bytes=1024-10240")->get; =head1 DESCRIPTION Simple implementation dowloads, see L. =head1 METHODS Provides same get methods as L =over =item get =item get_decoded =item get_callback =item get_filename =back =head1 SEE ALSO L =head1 AUTHOR Branislav Zahradník - since v0.99 =head1 COPYRIGHT AND LICENSE This module is a part of L distribution. =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Client/Object.pm0000644000175000017500000005403314264646670020770 0ustar branobranopackage Net::Amazon::S3::Client::Object; $Net::Amazon::S3::Client::Object::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use DateTime::Format::HTTP; use Digest::MD5 qw(md5 md5_hex); use Digest::MD5::File qw(file_md5 file_md5_hex); use File::stat; use MIME::Base64; use Moose::Util::TypeConstraints; use MooseX::Types::DateTime::MoreCoercions 0.07 qw( DateTime ); use IO::File 1.14; use Ref::Util (); # ABSTRACT: An easy-to-use Amazon S3 client object use Net::Amazon::S3::Constraint::ACL::Canned; use Net::Amazon::S3::Constraint::Etag; use Net::Amazon::S3::Client::Object::Range; with 'Net::Amazon::S3::Role::ACL'; enum 'StorageClass' => # Current list at https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html#AmazonS3-PutObject-request-header-StorageClass [ qw(standard reduced_redundancy standard_ia onezone_ia intelligent_tiering glacier deep_archive) ]; has 'client' => ( is => 'ro', isa => 'Net::Amazon::S3::Client', required => 1 ); has 'bucket' => ( is => 'ro', isa => 'Net::Amazon::S3::Client::Bucket', required => 1 ); has 'key' => ( is => 'ro', isa => 'Str', required => 1 ); has 'etag' => ( is => 'ro', isa => 'Net::Amazon::S3::Constraint::Etag', required => 0 ); has 'size' => ( is => 'ro', isa => 'Int', required => 0 ); has 'last_modified' => ( is => 'ro', isa => DateTime, coerce => 1, required => 0, default => sub { shift->last_modified_raw }, lazy => 1 ); has 'last_modified_raw' => ( is => 'ro', isa => 'Str', required => 0 ); has 'expires' => ( is => 'rw', isa => DateTime, coerce => 1, required => 0 ); has 'content_type' => ( is => 'ro', isa => 'Str', required => 0, default => 'binary/octet-stream' ); has 'content_disposition' => ( is => 'ro', isa => 'Str', required => 0, ); has 'content_encoding' => ( is => 'ro', isa => 'Str', required => 0, ); has 'cache_control' => ( is => 'ro', isa => 'Str', required => 0, ); has 'storage_class' => ( is => 'ro', isa => 'StorageClass', required => 0, default => 'standard', ); has 'user_metadata' => ( is => 'ro', isa => 'HashRef', required => 0, default => sub { {} }, ); has 'website_redirect_location' => ( is => 'ro', isa => 'Str', required => 0, ); has 'encryption' => ( is => 'ro', isa => 'Maybe[Str]', required => 0, ); __PACKAGE__->meta->make_immutable; sub range { my ($self, $range) = @_; return Net::Amazon::S3::Client::Object::Range->new ( object => $self, range => $range, ); } sub exists { my $self = shift; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Head', ); return $response->is_success; } sub _get { my $self = shift; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Fetch', method => 'GET', ); $self->_load_user_metadata ($response->http_response); return $response; } sub get { my $self = shift; return $self->_get->content; } sub get_decoded { my $self = shift; return $self->_get->decoded_content(@_); } sub get_callback { my ( $self, $callback ) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Fetch', filename => $callback, method => 'GET', ); return $response->http_response; } sub get_filename { my ( $self, $filename ) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Fetch', filename => $filename, method => 'GET', ); $self->_load_user_metadata($response->http_response); } sub _load_user_metadata { my ( $self, $http_response ) = @_; my %user_metadata; for my $header_name ($http_response->header_field_names) { my ($metadata_name) = lc($header_name) =~ /\A x-amz-meta- (.*) \z/xms or next; $user_metadata{$metadata_name} = $http_response->header($header_name); } %{ $self->user_metadata } = %user_metadata; } sub put { my ( $self, $value ) = @_; $self->_put( $value, length $value, md5_hex($value) ); } sub _put { my ( $self, $value, $size, $md5_hex ) = @_; my $md5_base64 = encode_base64( pack( 'H*', $md5_hex ) ); chomp $md5_base64; my $conf = { 'Content-MD5' => $md5_base64, 'Content-Length' => $size, 'Content-Type' => $self->content_type, }; if ( $self->expires ) { $conf->{Expires} = DateTime::Format::HTTP->format_datetime( $self->expires ); } if ( $self->content_encoding ) { $conf->{'Content-Encoding'} = $self->content_encoding; } if ( $self->content_disposition ) { $conf->{'Content-Disposition'} = $self->content_disposition; } if ( $self->cache_control ) { $conf->{'Cache-Control'} = $self->cache_control; } if ( $self->storage_class && $self->storage_class ne 'standard' ) { $conf->{'x-amz-storage-class'} = uc $self->storage_class; } if ( $self->website_redirect_location ) { $conf->{'x-amz-website-redirect-location'} = $self->website_redirect_location; } $conf->{"x-amz-meta-\L$_"} = $self->user_metadata->{$_} for keys %{ $self->user_metadata }; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Add', value => $value, headers => $conf, acl => $self->acl, encryption => $self->encryption, ); my $http_response = $response->http_response; confess 'Error uploading ' . $http_response->as_string unless $http_response->is_success; return ''; } sub put_filename { my ( $self, $filename ) = @_; my $md5_hex = $self->etag || file_md5_hex($filename); my $size = $self->size; unless ($size) { my $stat = stat($filename) || confess("No $filename: $!"); $size = $stat->size; } $self->_put( $self->_content_sub($filename), $size, $md5_hex ); } sub delete { my $self = shift; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Delete', ); return $response->is_success; } sub set_acl { my ($self, %params) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Acl::Set', %params, ); return $response->is_success; } sub add_tags { my ($self, %params) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Tags::Add', %params, ); return $response->is_success; } sub delete_tags { my ($self, %params) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Tags::Delete', (version_id => $params{version_id}) x!! defined $params{version_id}, ); return $response->is_success; } sub initiate_multipart_upload { my $self = shift; my %args = ref($_[0]) ? %{$_[0]} : @_; $args{acl} = $args{acl_short} if exists $args{acl_short}; delete $args{acl_short}; $args{acl} = $self->acl unless $args{acl}; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Upload::Create', encryption => $self->encryption, ($args{acl} ? (acl => $args{acl}) : ()), ($args{headers} ? (headers => $args{headers}) : ()), ); return unless $response->is_success; confess "Couldn't get upload id from initiate_multipart_upload response XML" unless $response->upload_id; return $response->upload_id; } sub complete_multipart_upload { my $self = shift; my %args = ref($_[0]) ? %{$_[0]} : @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Upload::Complete', upload_id => $args{upload_id}, etags => $args{etags}, part_numbers => $args{part_numbers}, ); return $response->http_response; } sub abort_multipart_upload { my $self = shift; my %args = ref($_[0]) ? %{$_[0]} : @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Upload::Abort', upload_id => $args{upload_id}, ); return $response->http_response; } sub put_part { my $self = shift; my %args = ref($_[0]) ? %{$_[0]} : @_; #work out content length header $args{headers}->{'Content-Length'} = length $args{value} if(defined $args{value}); my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Upload::Part', upload_id => $args{upload_id}, part_number => $args{part_number}, acl_short => $args{acl_short}, copy_source => $args{copy_source}, headers => $args{headers}, value => $args{value}, ); return $response->http_response; } sub list_parts { confess "Not implemented"; # TODO - Net::Amazon::S3::Request:ListParts is implemented, but need to # define better interface at this level. Currently returns raw XML. } sub uri { my $self = shift; return Net::Amazon::S3::Operation::Object::Fetch::Request->new ( s3 => $self->client->s3, bucket => $self->bucket->name, key => $self->key, method => 'GET', )->http_request->uri; } sub query_string_authentication_uri { my ($self, $query_form) = @_; return $self->query_string_authentication_uri_for_method (GET => $query_form); } sub query_string_authentication_uri_for_method { my ($self, $method, $query_form) = @_; return Net::Amazon::S3::Operation::Object::Fetch::Request->new ( s3 => $self->client->s3, bucket => $self->bucket->name, key => $self->key, method => $method, )->query_string_authentication_uri ($self->expires->epoch, $query_form); } sub head { my $self = shift; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Fetch', key => $self->key, method => 'HEAD', ); return unless $ response->is_success; my $http_response = $response->http_response; my %metadata; for my $header_name ($http_response->header_field_names) { if ($self->_is_metadata_header ($header_name)) { my $metadata_name = $self->_format_metadata_name ($header_name); $metadata{$metadata_name} = $http_response->header ($header_name); } } return \%metadata; } sub _is_metadata_header { my (undef, $header) = @_; $header = lc($header); my %valid_metadata_headers = map +($_ => 1), ( 'accept-ranges', 'cache-control', 'etag', 'expires', 'last-modified', ); return 1 if exists $valid_metadata_headers{$header}; return 1 if $header =~ m/^x-amz-(?!id-2$)/; return 1 if $header =~ m/^content-/; return 0; } sub _format_metadata_name { my (undef, $header) = @_; $header = lc($header); $header =~ s/^x-amz-//; my $metadata_name = join('', map (ucfirst, split(/-/, $header))); $metadata_name = 'ETag' if ($metadata_name eq 'Etag'); return $metadata_name; } sub available { my $self = shift; my %metadata = %{$self->head}; # An object is available if: # - the storage class isn't GLACIER; # - the storage class is GLACIER and the object was fully restored (Restore: ongoing-request="false"); my $glacier = (exists($metadata{StorageClass}) and $metadata{StorageClass} eq 'GLACIER') ? 1 : 0; my $restored = (exists($metadata{Restore}) and $metadata{Restore} =~ m/ongoing-request="false"/) ? 1 : 0; return (!$glacier or $restored) ? 1 :0; } sub restore { my $self = shift; my (%conf) = @_; my $request = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Object::Restore', key => $self->key, days => $conf{days}, tier => $conf{tier}, ); return $request->http_response; } sub _content_sub { my $self = shift; my $filename = shift; my $stat = stat($filename); my $remaining = $stat->size; my $blksize = $stat->blksize || 4096; confess "$filename not a readable file with fixed size" unless -r $filename and ( -f _ || $remaining ); my $fh = IO::File->new( $filename, 'r' ) or confess "Could not open $filename: $!"; $fh->binmode; return sub { my $buffer; # upon retries the file is closed and we must reopen it unless ( $fh->opened ) { $fh = IO::File->new( $filename, 'r' ) or confess "Could not open $filename: $!"; $fh->binmode; $remaining = $stat->size; } # warn "read remaining $remaining"; unless ( my $read = $fh->read( $buffer, $blksize ) ) { # warn "read $read buffer $buffer remaining $remaining"; confess "Error while reading upload content $filename ($remaining remaining) $!" if $! and $remaining; # otherwise, we found EOF $fh->close or confess "close of upload content $filename failed: $!"; $buffer ||= '' ; # LWP expects an emptry string on finish, read returns 0 } $remaining -= length($buffer); return $buffer; }; } sub _is_multipart_etag { my ( $self, $etag ) = @_; return 1 if($etag =~ /\-\d+$/); } sub _perform_operation { my ($self, $operation, %params) = @_; $self->bucket->_perform_operation ($operation => ( key => $self->key, %params, )); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Client::Object - An easy-to-use Amazon S3 client object =head1 VERSION version 0.991 =head1 SYNOPSIS # show the key print $object->key . "\n"; # show the etag of an existing object (if fetched by listing # a bucket) print $object->etag . "\n"; # show the size of an existing object (if fetched by listing # a bucket) print $object->size . "\n"; # to create a new object my $object = $bucket->object( key => 'this is the key' ); $object->put('this is the value'); # to get the value of an object my $value = $object->get; # to get the metadata of an object my %metadata = %{$object->head}; # to see if an object exists if ($object->exists) { ... } # to delete an object $object->delete; # to create a new object which is publically-accessible with a # content-type of text/plain which expires on 2010-01-02 my $object = $bucket->object( key => 'this is the public key', acl => Net::Amazon::S3::ACL::CANNED->PUBLIC_READ, content_type => 'text/plain', expires => '2010-01-02', ); $object->put('this is the public value'); # return the URI of a publically-accessible object my $uri = $object->uri; # to view if an object is available for downloading # Basically, the storage class isn't GLACIER or the object was # fully restored $object->available; # to restore an object on a GLACIER storage class $object->restore( days => 1, tier => 'Standard', ); # to store a new object with server-side encryption enabled my $object = $bucket->object( key => 'my secret', encryption => 'AES256', ); $object->put('this data will be stored using encryption.'); # upload a file my $object = $bucket->object( key => 'images/my_hat.jpg', content_type => 'image/jpeg', ); $object->put_filename('hat.jpg'); # upload a file if you already know its md5_hex and size my $object = $bucket->object( key => 'images/my_hat.jpg', content_type => 'image/jpeg', etag => $md5_hex, size => $size, ); $object->put_filename('hat.jpg'); # download the value of the object into a file my $object = $bucket->object( key => 'images/my_hat.jpg' ); $object->get_filename('hat_backup.jpg'); # use query string authentication for object fetch my $object = $bucket->object( key => 'images/my_hat.jpg', expires => '2009-03-01', ); my $uri = $object->query_string_authentication_uri(); # use query string authentication for object upload my $object = $bucket->object( key => 'images/my_hat.jpg', expires => '2009-03-01', ); my $uri = $object->query_string_authentication_uri_for_method('PUT'); =head1 DESCRIPTION This module represents objects in buckets. =for test_synopsis no strict 'vars' =head1 METHODS =head2 range my $value = $object->range ('bytes=1024-10240')->get; Provides simple interface to ranged download. See also L. =head2 etag # show the etag of an existing object (if fetched by listing # a bucket) print $object->etag . "\n"; =head2 delete # to delete an object $object->delete; =head2 exists # to see if an object exists if ($object->exists) { ... } Method doesn't report error when bucket or key doesn't exist. =head2 get # to get the vaue of an object my $value = $object->get; =head2 head # to get the metadata of an object my %metadata = %{$object->head}; Unlike C this method does report error. =head2 get_decoded # get the value of an object, and decode any Content-Encoding and/or # charset; see decoded_content in HTTP::Response my $value = $object->get_decoded; =head2 get_filename # download the value of the object into a file my $object = $bucket->object( key => 'images/my_hat.jpg' ); $object->get_filename('hat_backup.jpg'); =head2 last_modified, last_modified_raw # get the last_modified data as DateTime (slow) my $dt = $obj->last_modified; # or raw string in form '2015-05-15T10:12:40.000Z' (fast) # use this form if you are working with thousands of objects and # do not actually need an expensive DateTime for each of them my $raw = $obj->last_modified_raw; =head2 key # show the key print $object->key . "\n"; =head2 available # to view if an object is available for downloading # Basically, the storage class isn't GLACIER or the object was # fully restored $object->available; =head2 restore # to restore an object on a GLACIER storage class $object->restore( days => 1, tier => 'Standard', ); =head2 put # to create a new object my $object = $bucket->object( key => 'this is the key' ); $object->put('this is the value'); # to create a new object which is publically-accessible with a # content-type of text/plain my $object = $bucket->object( key => 'this is the public key', acl => 'public-read', content_type => 'text/plain', ); $object->put('this is the public value'); For C refer L. You may also set Content-Encoding using C, and Content-Disposition using C. You may specify the S3 storage class by setting C to either C, C, C, C, C, C, or C; the default is C. You may set website-redirect-location object metadata by setting C to either another object name in the same bucket, or to an external URL. =head2 put_filename # upload a file my $object = $bucket->object( key => 'images/my_hat.jpg', content_type => 'image/jpeg', ); $object->put_filename('hat.jpg'); # upload a file if you already know its md5_hex and size my $object = $bucket->object( key => 'images/my_hat.jpg', content_type => 'image/jpeg', etag => $md5_hex, size => $size, ); $object->put_filename('hat.jpg'); You may also set Content-Encoding using C, and Content-Disposition using C. You may specify the S3 storage class by setting C to either C, C, C, C, C, C, or C; the default is C. You may set website-redirect-location object metadata by setting C to either another object name in the same bucket, or to an external URL. User metadata may be set by providing a non-empty hashref as C. =head2 query_string_authentication_uri # use query string authentication, forcing download with custom filename my $object = $bucket->object( key => 'images/my_hat.jpg', expires => '2009-03-01', ); my $uri = $object->query_string_authentication_uri({ 'response-content-disposition' => 'attachment; filename=abc.doc', }); =head2 query_string_authentication_uri_for_method my $uri = $object->query_string_authentication_uri_for_method ('PUT'); Similar to L but creates presigned uri for specified HTTP method (Signature V4 uses also HTTP method). Methods providee authenticated uri only for direct object operations. See L =head2 size # show the size of an existing object (if fetched by listing # a bucket) print $object->size . "\n"; =head2 uri # return the URI of a publically-accessible object my $uri = $object->uri; =head2 initiate_multipart_upload #initiate a new multipart upload for this object my $object = $bucket->object( key => 'massive_video.avi', acl => ..., ); my $upload_id = $object->initiate_multipart_upload; For description of C refer C. =head2 put_part #add a part to a multipart upload my $put_part_response = $object->put_part( upload_id => $upload_id, part_number => 1, value => $chunk_content, ); my $part_etag = $put_part_response->header('ETag') Returns an L object. It is necessary to keep the ETags for each part, as these are required to complete the upload. =head2 complete_multipart_upload #complete a multipart upload $object->complete_multipart_upload( upload_id => $upload_id, etags => [$etag_1, $etag_2], part_numbers => [$part_number_1, $part_number2], ); The etag and part_numbers parameters are ordered lists specifying the part numbers and ETags for each individual part of the multipart upload. =head2 user_metadata my $object = $bucket->object(key => $key); my $content = $object->get; # or use $object->get_filename($filename) # return the user metadata downloaded, as a hashref my $user_metadata = $object->user_metadata; To upload an object with user metadata, set C at construction time to a hashref, with no C prefixes on the key names. When downloading an object, the C, C and C ethods set the contents of C to the same format. =head2 add_tags $object->add_tags ( tags => { tag1 => 'val1', tag2 => 'val2' }, ); $object->add_tags ( tags => { tag1 => 'val1', tag2 => 'val2' }, version_id => $version_id, ); =head2 delete_tags $object->delete_tags; $object->delete_tags ( version_id => $version_id, ); =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Vendor.pm0000644000175000017500000000677514264646670017613 0ustar branobranopackage Net::Amazon::S3::Vendor; $Net::Amazon::S3::Vendor::VERSION = '0.991'; use Moose 0.85; # ABSTRACT: Base class for vendor specific behaviour has host => ( is => 'ro', isa => 'Str', required => 1, ); has authorization_method => ( is => 'ro', isa => 'Str', lazy => 1, default => sub { require Net::Amazon::S3::Signature::V2; 'Net::Amazon::S3::Signature::V2', }, ); has use_https => ( is => 'ro', isa => 'Bool', lazy => 1, default => sub { 1 }, ); has use_virtual_host => ( is => 'ro', isa => 'Bool', lazy => 1, default => sub { $_[0]->authorization_method->enforce_use_virtual_host }, ); has default_region => ( is => 'ro', required => 0, default => sub { 'us-east-1' }, ); has enforce_empty_content_length => ( is => 'ro', default => sub { 1 }, ); sub guess_bucket_region { my ($self, $bucket) = @_; return $self->default_region; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Vendor - Base class for vendor specific behaviour =head1 VERSION version 0.991 =head1 SYNOPSIS # use it with Amazon AWS my $s3 = Net::Amazon::S3->new ( vendor => Net::Amazon::S3::Vendor::Amazon->new, ..., ); # or build your own vendor description my $vendor = Net::Amazon::S3::Vendor::Generic->new ( host => 'my.s3.service', use_https => 1, use_virtual_host => 1, authorization_method => 'Net::Amazon::S3::Signature::V2', ); # or my $vendor = Net::Amazon::S3::Vendor::Generic->new ( host => 'my.s3.service', use_https => 1, use_virtual_host => 1, authorization_method => 'Net::Amazon::S3::Signature::V4', default_region => '...', ); # and construct your s3 connection my $s3 = Net::Amazon::S3->new ( vendor => $vendor, ... ); =head1 DESCRIPTION S3 protocol is used not only by Amazon AWS but by many other object-storage services. They provide same API, but it's just there's a little difference. Examples? Allright, you can upload file but other provider does not support multipart uploads. Or although some providers support Signature V4 they may not support HEAD bucket request to fetch it automatically. =head2 Properties =head3 host Required, where service is located. Available here so one can move its parameters into its own vendor class. =head3 authorization_method Default: L<< Net::Amazon::S3::Signature::V2 >> Signature class used to authorize requests. =head3 use_https Default: true. Whether to use HTTPS or not. =head3 use_virtual_host Default: whatever C enforces Whether to use path or virtual host access style. Path style uses single host with bucket contained in uri path whereas virtual host style use bucket specific virtual hosts. =head3 default_region Default: undef Value that C will return. Use when your provider doesn't support HEAD region request but uses Signature V4 authorization method. =head2 Methods =head3 guess_bucket_region ($bucket) Returns bucket's region =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/0000775000175000017500000000000014264646670017433 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Bucket.pm0000644000175000017500000000167314264646670021213 0ustar branobranopackage Net::Amazon::S3::Request::Bucket; # ABSTRACT: Base class for all S3 Bucket operations $Net::Amazon::S3::Request::Bucket::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Service'; with 'Net::Amazon::S3::Role::Bucket'; override _request_path => sub { my ($self) = @_; return super . $self->bucket->bucket . "/"; }; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Bucket - Base class for all S3 Bucket operations =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Service.pm0000644000175000017500000000145414264646670021373 0ustar branobranopackage Net::Amazon::S3::Request::Service; # ABSTRACT: Base class for all S3 Service operations $Net::Amazon::S3::Request::Service::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request'; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Service - Base class for all S3 Service operations =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Object.pm0000644000175000017500000000176714264646670021210 0ustar branobranopackage Net::Amazon::S3::Request::Object; # ABSTRACT: Base class for all S3 Object operations $Net::Amazon::S3::Request::Object::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; extends 'Net::Amazon::S3::Request::Bucket'; has key => ( is => 'ro', isa => 'Str', required => 1, ); override _request_path => sub { my ($self) = @_; return super . (join '/', map {$self->s3->_urlencode($_)} split /\//, $self->key); }; __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Object - Base class for all S3 Object operations =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/0000775000175000017500000000000014264646670020334 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/0000775000175000017500000000000014264646670021113 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header.pm0000644000175000017500000000303314264646670022636 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Header; # ABSTRACT: HTTP Header Role $Net::Amazon::S3::Request::Role::HTTP::Header::VERSION = '0.991'; use MooseX::Role::Parameterized; parameter name => ( is => 'ro', isa => 'Str', required => 1, ); parameter header => ( is => 'ro', isa => 'Str', ); parameter constraint => ( is => 'ro', isa => 'Str', init_arg => 'isa', required => 1, ); parameter required => ( is => 'ro', isa => 'Bool', default => 0, ); parameter default => ( is => 'ro', isa => 'Str|CodeRef', required => 0, ); role { my ($params) = @_; my $name = $params->name; my $header = $params->header; has $name => ( is => 'ro', isa => $params->constraint, (init_arg => undef) x!! $name =~ m/^_/, required => $params->required, (default => $params->default) x!! defined $params->default, ); around _request_headers => eval <<"INLINE"; sub { my (\$inner, \$self) = \@_; my \$value = \$self->$name; return (\$self->\$inner, (q[$header] => \$value) x!! defined \$value); }; INLINE }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Header - HTTP Header Role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Method.pm0000644000175000017500000000205014264646670022664 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Method; # ABSTRACT: HTTP method role $Net::Amazon::S3::Request::Role::HTTP::Method::VERSION = '0.991'; use MooseX::Role::Parameterized; use Net::Amazon::S3::HTTPRequest; parameter method => ( is => 'ro', isa => 'HTTPMethod', required => 0, ); role { my ($params) = @_; has _http_request_method => ( is => 'ro', isa => 'HTTPMethod', $params->method ? ( init_arg => undef, default => $params->method, ) : ( init_arg => 'method', required => 1 ), ); }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Method - HTTP method role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header/0000775000175000017500000000000014264646670022303 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_length.pm0000644000175000017500000000172214264646670025614 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Header::Content_length; # ABSTRACT: Content-Lenghth header role $Net::Amazon::S3::Request::Role::HTTP::Header::Content_length::VERSION = '0.991'; use Moose::Role; use Digest::MD5 qw[]; use MIME::Base64 qw[]; around _request_headers => sub { my ($inner, $self) = @_; my $content = $self->_http_request_content; return ($self->$inner, ('Content-Length' => length $content)); }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Header::Content_length - Content-Lenghth header role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header/ACL.pm0000644000175000017500000000166414264646670023245 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Header::ACL; # ABSTRACT: Headers builders for ACL $Net::Amazon::S3::Request::Role::HTTP::Header::ACL::VERSION = '0.991'; use Moose::Role; use Moose::Util::TypeConstraints; use Carp (); with 'Net::Amazon::S3::Role::ACL'; around _request_headers => sub { my ($inner, $self) = @_; return +( $self->$inner, $self->acl ? $self->acl->build_headers : (), ); }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Header::ACL - Headers builders for ACL =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_md5.pm0000644000175000017500000000201714264646670025016 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Header::Content_md5; # ABSTRACT: Content-MD5 header role $Net::Amazon::S3::Request::Role::HTTP::Header::Content_md5::VERSION = '0.991'; use Moose::Role; use Digest::MD5 qw[]; use MIME::Base64 qw[]; around _request_headers => sub { my ($inner, $self) = @_; my $content = $self->_http_request_content; my $value = MIME::Base64::encode_base64( Digest::MD5::md5( $content ) ); chomp $value; return ($self->$inner, ('Content-MD5' => $value)); }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Header::Content_md5 - Content-MD5 header role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header/Copy_source.pm0000644000175000017500000000244514264646670025136 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Header::Copy_source; # ABSTRACT: x-amz-copy-source header role $Net::Amazon::S3::Request::Role::HTTP::Header::Copy_source::VERSION = '0.991'; use Moose::Role; use Net::Amazon::S3::Constants; with 'Net::Amazon::S3::Request::Role::HTTP::Header' => { name => '_copy_source', header => Net::Amazon::S3::Constants->HEADER_COPY_SOURCE, isa => 'Maybe[Str]', required => 0, default => sub { my ($self) = @_; defined $self->copy_source_bucket && defined $self->copy_source_key ? $self->copy_source_bucket.'/'.$self->copy_source_key : undef ; }, }; has 'copy_source_bucket' => ( is => 'ro', isa => 'Str', required => 0 ); has 'copy_source_key' => ( is => 'ro', isa => 'Str', required => 0 ); 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Header::Copy_source - x-amz-copy-source header role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_type.pm0000644000175000017500000000202214264646670025306 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Header::Content_type; # ABSTRACT: Content-Type header role $Net::Amazon::S3::Request::Role::HTTP::Header::Content_type::VERSION = '0.991'; use MooseX::Role::Parameterized; parameter content_type => ( is => 'ro', isa => 'Str', required => 1, ); role { my ($params) = @_; my $content_type = $params->content_type; around _request_headers => sub { my ($inner, $self) = @_; return ($self->$inner, ('Content-Type' => $content_type)); }; }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Header::Content_type - Content-Type header role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Header/Encryption.pm0000644000175000017500000000174214264646670024775 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Header::Encryption; # ABSTRACT: x-amz-server-side-encryption header role $Net::Amazon::S3::Request::Role::HTTP::Header::Encryption::VERSION = '0.991'; use Moose::Role; use Net::Amazon::S3::Constants; with 'Net::Amazon::S3::Request::Role::HTTP::Header' => { name => 'encryption', header => Net::Amazon::S3::Constants->HEADER_SERVER_ENCRYPTION, isa => 'Maybe[Str]', required => 0, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Header::Encryption - x-amz-server-side-encryption header role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Method/0000775000175000017500000000000014264646670022333 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Method/DELETE.pm0000644000175000017500000000145014264646670023631 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Method::DELETE; # ABSTRACT: HTTP DELETE method role $Net::Amazon::S3::Request::Role::HTTP::Method::DELETE::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::HTTP::Method' => { method => 'DELETE' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Method::DELETE - HTTP DELETE method role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Method/GET.pm0000644000175000017500000000142614264646670023311 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Method::GET; # ABSTRACT: HTTP GET method role $Net::Amazon::S3::Request::Role::HTTP::Method::GET::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::HTTP::Method' => { method => 'GET' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Method::GET - HTTP GET method role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Method/PUT.pm0000644000175000017500000000142614264646670023342 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Method::PUT; # ABSTRACT: HTTP PUT method role $Net::Amazon::S3::Request::Role::HTTP::Method::PUT::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::HTTP::Method' => { method => 'PUT' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Method::PUT - HTTP PUT method role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Method/POST.pm0000644000175000017500000000143414264646670023456 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Method::POST; # ABSTRACT: HTTP POST method role $Net::Amazon::S3::Request::Role::HTTP::Method::POST::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::HTTP::Method' => { method => 'POST' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Method::POST - HTTP POST method role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/HTTP/Method/HEAD.pm0000644000175000017500000000143414264646670023372 0ustar branobranopackage Net::Amazon::S3::Request::Role::HTTP::Method::HEAD; # ABSTRACT: HTTP HEAD method role $Net::Amazon::S3::Request::Role::HTTP::Method::HEAD::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::HTTP::Method' => { method => 'HEAD' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::HTTP::Method::HEAD - HTTP HEAD method role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/0000775000175000017500000000000014264646670021441 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action.pm0000644000175000017500000000156014264646670023214 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Action; # ABSTRACT: query action role $Net::Amazon::S3::Request::Role::Query::Action::VERSION = '0.991'; use MooseX::Role::Parameterized; parameter action => ( is => 'ro', isa => 'Str', ); role { my ($params) = @_; my $action = $params->action; method '_request_query_action' => sub { $action }; }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Action - query action role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action/0000775000175000017500000000000014264646670022656 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action/Tagging.pm0000644000175000017500000000146414264646670024577 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Action::Tagging; # ABSTRACT: tagging query action role $Net::Amazon::S3::Request::Role::Query::Action::Tagging::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Action' => { action => 'tagging' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Action::Tagging - tagging query action role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action/Location.pm0000644000175000017500000000147214264646670024766 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Action::Location; # ABSTRACT: location query action role $Net::Amazon::S3::Request::Role::Query::Action::Location::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Action' => { action => 'location' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Action::Location - location query action role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action/Uploads.pm0000644000175000017500000000146414264646670024626 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Action::Uploads; # ABSTRACT: uploads query action role $Net::Amazon::S3::Request::Role::Query::Action::Uploads::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Action' => { action => 'uploads' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Action::Uploads - uploads query action role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action/Delete.pm0000644000175000017500000000145614264646670024422 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Action::Delete; # ABSTRACT: delete query action role $Net::Amazon::S3::Request::Role::Query::Action::Delete::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Action' => { action => 'delete' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Action::Delete - delete query action role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action/Restore.pm0000644000175000017500000000146414264646670024642 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Action::Restore; # ABSTRACT: uploads query action role $Net::Amazon::S3::Request::Role::Query::Action::Restore::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Action' => { action => 'restore' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Action::Restore - uploads query action role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Action/Acl.pm0000644000175000017500000000143414264646670023713 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Action::Acl; # ABSTRACT: acl query action role $Net::Amazon::S3::Request::Role::Query::Action::Acl::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Action' => { action => 'acl' }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Action::Acl - acl query action role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/0000775000175000017500000000000014264646670022501 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/Delimiter.pm0000644000175000017500000000155014264646670024754 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param::Delimiter; # ABSTRACT: delimiter query param role $Net::Amazon::S3::Request::Role::Query::Param::Delimiter::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Param' => { param => 'delimiter', constraint => 'Maybe[Str]', required => 0, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param::Delimiter - delimiter query param role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/Max_keys.pm0000644000175000017500000000162014264646670024614 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param::Max_keys; # ABSTRACT: max-keys query param role $Net::Amazon::S3::Request::Role::Query::Param::Max_keys::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Param' => { param => 'max_keys', query_param => 'max-keys', constraint => 'Maybe[Str]', required => 0, default => 1000, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param::Max_keys - max-keys query param role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/Prefix.pm0000644000175000017500000000152614264646670024276 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param::Prefix; # ABSTRACT: prefix query param role $Net::Amazon::S3::Request::Role::Query::Param::Prefix::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Param' => { param => 'prefix', constraint => 'Maybe[Str]', required => 0, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param::Prefix - prefix query param role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/Version_id.pm0000644000175000017500000000160414264646670025137 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param::Version_id; # ABSTRACT: version_id query param role $Net::Amazon::S3::Request::Role::Query::Param::Version_id::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Param' => { param => 'version_id', query_param => 'versionId', constraint => 'Str', required => 0, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param::Version_id - version_id query param role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/Marker.pm0000644000175000017500000000152614264646670024262 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param::Marker; # ABSTRACT: marker query param role $Net::Amazon::S3::Request::Role::Query::Param::Marker::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Param' => { param => 'marker', constraint => 'Maybe[Str]', required => 0, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param::Marker - marker query param role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/Part_number.pm0000644000175000017500000000161114264646670025312 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param::Part_number; # ABSTRACT: partNumber query param role $Net::Amazon::S3::Request::Role::Query::Param::Part_number::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Param' => { param => 'part_number', query_param => 'partNumber', constraint => 'Int', required => 1, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param::Part_number - partNumber query param role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param/Upload_id.pm0000644000175000017500000000157514264646670024745 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param::Upload_id; # ABSTRACT: upload_id query param role $Net::Amazon::S3::Request::Role::Query::Param::Upload_id::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::Query::Param' => { param => 'upload_id', query_param => 'uploadId', constraint => 'Str', required => 1, }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param::Upload_id - upload_id query param role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Query/Param.pm0000644000175000017500000000307314264646670023040 0ustar branobranopackage Net::Amazon::S3::Request::Role::Query::Param; # ABSTRACT: request query params role $Net::Amazon::S3::Request::Role::Query::Param::VERSION = '0.991'; use MooseX::Role::Parameterized; parameter param => ( is => 'ro', isa => 'Str', required => 1, ); parameter query_param => ( is => 'ro', isa => 'Str', lazy => 1, default => sub { $_[0]->param }, ); parameter constraint => ( is => 'ro', isa => 'Str', required => 1, ); parameter required => ( is => 'ro', isa => 'Bool', default => 0, ); parameter default => ( is => 'ro', isa => 'Str|CodeRef', required => 0, ); role { my ($params) = @_; my $param = $params->param; my $query_param = $params->query_param; has $param => ( is => 'ro', isa => $params->constraint, required => $params->required, (default => $params->default) x!! defined $params->default, ); around _request_query_params => eval <<"INLINE"; sub { my (\$inner, \$self) = \@_; my \$value = \$self->$param; return (\$self->\$inner, (q[$query_param] => \$value) x!! defined \$value); }; INLINE }; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Query::Param - request query params role =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Tags/0000775000175000017500000000000014264646670021232 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/Tags/Add.pm0000644000175000017500000000226614264646670022264 0ustar branobranopackage Net::Amazon::S3::Request::Role::Tags::Add; # ABSTRACT: Add tags request parts common to Bucket and Object $Net::Amazon::S3::Request::Role::Tags::Add::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::HTTP::Method::PUT'; with 'Net::Amazon::S3::Request::Role::Query::Action::Tagging'; with 'Net::Amazon::S3::Request::Role::XML::Content'; has 'tags' => ( is => 'ro', isa => 'HashRef', required => 1, ); sub _request_content { my ($self) = @_; $self->_build_xml (Tagging => [ { TagSet => [ map +{ Tag => [ { Key => $_ }, { Value => $self->tags->{$_} }, ]}, sort keys %{ $self->tags } ]}, ]); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::Tags::Add - Add tags request parts common to Bucket and Object =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/XML/0000775000175000017500000000000014264646670020774 5ustar branobranoNet-Amazon-S3-0.991/lib/Net/Amazon/S3/Request/Role/XML/Content.pm0000644000175000017500000000322214264646670022741 0ustar branobranopackage Net::Amazon::S3::Request::Role::XML::Content; # ABSTRACT: Role providing XML content $Net::Amazon::S3::Request::Role::XML::Content::VERSION = '0.991'; use Moose::Role; with 'Net::Amazon::S3::Request::Role::HTTP::Header::Content_length'; with 'Net::Amazon::S3::Request::Role::HTTP::Header::Content_type' => { content_type => 'application/xml' }; sub _build_xml { my ($self, $root_name, $root_content) = @_; my $ns = Net::Amazon::S3::Constants->S3_NAMESPACE_URI; my $xml_doc = XML::LibXML::Document->new ('1.0','UTF-8'); my $root_element = $xml_doc->createElementNS ($ns, $root_name); $xml_doc->setDocumentElement ($root_element); my @queue = ([ $root_element, $root_content ]); while (my $node = shift @queue) { my ($parent, $content) = @$node; for my $tag (@$content) { my ($tag_name, $tag_content) = %$tag; my $tag_node = $parent->addNewChild ($ns, $tag_name); if (ref $tag_content) { push @queue, [$tag_node, $tag_content]; next; } if (defined $tag_content && length $tag_content) { $tag_node->addChild ($xml_doc->createTextNode ($tag_content)); next; } } } $xml_doc->toString; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3::Request::Role::XML::Content - Role providing XML content =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Net/Amazon/S3.pm0000644000175000017500000007626414264646670016356 0ustar branobranopackage Net::Amazon::S3; # ABSTRACT: Use the Amazon S3 - Simple Storage Service $Net::Amazon::S3::VERSION = '0.991'; use Moose 0.85; use MooseX::StrictConstructor 0.16; use Carp; use Digest::HMAC_SHA1; use Safe::Isa (); use Net::Amazon::S3::Bucket; use Net::Amazon::S3::Client; use Net::Amazon::S3::Client::Bucket; use Net::Amazon::S3::Client::Object; use Net::Amazon::S3::Error::Handler::Legacy; use Net::Amazon::S3::HTTPRequest; use Net::Amazon::S3::Request; use Net::Amazon::S3::Response; use Net::Amazon::S3::Operation::Bucket::Acl::Fetch; use Net::Amazon::S3::Operation::Bucket::Acl::Set; use Net::Amazon::S3::Operation::Bucket::Create; use Net::Amazon::S3::Operation::Bucket::Delete; use Net::Amazon::S3::Operation::Bucket::Location; use Net::Amazon::S3::Operation::Bucket::Tags::Add; use Net::Amazon::S3::Operation::Bucket::Tags::Delete; use Net::Amazon::S3::Operation::Buckets::List; use Net::Amazon::S3::Operation::Object::Acl::Fetch; use Net::Amazon::S3::Operation::Object::Acl::Set; use Net::Amazon::S3::Operation::Object::Add; use Net::Amazon::S3::Operation::Object::Delete; use Net::Amazon::S3::Operation::Object::Fetch; use Net::Amazon::S3::Operation::Object::Head; use Net::Amazon::S3::Operation::Object::Restore; use Net::Amazon::S3::Operation::Object::Tags::Add; use Net::Amazon::S3::Operation::Object::Tags::Delete; use Net::Amazon::S3::Operation::Object::Upload::Abort; use Net::Amazon::S3::Operation::Object::Upload::Complete; use Net::Amazon::S3::Operation::Object::Upload::Create; use Net::Amazon::S3::Operation::Object::Upload::Part; use Net::Amazon::S3::Operation::Object::Upload::Parts; use Net::Amazon::S3::Operation::Objects::Delete; use Net::Amazon::S3::Operation::Objects::List; use Net::Amazon::S3::Signature::V2; use Net::Amazon::S3::Signature::V4; use Net::Amazon::S3::Utils; use Net::Amazon::S3::Vendor; use Net::Amazon::S3::Vendor::Amazon; use LWP::UserAgent::Determined; use URI::Escape qw(uri_escape_utf8); my $AMAZON_S3_HOST = 's3.amazonaws.com'; has authorization_context => ( is => 'ro', isa => 'Net::Amazon::S3::Authorization', required => 0, handles => { aws_access_key_id => 'aws_access_key_id', aws_secret_access_key => 'aws_secret_access_key', aws_session_token => 'aws_session_token', }, ); has vendor => ( is => 'ro', isa => 'Net::Amazon::S3::Vendor', required => 1, handles => { authorization_method => 'authorization_method', host => 'host', secure => 'use_https', use_virtual_host => 'use_virtual_host', }, ); has 'timeout' => ( is => 'ro', isa => 'Num', required => 0, default => 30 ); has 'retry' => ( is => 'ro', isa => 'Bool', required => 0, default => 0 ); has 'ua' => is => 'rw' => isa => 'LWP::UserAgent' => required => 0 => lazy => 1 => builder => '_build_ua' ; has 'err' => ( is => 'rw', isa => 'Maybe[Str]', required => 0 ); has 'errstr' => ( is => 'rw', isa => 'Maybe[Str]', required => 0 ); has keep_alive_cache_size => ( is => 'ro', isa => 'Int', required => 0, default => 10 ); has error_handler_class => ( is => 'ro', lazy => 1, default => 'Net::Amazon::S3::Error::Handler::Legacy', ); has error_handler => ( is => 'ro', lazy => 1, default => sub { $_[0]->error_handler_class->new (s3 => $_[0]) }, ); has bucket_class => ( is => 'ro', init_arg => undef, lazy => 1, default => 'Net::Amazon::S3::Bucket', ); sub _build_arg_authorization_context { my ($args) = @_; my $aws_access_key_id = delete $args->{aws_access_key_id}; my $aws_secret_access_key = delete $args->{aws_secret_access_key}; my $use_iam_role = delete $args->{use_iam_role}; my $aws_session_token = delete $args->{aws_session_token}; if ($args->{authorization_context}) { return $args->{authorization_context}; } if ($use_iam_role || $aws_session_token) { require Net::Amazon::S3::Authorization::IAM; return Net::Amazon::S3::Authorization::IAM->new ( aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, aws_session_token => $aws_session_token, ) } require Net::Amazon::S3::Authorization::Basic; return Net::Amazon::S3::Authorization::Basic->new ( aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, ); } sub _build_arg_vendor { my ($args) = @_; my %backward = map { $_ => delete $args->{$_} } grep { exists $args->{$_} } qw[ host secure use_virtual_host authorization_method ] ; return $args->{vendor} if $args->{vendor}; $backward{host} = $AMAZON_S3_HOST unless exists $backward{host}; $backward{use_https} = delete $backward{secure} if exists $backward{secure}; my $vendor_class = $backward{host} eq $AMAZON_S3_HOST ? 'Net::Amazon::S3::Vendor::Amazon' : 'Net::Amazon::S3::Vendor' ; return $vendor_class->new (%backward); } around BUILDARGS => sub { my ($orig, $class) = (shift, shift); my $args = $class->$orig (@_); # support compat authorization arguments $args->{authorization_context} = _build_arg_authorization_context $args; $args->{vendor} = _build_arg_vendor $args; $args; }; sub _build_ua { my $self = shift; my $ua; if ( $self->retry ) { $ua = LWP::UserAgent::Determined->new( keep_alive => $self->keep_alive_cache_size, requests_redirectable => [qw(GET HEAD DELETE PUT POST)], ); $ua->timing('1,2,4,8,16,32'); } else { $ua = LWP::UserAgent->new( keep_alive => $self->keep_alive_cache_size, requests_redirectable => [qw(GET HEAD DELETE PUT POST)], ); } $ua->timeout( $self->timeout ); $ua->env_proxy; return $ua; } sub buckets { my ($self, %args) = @_; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Buckets::List', %args, ); return unless $response->is_success; my $owner_id = $response->owner_id;; my $owner_displayname = $response->owner_displayname; my @buckets; foreach my $bucket ($response->buckets) { push @buckets, $self->bucket_class->new ( account => $self, bucket => $bucket->{name}, creation_date => $bucket->{creation_date}, ); } return +{ owner_id => $owner_id, owner_displayname => $owner_displayname, buckets => \@buckets, }; } sub add_bucket { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket (\@_); my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Create', %args, ); return unless $response->is_success; return $self->bucket ($args{bucket}); } sub bucket { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket (\@_); return $args{bucket} if $args{bucket}->$Safe::Isa::_isa ($self->bucket_class); return $self->bucket_class->new ({ account => $self, bucket => $args{bucket}, (region => $args{region}) x defined $args{region}, }); } sub delete_bucket { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket (\@_); croak 'must specify bucket' unless defined $args{bucket}; my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Bucket::Delete', %args, ); return unless $response->is_success; return 1; } sub list_bucket { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket (\@_); my $response = $self->_perform_operation ( 'Net::Amazon::S3::Operation::Objects::List', %args, ); return unless $response->is_success; my $return = { bucket => $response->bucket, prefix => $response->prefix, marker => $response->marker, next_marker => $response->next_marker, max_keys => $response->max_keys, is_truncated => $response->is_truncated, }; my @keys; foreach my $node ($response->contents) { push @keys, { key => $node->{key}, last_modified => $node->{last_modified}, etag => $node->{etag}, size => $node->{size}, storage_class => $node->{storage_class}, owner_id => $node->{owner}{id}, owner_displayname => $node->{owner}{displayname}, }; } $return->{keys} = \@keys; if ( $args{delimiter} ) { $return->{common_prefixes} = [ $response->common_prefixes ]; } return $return; } sub list_bucket_all { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket (\@_); my $bucket = $args{bucket}; croak 'must specify bucket' unless $bucket; my $response = $self->list_bucket (%args); return $response unless $response->{is_truncated}; my $all = $response; while (1) { my $next_marker = $response->{next_marker} || $response->{keys}->[-1]->{key}; $response = $self->list_bucket ( %args, marker => $next_marker, ); push @{ $all->{keys} }, @{ $response->{keys} }; last unless $response->{is_truncated}; } delete $all->{is_truncated}; delete $all->{next_marker}; return $all; } # compat wrapper; deprecated as of 2005-03-23 sub add_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket_and_object (\@_); my $bucket = $self->bucket (delete $args{bucket}); return $bucket->add_key (%args); } # compat wrapper; deprecated as of 2005-03-23 sub get_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket_and_object (\@_); my $bucket = $self->bucket (delete $args{bucket}); return $bucket->get_key (%args); } # compat wrapper; deprecated as of 2005-03-23 sub head_key { my ( $self, $conf ) = @_; my $bucket = $self->bucket (delete $conf->{bucket}); return $bucket->head_key( $conf->{key} ); } # compat wrapper; deprecated as of 2005-03-23 sub delete_key { my $self = shift; my %args = Net::Amazon::S3::Utils->parse_arguments_with_bucket_and_object (\@_); my $bucket = $self->bucket (delete $args{bucket}); return $bucket->delete_key (%args); } sub _perform_operation { my ($self, $operation, %params) = @_; my $error_handler = delete $params{error_handler}; $error_handler = $self->error_handler unless defined $error_handler; my $request_class = $operation . '::Request'; my $response_class = $operation . '::Response'; my $filename = delete $params{filename}; my $request = $request_class->new (s3 => $self, %params); my $http_response = $self->ua->request ($request->http_request, $filename); my $response = $response_class->new (http_response => $http_response); $error_handler->handle_error ($response); return $response; } sub _urlencode { my ( $self, $unencoded ) = @_; return uri_escape_utf8( $unencoded, '^A-Za-z0-9_~\-\.' ); } __PACKAGE__->meta->make_immutable; 1; __END__ =pod =encoding UTF-8 =head1 NAME Net::Amazon::S3 - Use the Amazon S3 - Simple Storage Service =head1 VERSION version 0.991 =head1 SYNOPSIS use Net::Amazon::S3; use Net::Amazon::S3::Authorization::Basic; use Net::Amazon::S3::Authorization::IAM; my $aws_access_key_id = 'fill me in'; my $aws_secret_access_key = 'fill me in too'; my $s3 = Net::Amazon::S3->new ( authorization_context => Net::Amazon::S3::Authorization::Basic->new ( aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, ), retry => 1, ); # or use an IAM role. my $s3 = Net::Amazon::S3->new ( authorization_context => Net::Amazon::S3::Authorization::IAM->new ( aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, ), retry => 1, ); # a bucket is a globally-unique directory # list all buckets that i own my $response = $s3->buckets; foreach my $bucket ( @{ $response->{buckets} } ) { print "You have a bucket: " . $bucket->bucket . "\n"; } # create a new bucket my $bucketname = 'acmes_photo_backups'; my $bucket = $s3->add_bucket( { bucket => $bucketname } ) or die $s3->err . ": " . $s3->errstr; # or use an existing bucket $bucket = $s3->bucket($bucketname); # store a file in the bucket $bucket->add_key_filename( '1.JPG', 'DSC06256.JPG', { content_type => 'image/jpeg', }, ) or die $s3->err . ": " . $s3->errstr; # store a value in the bucket $bucket->add_key( 'reminder.txt', 'this is where my photos are backed up' ) or die $s3->err . ": " . $s3->errstr; # list files in the bucket $response = $bucket->list_all or die $s3->err . ": " . $s3->errstr; foreach my $key ( @{ $response->{keys} } ) { my $key_name = $key->{key}; my $key_size = $key->{size}; print "Bucket contains key '$key_name' of size $key_size\n"; } # fetch file from the bucket $response = $bucket->get_key_filename( '1.JPG', 'GET', 'backup.jpg' ) or die $s3->err . ": " . $s3->errstr; # fetch value from the bucket $response = $bucket->get_key('reminder.txt') or die $s3->err . ": " . $s3->errstr; print "reminder.txt:\n"; print " content length: " . $response->{content_length} . "\n"; print " content type: " . $response->{content_type} . "\n"; print " etag: " . $response->{content_type} . "\n"; print " content: " . $response->{value} . "\n"; # delete keys $bucket->delete_key('reminder.txt') or die $s3->err . ": " . $s3->errstr; $bucket->delete_key('1.JPG') or die $s3->err . ": " . $s3->errstr; # and finally delete the bucket $bucket->delete_bucket or die $s3->err . ": " . $s3->errstr; =head1 DESCRIPTION This module provides a Perlish interface to Amazon S3. From the developer blurb: "Amazon S3 is storage for the Internet. It is designed to make web-scale computing easier for developers. Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of web sites. The service aims to maximize benefits of scale and to pass those benefits on to developers". To find out more about S3, please visit: http://s3.amazonaws.com/ To use this module you will need to sign up to Amazon Web Services and provide an "Access Key ID" and " Secret Access Key". If you use this module, you will incurr costs as specified by Amazon. Please check the costs. If you use this module with your Access Key ID and Secret Access Key you must be responsible for these costs. I highly recommend reading all about S3, but in a nutshell data is stored in values. Values are referenced by keys, and keys are stored in buckets. Bucket names are global. Note: This is the legacy interface, please check out L instead. Development of this code happens here: https://github.com/rustyconover/net-amazon-s3 =head2 Bucket names with dots, HTTPS, and Signature V4 At the moment Amazon S3 doesn't play well with HTTPS and virtual bucket hosts if bucket name contains dots. Due the current implementation of Signature V4 handling you should use workaround consisting of usage of region hostnames my $bucket_region = $global_s3->bucket ($bucket)->_head_region; my $region_s3 = Net::Amazon:S3->new ( ..., vendor => Net::Amazon::S3::Vendor::Amazon->new ( host => "s3-$bucket_region.amazonaws.com", use_virtual_host => 0, ), ); my $bucket = $region_s3->bucket ($bucket); And use bucket instance / region s3 connection. =head1 METHODS =head2 new Create a new S3 client object. Takes some arguments: =over =item authorization_context Class that provides authorization information. See one of available implementations for more =over =item L =item L =back =item vendor Instance of L holding vendor specific deviations. S3 became widely used object storage protocol with many vendors providing different feature sets and different compatibility level. One common difference is bucket's HEAD request to determine its region. To maintain currently known differences along with any differencies that may rise in feature it's better to hold vendor specification in dedicated classes. This also allows users to build their own fine-tuned vendor classes. =over =item L =item L =back =item aws_access_key_id Deprecated. When used it's used to create authorization context. Use your Access Key ID as the value of the AWSAccessKeyId parameter in requests you send to Amazon Web Services (when required). Your Access Key ID identifies you as the party responsible for the request. =item aws_secret_access_key Deprecated. When used it's used to create authorization context. Since your Access Key ID is not encrypted in requests to AWS, it could be discovered and used by anyone. Services that are not free require you to provide additional information, a request signature, to verify that a request containing your unique Access Key ID could only have come from you. DO NOT INCLUDE THIS IN SCRIPTS OR APPLICATIONS YOU DISTRIBUTE. YOU'LL BE SORRY =item aws_session_token Deprecated. When used it's used to create authorization context. If you are using temporary credentials provided by the AWS Security Token Service, set the token here, and it will be added to the request in order to authenticate it. =item use_iam_role Deprecated. When used it's used to create authorization context. If you'd like to use IAM provided temporary credentials, pass this option with a true value. =item secure Deprecated. Set this to C<0> if you don't want to use SSL-encrypted connections when talking to S3. Defaults to C<1>. To use SSL-encrypted connections, LWP::Protocol::https is required. See L<#vendor> and L. =item keep_alive_cache_size Set this to C<0> to disable Keep-Alives. Default is C<10>. =item timeout How many seconds should your script wait before bailing on a request to S3? Defaults to 30. =item retry If this library should retry upon errors. This option is recommended. This uses exponential backoff with retries after 1, 2, 4, 8, 16, 32 seconds, as recommended by Amazon. Defaults to off. When retry is on, request will be automatically retried when one of following HTTP statuses happens =over =item 408 - Request Timeout =item 500 - Internal Server Error =item 502 - Bad Gateway =item 503 - Service Unavailable =item 504 - Gateway Timeout =back For more details see L. =item host Deprecated. The S3 host endpoint to use. Defaults to 's3.amazonaws.com'. This allows you to connect to any S3-compatible host. See L<#vendor> and L. =item use_virtual_host Deprecated. Use the virtual host method ('bucketname.s3.amazonaws.com') instead of specifying the bucket at the first part of the path. This is particularly useful if you want to access buckets not located in the US-Standard region (such as EU, Asia Pacific or South America). See L for the pros and cons. See L<#vendor> and L. =item authorization_method Deprecated. Authorization implementation package name. This library provides L<< Net::Amazon::S3::Signature::V2 >> and L<< Net::Amazon::S3::Signature::V4 >> Default is Signature 4 if host is C<< s3.amazonaws.com >>, Signature 2 otherwise See L<#vendor> and L. =item error_handler_class Error handler class name (package name), see L<< Net::Amazon::S3::Error::Handler >> for more. Default: L<< Net::Amazon::S3::Error::Handler::Legacy >> =item error_handler Instance of error handler class. =back =head3 Notes When using L in child processes using fork (such as in combination with the excellent L) you should create the S3 object in each child, use a fresh LWP::UserAgent in each child, or disable the L in the parent: $s3->ua( LWP::UserAgent->new( keep_alive => 0, requests_redirectable => [qw'GET HEAD DELETE PUT POST'] ); =head2 buckets Returns undef on error, else hashref of results =head2 add_bucket # Create new bucket with default location my $bucket = $s3->add_bucket ('new-bucket'); # Create new bucket in another location my $bucket = $s3->add_bucket ('new-bucket', location_constraint => 'eu-west-1'); my $bucket = $s3->add_bucket ('new-bucket', { location_constraint => 'eu-west-1' }); my $bucket = $s3->add_bucket (bucket => 'new-bucket', location_constraint => 'eu-west-1'); my $bucket = $s3->add_bucket ({ bucket => 'new-bucket', location_constraint => 'eu-west-1' }); Method creates and returns new bucket. In case of error it reports it and returns C (refer L). Recognized positional arguments (refer L) =over =item bucket Required, recognized as positional. The name of the bucket you want to add. =back Recognized optional arguments =over =item acl acl => 'private' acl => Net::Amazon::S3::ACL::Canned->PRIVATE acl => Net::Amazon::S3::ACL::Set->grant_read (email => 'foo@bar.baz') I Set ACL to the newly created bucket. Refer L for possibilities. =item acl_short (deprecated) I When specified its value is used to populate C argument (unless it exists). =item location_constraint Optional. Sets the location constraint of the new bucket. If left unspecified, the default S3 datacenter location will be used. This library recognizes regions according Amazon S3 documentation =over =item → L =item → L =back =back Provides operation L. =head2 bucket BUCKET # build bucket with guessed region $s3->bucket ('foo'); $s3->bucket (bucket => 'foo'); $s3->bucket (name => 'foo'); # build with explicit region $s3->bucket ('foo', region => 'bar'); Returns an (unverified) bucket object from an account. Does no network access. However, when guessing region, C operation may be called before first network access. Region is mandatory when using Signature V4 authorization, which is default for AWS. AWS limits number of HTTP requests, see L =head2 delete_bucket $s3->delete_bucket ($bucket); $s3->delete_bucket (bucket => $bucket); Deletes bucket from account. Returns C if the bucket is successfully deleted. Returns C and reports an error otherwise (refer L) Positional arguments (refer L) =over =item bucket Required. The name of the bucket or L instance you want to delete. =back Provides operation L<"DeleteBucket"|https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html> =head2 list_bucket List all keys in this bucket. Takes a hashref of arguments: MANDATORY =over =item bucket The name of the bucket you want to list keys on =back OPTIONAL =over =item prefix Restricts the response to only contain results that begin with the specified prefix. If you omit this optional argument, the value of prefix for your query will be the empty string. In other words, the results will be not be restricted by prefix. =item delimiter If this optional, Unicode string parameter is included with your request, then keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection. These rolled-up keys are not returned elsewhere in the response. For example, with prefix="USA/" and delimiter="/", the matching keys "USA/Oregon/Salem" and "USA/Oregon/Portland" would be summarized in the response as a single "USA/Oregon" element in the CommonPrefixes collection. If an otherwise matching key does not contain the delimiter after the prefix, it appears in the Contents collection. Each element in the CommonPrefixes collection counts as one against the MaxKeys limit. The rolled-up keys represented by each CommonPrefixes element do not. If the Delimiter parameter is not present in your request, keys in the result set will not be rolled-up and neither the CommonPrefixes collection nor the NextMarker element will be present in the response. =item max-keys This optional argument limits the number of results returned in response to your query. Amazon S3 will return no more than this number of results, but possibly less. Even if max-keys is not specified, Amazon S3 will limit the number of results in the response. Check the IsTruncated flag to see if your results are incomplete. If so, use the Marker parameter to request the next page of results. For the purpose of counting max-keys, a 'result' is either a key in the 'Contents' collection, or a delimited prefix in the 'CommonPrefixes' collection. So for delimiter requests, max-keys limits the total number of list results, not just the number of keys. =item marker This optional parameter enables pagination of large result sets. C specifies where in the result set to resume listing. It restricts the response to only contain results that occur alphabetically after the value of marker. To retrieve the next page of results, use the last key from the current page of results as the marker in your next request. See also C, below. If C is omitted,the first page of results is returned. =back Returns undef on error and a hashref of data on success: The hashref looks like this: { bucket => $bucket_name, prefix => $bucket_prefix, common_prefixes => [$prefix1,$prefix2,...] marker => $bucket_marker, next_marker => $bucket_next_available_marker, max_keys => $bucket_max_keys, is_truncated => $bucket_is_truncated_boolean keys => [$key1,$key2,...] } Explanation of bits of that: =over =item common_prefixes If list_bucket was requested with a delimiter, common_prefixes will contain a list of prefixes matching that delimiter. Drill down into these prefixes by making another request with the prefix parameter. =item is_truncated B flag that indicates whether or not all results of your query were returned in this response. If your results were truncated, you can make a follow-up paginated request using the Marker parameter to retrieve the rest of the results. =item next_marker A convenience element, useful when paginating with delimiters. The value of C, if present, is the largest (alphabetically) of all key names and all CommonPrefixes prefixes in the response. If the C flag is set, request the next page of results by setting C to the value of C. This element is only present in the response if the C parameter was sent with the request. =back Each key is a hashref that looks like this: { key => $key, last_modified => $last_mod_date, etag => $etag, # An MD5 sum of the stored content. size => $size, # Bytes storage_class => $storage_class # Doc? owner_id => $owner_id, owner_displayname => $owner_name } =head2 list_bucket_all List all keys in this bucket without having to worry about 'marker'. This is a convenience method, but may make multiple requests to S3 under the hood. Takes the same arguments as list_bucket. =head2 _perform_operation my $response = $s3->_perform_operation ('Operation' => ( # ... operation request parameters )); Internal operation implementation method, takes request construction parameters, performs necessary HTTP requests(s) and returns Response instance. Method takes same named parameters as realted Request class. Method provides available contextual parameters by default (eg s3, bucket) Method invokes contextual error handler. =head1 CALLING CONVENTION I - calling convention extentend In order to make method calls somehow consistent, backward compatible, and extendable, API's methods support multiple ways how to provide their arguments =over =item plain named arguments (preferred) method (named => 'argument', another => 'argument'); =item trailing configuration hash method ({ named => 'argument', another => 'argument' }); method (positional, { named => 'argument', another => 'argument' } ); Last argument of every method can be configuration hash, treated as additional named arguments. Can be combined with named arguments. =item positional arguments with optional named arguments method (positional, named => 'argument', another => 'argument'); method (positional, { named => 'argument', another => 'argument' } ); For methods supporting mandatory positional arguments additional named arguments and/or configuration hash is supported. Named arguments or configuration hash can specify value of positional arguments as well removing it from list of required positional arguments for given call (see example) $s3->bucket->add_key ('key', 'value', acl => $acl); $s3->bucket->add_key ('value', key => 'key', acl => $acl); $s3->bucket->add_key (key => 'key', value => 'value', acl => $acl); =back =head1 ERROR HANDLING L supports pluggable error handling via L. When response ends up with an error, every method reports it, and in case it receives control back (no exception), it returns C. Default error handling for L is L which (mostly) sets C and C. =head1 LICENSE This module contains code modified from Amazon that contains the following notice: # This software code is made available "AS IS" without warranties of any # kind. You may copy, display, modify and redistribute the software # code either by itself or as incorporated into your code; provided that # you do not remove any proprietary notices. Your use of this software # code is at your own risk and you waive any claim against Amazon # Digital Services, Inc. or its affiliates with respect to your use of # this software code. (c) 2006 Amazon Digital Services, Inc. or its # affiliates. =head1 TESTING Testing S3 is a tricky thing. Amazon wants to charge you a bit of money each time you use their service. And yes, testing counts as using. Because of this, the application's test suite skips anything approaching a real test unless you set these three environment variables: =over =item AMAZON_S3_EXPENSIVE_TESTS Doesn't matter what you set it to. Just has to be set =item AWS_ACCESS_KEY_ID Your AWS access key =item AWS_ACCESS_KEY_SECRET Your AWS sekkr1t passkey. Be forewarned that setting this environment variable on a shared system might leak that information to another user. Be careful. =back =head1 AUTHOR Leon Brocard and unknown Amazon Digital Services programmers. Brad Fitzpatrick - return values, Bucket object Pedro Figueiredo - since 0.54 Branislav Zahradník - since v0.81 =head1 SEE ALSO L =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/0000775000175000017500000000000014264646670014751 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/0000775000175000017500000000000014264646670016527 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/Net/0000775000175000017500000000000014264646670017255 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/0000775000175000017500000000000014264646670020502 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/0000775000175000017500000000000014264646670020767 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Request.pm0000644000175000017500000001124214264646670022753 0ustar branobranopackage Shared::Examples::Net::Amazon::S3::Request; # ABSTRACT: used for testing and as example $Shared::Examples::Net::Amazon::S3::Request::VERSION = '0.991'; use strict; use warnings; use parent qw[ Exporter::Tiny ]; use Test::More; use Test::Deep; use Moose qw[]; use Moose::Object; use Moose::Util; use XML::LibXML; use Net::Amazon::S3; use Net::Amazon::S3::Bucket; use Shared::Examples::Net::Amazon::S3; our @EXPORT_OK = ( qw[ behaves_like_net_amazon_s3_request ], qw[ expect_request_class ], qw[ expect_request_instance ], ); sub _canonical_xml { my ($xml) = @_; return $xml unless $xml; return $xml if ref $xml; my $canonical = eval { XML::LibXML->load_xml ( string => $xml, no_blanks => 1, )->toStringC14N }; return $xml unless defined $canonical; return $canonical; } sub _test_meta_build_http_request { my ($self, %params) = @_; return $self->_build_signed_request (%params); } sub _test_class { my ($request_class, %params) = @_; $params{superclasses} ||= []; $params{methods}{_build_http_request} = \& _test_meta_build_http_request; push @{ $params{superclasses} }, $request_class; return Moose::Meta::Class->create_anon_class (%params); } sub expect_request_class { my ($request_class) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return use_ok $request_class; } sub expect_request_instance { my (%params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; my %with = map +( substr ($_, 5) => delete $params{$_} ), grep m/^with_/, keys %params ; $with{s3} = Shared::Examples::Net::Amazon::S3::s3_api_with_signature_2 ( host => $params{with_host} || 's3.amazonaws.com', ); my $test_class = _test_class $params{request_class}, map +( $_ => $params{$_} ), grep exists $params{$_}, qw [ roles ], ; my $request = eval { $test_class->name->new (%with) }; my $error = $@; if (exists $params{throws}) { if (defined $request) { fail "create instance should fail"; } else { cmp_deeply $error, $params{throws}, "create instance should fail"; } } else { ok defined $request, "should create (mocked) instance of $params{request_class}" or diag $error; } return $request; } sub expect_request_uri { my ($request, $expected) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return cmp_deeply $request->http_request->request_uri, $expected, "it builds expected request uri" ; } sub expect_request_method { my ($request, $expected) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return cmp_deeply $request->http_request->method, $expected, "it builds expected request method" ; } sub expect_request_headers { my ($request, $expected) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return cmp_deeply $request->http_request->headers, $expected, "it builds expected request headers" ; } sub expect_request_content { my ($request, $expected) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; # XML builders doesn't need to produce whitespaces for readability # wherease test expectation should be as readable as possible # compare canonicalized xml strings than return is _canonical_xml ($request->http_request->content), _canonical_xml ($expected), "it builds expected request XML content" ; } sub behaves_like_net_amazon_s3_request { my ($title, %params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; subtest $title => sub { plan tests => 2 + scalar grep exists $params{$_}, qw[ expect_request_uri ], qw[ expect_request_method ], qw[ expect_request_headers ], qw[ expect_request_content ], ; expect_request_class $params{request_class}; my $request = expect_request_instance %params; expect_request_uri $request => $params{expect_request_uri} if exists $params{expect_request_uri}; expect_request_method $request => $params{expect_request_method} if exists $params{expect_request_method}; expect_request_headers $request => $params{expect_request_headers} if exists $params{expect_request_headers}; expect_request_content $request => $params{expect_request_content} if exists $params{expect_request_content}; }; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Request - used for testing and as example =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Client.pm0000644000175000017500000001555014264646670022547 0ustar branobranopackage Shared::Examples::Net::Amazon::S3::Client; # ABSTRACT: used for testing and as example $Shared::Examples::Net::Amazon::S3::Client::VERSION = '0.991'; use strict; use warnings; use parent qw[ Exporter::Tiny ]; use Hash::Util; use HTTP::Response; use HTTP::Status; use Sub::Override; use Test::Deep; use Test::More; use Net::Amazon::S3::Client; use Shared::Examples::Net::Amazon::S3; our @EXPORT_OK = ( qw[ expect_signed_uri ], qw[ expect_client_list_all_my_buckets ], qw[ expect_client_bucket_acl_get ], qw[ expect_client_bucket_acl_set ], qw[ expect_client_bucket_create ], qw[ expect_client_bucket_delete ], qw[ expect_client_bucket_objects_delete ], qw[ expect_client_bucket_objects_list ], qw[ expect_client_bucket_tags_add ], qw[ expect_client_bucket_tags_delete ], qw[ expect_client_object_acl_set ], qw[ expect_client_object_create ], qw[ expect_client_object_delete ], qw[ expect_client_object_fetch ], qw[ expect_client_object_head ], qw[ expect_client_object_tags_add], qw[ expect_client_object_tags_delete], ); *with_fixture = *Shared::Examples::Net::Amazon::S3::with_fixture; sub _exporter_expand_sub { my ($self, $name, $args, $globals) = @_; my $s3_operation = $name; $s3_operation =~ s/_client_/_operation_/; return +( $name => eval <<"GEN_SUB" ); sub { push \@_, -shared_examples => __PACKAGE__; goto \\& Shared::Examples::Net::Amazon::S3::$s3_operation; } GEN_SUB } sub _default_with_api { my ($self, $params) = @_; $params->{with_client} ||= Net::Amazon::S3::Client->new ( s3 => Shared::Examples::Net::Amazon::S3::s3_api_with_signature_2 () ); } sub _mock_http_response { my ($self, $api, %params) = @_; Shared::Examples::Net::Amazon::S3->s3_api_mock_http_response ( $api->s3, %params, ) } sub expect_signed_uri { my ($title, %params) = @_; Hash::Util::lock_keys %params, qw[ with_client ], qw[ with_bucket ], qw[ with_region ], qw[ with_key ], qw[ with_expire_at ], qw[ with_method ], qw[ expect_uri ], ; my $guard = Sub::Override->new ( 'Net::Amazon::S3::Bucket::region' => sub { $params{with_region } }, ); my $got = $params{with_client} ->bucket ( name => $params{with_bucket}, ) ->object ( key => $params{with_key}, expires => $params{with_expire_at}, ) ->query_string_authentication_uri_for_method ( $params{with_method} || 'GET', ) ; cmp_deeply $got, $params{expect_uri}, $title; } sub operation_list_all_my_buckets { my ($self, %params) = @_; [ $_[0]->buckets ]; } sub operation_bucket_acl_get { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->acl ; } sub operation_bucket_create { my ($self, %params) = @_; $self->create_bucket( name => $params{with_bucket}, (acl => $params{with_acl}) x!! exists $params{with_acl}, (acl_short => $params{with_acl_short}) x!! exists $params{with_acl_short}, (location_constraint => $params{with_region}) x!! exists $params{with_region}, ); } sub operation_bucket_delete { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->delete ; } sub operation_bucket_objects_list { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->list ({ bucket => $params{with_bucket}, delimiter => $params{with_delimiter}, max_keys => $params{with_max_keys}, marker => $params{with_marker}, prefix => $params{with_prefix}, }) ; } sub operation_bucket_objects_delete { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->delete_multi_object (@{ $params{with_keys} }) ; } sub operation_object_create { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->object ( key => $params{with_key}, map +($_ => $params{"with_$_"}), grep exists $params{"with_$_"}, ( qw[ cache_control ], qw[ content_disposition ], qw[ content_encoding ], qw[ content_type ], qw[ encryption ], qw[ expires ], qw[ storage_class ], qw[ user_metadata ], qw[ acl ], qw[ acl_short ], ) ) ->${\ (ref $params{with_value} ? 'put_filename' : 'put' ) } ( ref $params{with_value} ? ${ $params{with_value} } : $params{with_value} ) ; } sub operation_object_delete { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->object (key => $params{with_key}) ->delete ; } sub operation_object_fetch { my ($self, %params) = @_; my $object = $self ->bucket (name => $params{with_bucket}) ->object (key => $params{with_key}) ; $object = $object->range ($params{with_range}) if $params{with_range}; $object->get; } sub operation_object_head { my ($self, %params) = @_; my $method = $params{-method} // 'exists'; $self ->bucket (name => $params{with_bucket}) ->object (key => $params{with_key}) ->$method ; } sub operation_bucket_acl_set { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->set_acl ( (acl => $params{with_acl}) x!! exists $params{with_acl}, (acl_short => $params{with_acl_short}) x!! exists $params{with_acl_short}, (acl_xml => $params{with_acl_xml}) x!! exists $params{with_acl_xml}, ) ; } sub operation_object_acl_set { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->object (key => $params{with_key}) ->set_acl ( (acl => $params{with_acl}) x!! exists $params{with_acl}, (acl_short => $params{with_acl_short}) x!! exists $params{with_acl_short}, (acl_xml => $params{with_acl_xml}) x!! exists $params{with_acl_xml}, ) ; } sub operation_bucket_tags_add { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->add_tags ( tags => $params{with_tags}, ) ; } sub operation_object_tags_add { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->object (key => $params{with_key}) ->add_tags ( tags => $params{with_tags}, (version_id => $params{with_version_id}) x!! defined $params{with_version_id}, ) ; } sub operation_bucket_tags_delete { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->delete_tags ; } sub operation_object_tags_delete { my ($self, %params) = @_; $self ->bucket (name => $params{with_bucket}) ->object (key => $params{with_key}) ->delete_tags ( (version_id => $params{with_version_id}) x!! defined $params{with_version_id}, ) ; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Client - used for testing and as example =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/API.pm0000644000175000017500000001547314264646670021746 0ustar branobranopackage Shared::Examples::Net::Amazon::S3::API; # ABSTRACT: used for testing and as example $Shared::Examples::Net::Amazon::S3::API::VERSION = '0.991'; use strict; use warnings; use parent qw[ Exporter::Tiny ]; use Hash::Util; use Test::Deep; use Test::More; use Net::Amazon::S3; use Shared::Examples::Net::Amazon::S3; our @EXPORT_OK = ( qw[ expect_signed_uri ], qw[ expect_api_list_all_my_buckets ], qw[ expect_api_bucket_acl_get ], qw[ expect_api_bucket_acl_set ], qw[ expect_api_bucket_create ], qw[ expect_api_bucket_delete ], qw[ expect_api_bucket_objects_delete ], qw[ expect_api_bucket_objects_list ], qw[ expect_api_bucket_tags_add ], qw[ expect_api_bucket_tags_delete ], qw[ expect_api_object_acl_get ], qw[ expect_api_object_acl_set ], qw[ expect_api_object_create ], qw[ expect_api_object_delete ], qw[ expect_api_object_fetch ], qw[ expect_api_object_head ], qw[ expect_api_object_tags_add ], qw[ expect_api_object_tags_delete ], qw[ with_fixture ], ); *with_fixture = *Shared::Examples::Net::Amazon::S3::with_fixture; sub _exporter_expand_sub { my ($self, $name, $args, $globals) = @_; my $s3_operation = $name; $s3_operation =~ s/_api_/_operation_/; return +( $name => eval <<"GEN_SUB" ); sub { push \@_, -shared_examples => __PACKAGE__; goto \\& Shared::Examples::Net::Amazon::S3::$s3_operation; } GEN_SUB } sub _default_with_api { my ($self, $params) = @_; $params->{with_s3} ||= Shared::Examples::Net::Amazon::S3::s3_api_with_signature_2 (); } sub _mock_http_response { my (undef, $api, %params) = @_; Shared::Examples::Net::Amazon::S3->s3_api_mock_http_response ( $api, %params, ) } sub expect_signed_uri { my ($title, %params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; Hash::Util::lock_keys %params, qw[ with_s3 ], qw[ with_bucket ], qw[ with_region ], qw[ with_key ], qw[ with_expire_at ], qw[ with_method ], qw[ expect_uri ], ; my $got = Net::Amazon::S3::Bucket ->new ({ account => $params{with_s3}, bucket => $params{with_bucket}, region => $params{with_region}, }) ->query_string_authentication_uri ( $params{with_key}, $params{with_expire_at}, (method => $params{with_method}) x!! exists $params{with_method}, ); cmp_deeply $got, $params{expect_uri}, $title; } sub operation_list_all_my_buckets { my ($self, %params) = @_; $self->buckets; } sub operation_bucket_acl_get { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->get_acl ; } sub operation_bucket_acl_set { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->set_acl ({ (acl => $params{with_acl}) x!! exists $params{with_acl}, (acl_short => $params{with_acl_short}) x!! exists $params{with_acl_short}, (acl_xml => $params{with_acl_xml}) x!! exists $params{with_acl_xml}, }) ; } sub operation_bucket_create { my ($self, %params) = @_; $self ->add_bucket ({ bucket => $params{with_bucket}, (acl => $params{with_acl}) x!! exists $params{with_acl}, (acl_short => $params{with_acl_short}) x!! exists $params{with_acl_short}, (location_constraint => $params{with_region}) x!! exists $params{with_region}, (region => $params{with_region}) x!! exists $params{with_region}, }) ; } sub operation_bucket_delete { my ($self, %params) = @_; $self ->delete_bucket ({ bucket => $params{with_bucket}, }) ; } sub operation_bucket_objects_list { my ($self, %params) = @_; $self ->list_bucket ({ bucket => $params{with_bucket}, delimiter => $params{with_delimiter}, max_keys => $params{with_max_keys}, marker => $params{with_marker}, prefix => $params{with_prefix}, }) ; } sub operation_bucket_objects_delete { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->delete_multi_object (@{ $params{with_keys} }) ; } sub operation_object_acl_get { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->get_acl ($params{with_key}) ; } sub operation_object_acl_set { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->set_acl ({ key => $params{with_key}, (acl => $params{with_acl}) x!! exists $params{with_acl}, (acl_short => $params{with_acl_short}) x!! exists $params{with_acl_short}, (acl_xml => $params{with_acl_xml}) x!! exists $params{with_acl_xml}, }) ; } sub operation_object_create { my ($self, %params) = @_; my $headers = { %{ $params{with_headers} || {} } }; $headers->{$_} = $params{"with_$_"} for grep exists $params{"with_$_"}, qw[ cache_control ], qw[ content_disposition ], qw[ content_encoding ], qw[ content_type ], qw[ encryption ], qw[ expires ], qw[ acl_short ], qw[ acl ], ; $headers->{x_amz_storage_class} = $params{with_storage_class} if $params{with_storage_class}; $headers->{"x_amz_meta_\L$_"} = $params{with_user_metadata}{$_} for keys %{ $params{with_user_metadata} || {} }; $self ->bucket ($params{with_bucket}) ->add_key ( $params{with_key}, $params{with_value}, $headers, ) ; } sub operation_object_delete { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->delete_key ($params{with_key}) ; } sub operation_object_fetch { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->get_key ( $params{with_key}, 'GET', ({ range => $params{with_range} }) x exists $params{with_range}, ) ; } sub operation_object_head { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->head_key ($params{with_key}) ; } sub operation_bucket_tags_add { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->add_tags ({ tags => $params{with_tags}, }) ; } sub operation_object_tags_add { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->add_tags ({ key => $params{with_key}, tags => $params{with_tags}, (version_id => $params{with_version_id}) x!! defined $params{with_version_id}, }) ; } sub operation_bucket_tags_delete { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->delete_tags ; } sub operation_object_tags_delete { my ($self, %params) = @_; $self ->bucket ($params{with_bucket}) ->delete_tags ({ key => $params{with_key}, (version_id => $params{with_version_id}) x!! defined $params{with_version_id}, }) ; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::API - used for testing and as example =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/0000775000175000017500000000000014264646670022415 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/request/0000775000175000017500000000000014264646670024105 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/request/bucket_create_ca_central_1.pm0000644000175000017500000000202014264646670031626 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::request::bucket_create_ca_central_1 # ABSTRACT: Shared::Examples providing request fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; ca-central-1 XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::request::bucket_create_ca_central_1 - Shared::Examples providing request fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/0000775000175000017500000000000014264646670023546 5ustar branobranoNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/invalid_object_state.pm0000644000175000017500000000172314264646670030261 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::invalid_object_state # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::error_fixture InvalidObjectState => HTTP::Status::HTTP_FORBIDDEN, q, ; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::invalid_object_state - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/access_denied.pm0000644000175000017500000000160014264646670026650 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::access_denied # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::error_fixture AccessDenied => HTTP::Status::HTTP_FORBIDDEN, ; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::access_denied - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/invalid_bucket_name.pm0000644000175000017500000000162314264646670030067 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::invalid_bucket_name # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::error_fixture InvalidBucketName => HTTP::Status::HTTP_BAD_REQUEST, ; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::invalid_bucket_name - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/no_such_bucket.pm0000644000175000017500000000160214264646670027074 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::no_such_bucket # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::error_fixture NoSuchBucket => HTTP::Status::HTTP_NOT_FOUND, ; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::no_such_bucket - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/http_bad_request.pm0000644000175000017500000000152314264646670027440 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::http_bad_request # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; +{ response_code => HTTP::Status::HTTP_BAD_REQUEST, }; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::http_bad_request - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/bucket_already_exists.pm0000644000175000017500000000162614264646670030464 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::bucket_already_exists # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::error_fixture BucketAlreadyExists => HTTP::Status::HTTP_CONFLICT, ; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::bucket_already_exists - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/no_such_key.pm0000644000175000017500000000157114264646670026414 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::no_such_key # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::error_fixture NoSuchKey => HTTP::Status::HTTP_NOT_FOUND, ; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::no_such_key - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/error/bucket_not_empty.pm0000644000175000017500000000160714264646670027461 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::error::bucket_not_empty # ABSTRACT: Shared::Examples providing error fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::error_fixture BucketNotEmpty => HTTP::Status::HTTP_CONFLICT, ; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::error::bucket_not_empty - Shared::Examples providing error fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/0000775000175000017500000000000014264646670024253 5ustar branobrano././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_delete_quiet_without_errors.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_delete_quiet_w0000644000175000017500000000214314264646670032241 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_delete_quiet_without_errors # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; package Shared::Examples::Net::Amazon::S3::Fixture::bucket::objects::delete::quiet_without_errors; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture qw[ fixture ]; fixture content => <<'XML'; XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_delete_quiet_without_errors - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_google_cloud_storage.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_google0000644000175000017500000000352014264646670032157 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_google_clout_storage # ABSTRACT: Shared::Examples providing response fixture # Google uses different XML namespace uri # XML namespace is treated by an XML parser as a string, # its value is not used to fetch any data, so we need extra test use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; gcs-bucket next/marker/is/foo true path/to/value 1473499153424000 1 2017-04-21T22:06:03.413Z "1f52bad2879ca96dacd7a40f33001230" 742213 path/to/value2 1473499153424001 1 2018-04-21T22:06:03.413Z "1f52bad2889ca96dacd7a40f33001230" 742214 XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_google_clout_storage - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/acl.pm0000644000175000017500000000256314264646670025354 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::acl # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a CustomersName@amazon.com 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a CustomersName@amazon.com FULL_CONTROL XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::acl - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000015500000000000011604 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_filter.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_f0000644000175000017500000000336014264646670032165 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_filter # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; some-bucket N Ned 40 false Nelson 2006-01-01T12:00:00.000Z "828ef3fdfa96f00ad9f27c383fc9ac7f" 5 STANDARD bcaf161ca5fb16fd081034f webfile Neo 2006-01-01T12:00:00.000Z "828ef3fdfa96f00ad9f27c383fc9ac7f" 4 STANDARD bcaf1ffd86a5fb16fd081034f webfile XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_filter - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/http_ok_empty.pm0000644000175000017500000000156114264646670027500 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::http_ok_empty # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use HTTP::Status; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture ( content_type => undef, ); __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::http_ok_empty - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_delimiter.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_d0000644000175000017500000000303614264646670032163 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_delimiter # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; some-bucket 1000 / false sample.jpg 2011-02-26T01:56:20.000Z "bf1d737a4d46a19f3bced6905cc8b902" 142863 canonical-user-id display-name STANDARD photos/ XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_delimiter - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000016700000000000011607 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_filter_truncated.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_f0000644000175000017500000000340314264646670032163 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_filter_truncated # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; some-bucket N Ned 40 true Nelson 2006-01-01T12:00:00.000Z "828ef3fdfa96f00ad9f27c383fc9ac7f" 5 STANDARD bcaf161ca5fb16fd081034f webfile Neo 2006-01-01T12:00:00.000Z "828ef3fdfa96f00ad9f27c383fc9ac7f" 4 STANDARD bcaf1ffd86a5fb16fd081034f webfile XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_filter_truncated - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1.pm0000644000175000017500000000350514264646670031241 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1 # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; some-bucket 1000 false my-image.jpg 2009-10-12T17:50:30.000Z "fba9dede5f27731c9771645a39863328" 434234 STANDARD 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a mtd@amazon.com my-third-image.jpg 2009-10-12T17:50:30.000Z "1b2cf535f27731c974343645a3985328" 64994 STANDARD_IA 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a mtd@amazon.com XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1 - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000016600000000000011606 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_with_owner_displayname.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_with_own0000644000175000017500000000255014264646670032327 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::service_list_buckets_with_owner_displayname # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; bcaf1ffd86f461ca5fb16fd081034f webfile quotes 2006-02-03T16:45:09.000Z samples 2006-02-03T16:41:58.000Z XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::service_list_buckets_with_owner_displayname - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_prefix_and_delimiter.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_p0000644000175000017500000000253314264646670032200 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_prefix_and_delimiter # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; some-bucket photos/2006/ 1000 / false photos/2006/February/ photos/2006/January/ XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::bucket_objects_list_v1_with_prefix_and_delimiter - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000017100000000000011602 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_without_owner_displayname.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_without_0000644000175000017500000000251114264646670032330 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::service_list_buckets_without_owner_displayname # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; bcaf1ffd86f461ca5fb16fd081034f quotes 2006-02-03T16:45:09.000Z samples 2006-02-03T16:41:58.000Z XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::service_list_buckets_without_owner_displayname - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/create_multipart_upload_with_success.pmNet-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture/response/create_multipart_upload_with_0000644000175000017500000000216714264646670032304 0ustar branobrano# PODNAME: Shared::Examples::Net::Amazon::S3::Fixture::response::create-multipart-upload-with-success # ABSTRACT: Shared::Examples providing response fixture use strict; use warnings; use Shared::Examples::Net::Amazon::S3::Fixture; Shared::Examples::Net::Amazon::S3::Fixture::fixture content => <<'XML'; bucket-name key-name new-upload-id XML __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture::response::create-multipart-upload-with-success - Shared::Examples providing response fixture =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3/Fixture.pm0000644000175000017500000000337614264646670022762 0ustar branobranopackage Shared::Examples::Net::Amazon::S3::Fixture; # ABSTRACT: used for testing to provide test fixtures $Shared::Examples::Net::Amazon::S3::Fixture::VERSION = '0.991'; use parent qw[ Exporter::Tiny ]; use HTTP::Status; our @EXPORT_OK = ( qw[ error_fixture ], qw[ response_fixture ], qw[ fixture ], ); sub response_fixture { my (%params) = @_; return +{ content_type => 'application/xml', content_length => length $params{with_response_data}, response_code => HTTP::Status::HTTP_OK, %params, }; } sub fixture { my (%params) = @_; return +{ content_type => 'application/xml', content_length => length $params{with_response_data}, response_code => HTTP::Status::HTTP_OK, %params, }; } sub error_fixture { my ($error_code, $http_status, $error_message) = @_; unless (defined $error_message) { $error_message = $error_code; $error_message =~ s/ (?<=[[:lower:]]) ([[:upper:]])/ \L$1\E/gx; } return response_fixture ( response_code => $http_status, content => <<"XML", $error_code $error_message error message /some-resource 4442587FB7D0A2F9 XML ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3::Fixture - used for testing to provide test fixtures =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/lib/Shared/Examples/Net/Amazon/S3.pm0000644000175000017500000002463214264646670021332 0ustar branobranopackage Shared::Examples::Net::Amazon::S3; # ABSTRACT: used for testing and as example $Shared::Examples::Net::Amazon::S3::VERSION = '0.991'; use strict; use warnings; use parent qw[ Exporter::Tiny ]; use Hash::Util; use Ref::Util ( qw[ is_regexpref ], ); use Test::Deep; use Test::More; use Test::LWP::UserAgent; use Net::Amazon::S3; use Shared::Examples::Net::Amazon::S3::API; use Shared::Examples::Net::Amazon::S3::Client; use Shared::Examples::Net::Amazon::S3::Request; our @EXPORT_OK = ( qw[ s3_api_with_signature_4 ], qw[ s3_api_with_signature_2 ], qw[ expect_net_amazon_s3_feature ], qw[ expect_net_amazon_s3_operation ], qw[ expect_operation_list_all_my_buckets ], qw[ expect_operation_bucket_create ], qw[ expect_operation_bucket_delete ], qw[ with_fixture ], qw[ fixture ], qw[ with_response_fixture ], ); my %fixtures; sub fixture { my ($name) = @_; $fixtures{$name} = eval "require Shared::Examples::Net::Amazon::S3::Fixture::$name" unless defined $fixtures{$name}; die "Fixture $name not found: $@" unless defined $fixtures{$name}; return +{ %{ $fixtures{$name} } }; } sub with_fixture { my ($name) = @_; my $fixture = fixture ($name); return wantarray ? %$fixture : $fixture ; } sub with_response_fixture { my ($name) = @_; my $fixture = fixture ($name); my $response_fixture = {}; for my $key (keys %$fixture) { my $new_key; $new_key ||= "with_response_data" if $key eq 'content'; $new_key ||= "with_$key" if $key =~ m/^response/; $new_key ||= "with_response_header_$key"; $response_fixture->{$new_key} = $fixture->{$key}; } return wantarray ? %$response_fixture : $response_fixture ; } sub s3_api { my $api = Net::Amazon::S3->new (@_); $api->ua (Test::LWP::UserAgent->new (network_fallback => 0)); $api; } sub s3_api_mock_http_response { my ($self, $api, %params) = @_; $params{with_response_code} ||= HTTP::Status::HTTP_OK; my %headers = ( content_type => 'application/xml', ( map { m/^with_response_header_(.*)/; defined $1 && length $1 ? ($1 => $params{$_}) : () } keys %params ), %{ $params{with_response_headers} || {} }, ); $api->ua->map_response ( sub { ${ $params{into} } = $_[0]; 1; }, HTTP::Response->new ( $params{with_response_code}, HTTP::Status::status_message ($params{with_response_code}), [ %headers ], $params{with_response_data}, ), ); } sub s3_api_with_signature_4 { s3_api ( @_, aws_access_key_id => 'AKIDEXAMPLE', aws_secret_access_key => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY', authorization_method => 'Net::Amazon::S3::Signature::V4', secure => 1, use_virtual_host => 1, ); } sub s3_api_with_signature_2 { s3_api ( @_, aws_access_key_id => 'AKIDEXAMPLE', aws_secret_access_key => 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY', authorization_method => 'Net::Amazon::S3::Signature::V2', secure => 1, use_virtual_host => 1, ); } sub expect_net_amazon_s3_feature { my ($title, %params) = @_; my $s3 = delete $params{with_s3}; my $feature = delete $params{feature}; my $expectation = "expect_$feature"; local $Test::Builder::Level = $Test::Builder::Level + 1; subtest $title => sub { plan tests => 2; if (my $code = Shared::Examples::Net::Amazon::S3::API->can ($expectation)) { $code->( "using S3 API" => ( with_s3 => $s3, %params )); } else { fail "Net::Amazon::S3 feature expectation $expectation not found"; } if (my $code = Shared::Examples::Net::Amazon::S3::Client->can ($expectation)) { $code->( "using S3 Client" => ( with_client => Net::Amazon::S3::Client->new (s3 => $s3), %params )); } else { fail "Net::Amazon::S3::Client feature expectation $expectation not found"; } }; } sub _operation_parameters { my ($params, @names) = @_; my $map = {}; $map = shift @names if Ref::Util::is_plain_hashref ($names[0]); return map +( ($map->{$_} || $_) => $params->{"with_$_"} ), grep exists $params->{"with_$_"}, @names ; } sub _with_keys { map "with_$_", @_; } sub _keys_operation () { return ( qw[ -shared_examples ], qw[ -method ], qw[ with_s3 ], qw[ with_client ], qw[ shared_examples ], qw[ with_response_code ], qw[ with_response_data ], qw[ with_response_headers ], qw[ with_response_header_content_type ], qw[ with_response_header_content_length ], qw[ expect_s3_err ], qw[ expect_s3_errstr ], qw[ expect_data ], qw[ expect_request ], qw[ expect_request_content ], qw[ expect_request_headers ], qw[ throws ], ); } sub _expect_request { my ($request, $expect, $title) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; my ($method, $uri) = %$expect; cmp_deeply $request, all ( methods (method => $method), methods (uri => methods (as_string => $uri)), ), $title || 'expect request' ; } sub _expect_request_content { my ($request, $expected, $title) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; my $got = Shared::Examples::Net::Amazon::S3::Request::_canonical_xml ($request->content); $expected = Shared::Examples::Net::Amazon::S3::Request::_canonical_xml ($expected); cmp_deeply $got, $expected, $title || "expect request content"; } sub _expect_request_headers { my ($request, $expected, $title) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; my %got = map +($_ => scalar $request->header ($_)), keys %$expected; cmp_deeply \ %got, $expected, $title || "expect request headers" ; } sub _expect_s3_err { my ($got, $expected, $title) = @_; SKIP: { skip "Net::Amazon::S3->err test irrelevant for Client", 1 if eq_deeply $got, obj_isa ('Net::Amazon::S3::Client'); cmp_deeply $got, methods (err => $expected), $title || 'expect S3->err'; } } sub _expect_s3_errstr { my ($got, $expected, $title) = @_; SKIP: { skip "Net::Amazon::S3->errstr test irrelevant for Client", 1 if eq_deeply $got, obj_isa ('Net::Amazon::S3::Client'); cmp_deeply $got, methods (errstr => $expected), $title || 'expect S3->errstr'; } } sub _expect_operation { my ($title, %params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; my $class = delete $params{-shared_examples}; my $operation = delete $params{-operation}; my $api = $class->_default_with_api (\%params); $class->_mock_http_response ($api, %params, into => \ (my $request)); if (my $code = $class->can ($operation)) { subtest $title => sub { plan tests => 1 + int (!! exists $params{expect_request}) + int (!! exists $params{expect_request_content}) + int (!! exists $params{expect_request_headers}) + int (!! exists $params{expect_s3_err}) + int (!! exists $params{expect_s3_errstr}) ; my $got; my $lives = eval { $got = $api->$code (%params); 1 }; my $error = $@; if ($lives) { exists $params{throws} ? fail "operation expected to throw but lives" : cmp_deeply $got, $params{expect_data}, "expect operation return data" ; } else { $params{throws} = re $params{throws} if is_regexpref $params{throws}; $params{throws} = obj_isa $params{throws} if defined $params{throws} && ! ref $params{throws}; defined $params{throws} ? cmp_deeply $error, $params{throws}, "it should throw" : do { fail "operation expected to live but died" ; diag $error } ; } _expect_request $request, $params{expect_request} if exists $params{expect_request}; _expect_request_content $request, $params{expect_request_content} if exists $params{expect_request_content}; _expect_request_headers ($request, $params{expect_request_headers}) if exists $params{expect_request_headers}; _expect_s3_err $api, $params{expect_s3_err} if exists $params{expect_s3_err}; _expect_s3_errstr $api, $params{expect_s3_errstr} if exists $params{expect_s3_errstr}; }; } else { fail $title or diag "Operation ${class}::$operation not found"; } } sub _generate_operation_expectation { my ($name, @parameters) = @_; my @on = ( ('bucket') x!! ($name =~ m/^ ( bucket | object )/x), ('key') x!! ($name =~ m/^ ( object )/x), ); my $on = "qw[ ${ \ join ' ', @on } ]"; eval <<"OPERATION_DECLARATION"; sub parameters_$name { qw[ ${ \ join ' ', @parameters } ] } sub expect_operation_$name { my (\$title, \%params) = \@_; local \$Test::Builder::Level = \$Test::Builder::Level + 1; Hash::Util::lock_keys \%params, _with_keys ($on, parameters_$name), _keys_operation; _expect_operation \$title, \%params, -operation => 'operation_$name'; } OPERATION_DECLARATION } _generate_operation_expectation list_all_my_buckets => ; _generate_operation_expectation bucket_acl_get => ; _generate_operation_expectation bucket_acl_set => qw[ acl ], qw[ acl_xml ], qw[ acl_short ], ; _generate_operation_expectation bucket_create => qw[ acl ], qw[ acl_short ], qw[ region ], ; _generate_operation_expectation bucket_delete => ; _generate_operation_expectation bucket_objects_list => qw[ delimiter ], qw[ max_keys ], qw[ marker ], qw[ prefix ], ; _generate_operation_expectation bucket_objects_delete => qw[ keys ], ; _generate_operation_expectation object_acl_get => ; _generate_operation_expectation object_acl_set => qw[ acl ], qw[ acl_xml ], qw[ acl_short ], ; _generate_operation_expectation object_create => qw[ headers ], qw[ value ], qw[ cache_control ], qw[ content_disposition ], qw[ content_encoding ], qw[ content_type ], qw[ encryption ], qw[ expires ], qw[ storage_class ], qw[ user_metadata ], qw[ acl ], qw[ acl_short ], ; _generate_operation_expectation object_delete => ; _generate_operation_expectation object_fetch => qw[ range ], ; _generate_operation_expectation object_head => ; _generate_operation_expectation bucket_tags_add => qw[ tags ], ; _generate_operation_expectation object_tags_add => qw[ tags ], qw[ version_id ], ; _generate_operation_expectation bucket_tags_delete => ; _generate_operation_expectation object_tags_delete => qw[ version_id ], ; 1; __END__ =pod =encoding UTF-8 =head1 NAME Shared::Examples::Net::Amazon::S3 - used for testing and as example =head1 VERSION version 0.991 =head1 AUTHOR Branislav Zahradník =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Net-Amazon-S3-0.991/Makefile.PL0000644000175000017500000001016614264646670014751 0ustar branobrano# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.025. use strict; use warnings; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Use the Amazon S3 - Simple Storage Service", "AUTHOR" => "Branislav Zahradn\x{ed}k ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "Net-Amazon-S3", "EXE_FILES" => [ "bin/s3cl" ], "LICENSE" => "perl", "NAME" => "Net::Amazon::S3", "PREREQ_PM" => { "Carp" => 0, "Data::Stream::Bulk::Callback" => 0, "DateTime::Format::HTTP" => 0, "Digest::HMAC_SHA1" => 0, "Digest::MD5" => 0, "Digest::MD5::File" => 0, "Digest::SHA" => 0, "Exporter::Tiny" => 0, "File::Find::Rule" => 0, "File::stat" => 0, "Getopt::Long" => 0, "HTTP::Date" => 0, "HTTP::Response" => 0, "HTTP::Status" => 0, "Hash::Util" => 0, "IO::File" => "1.14", "LWP" => "6.03", "LWP::UserAgent::Determined" => 0, "MIME::Base64" => 0, "MIME::Types" => 0, "Moose" => "0.85", "Moose::Meta::Class" => 0, "Moose::Object" => 0, "Moose::Role" => 0, "Moose::Util" => 0, "Moose::Util::TypeConstraints" => 0, "MooseX::Role::Parameterized" => 0, "MooseX::StrictConstructor" => "0.16", "MooseX::Types::DateTime::MoreCoercions" => "0.07", "Path::Class" => 0, "Pod::Usage" => 0, "Ref::Util" => 0, "Regexp::Common" => 0, "Safe::Isa" => 0, "Scalar::Util" => 0, "Sub::Override" => 0, "Term::Encoding" => 0, "Term::ProgressBar::Simple" => 0, "Test::Deep" => "0.111.0", "Test::LWP::UserAgent" => 0, "Test::More" => 0, "Time::Piece" => 0, "URI" => 0, "URI::Escape" => 0, "URI::QueryParam" => 0, "XML::LibXML" => 0, "XML::LibXML::XPathContext" => 0, "constant" => 0, "namespace::clean" => 0, "parent" => 0, "sort" => 0, "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "File::Temp" => 0, "FindBin" => 0, "HTTP::Request" => 0, "LWP::Simple" => 0, "Test::Deep" => "0.111.0", "Test::Exception" => 0, "Test::MockTime" => 0, "Test::Warnings" => 0, "lib" => 0, "utf8" => 0, "vars" => 0 }, "VERSION" => "0.991", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Data::Stream::Bulk::Callback" => 0, "DateTime::Format::HTTP" => 0, "Digest::HMAC_SHA1" => 0, "Digest::MD5" => 0, "Digest::MD5::File" => 0, "Digest::SHA" => 0, "Exporter::Tiny" => 0, "File::Find::Rule" => 0, "File::Temp" => 0, "File::stat" => 0, "FindBin" => 0, "Getopt::Long" => 0, "HTTP::Date" => 0, "HTTP::Request" => 0, "HTTP::Response" => 0, "HTTP::Status" => 0, "Hash::Util" => 0, "IO::File" => "1.14", "LWP" => "6.03", "LWP::Simple" => 0, "LWP::UserAgent::Determined" => 0, "MIME::Base64" => 0, "MIME::Types" => 0, "Moose" => "0.85", "Moose::Meta::Class" => 0, "Moose::Object" => 0, "Moose::Role" => 0, "Moose::Util" => 0, "Moose::Util::TypeConstraints" => 0, "MooseX::Role::Parameterized" => 0, "MooseX::StrictConstructor" => "0.16", "MooseX::Types::DateTime::MoreCoercions" => "0.07", "Path::Class" => 0, "Pod::Usage" => 0, "Ref::Util" => 0, "Regexp::Common" => 0, "Safe::Isa" => 0, "Scalar::Util" => 0, "Sub::Override" => 0, "Term::Encoding" => 0, "Term::ProgressBar::Simple" => 0, "Test::Deep" => "0.111.0", "Test::Exception" => 0, "Test::LWP::UserAgent" => 0, "Test::MockTime" => 0, "Test::More" => 0, "Test::Warnings" => 0, "Time::Piece" => 0, "URI" => 0, "URI::Escape" => 0, "URI::QueryParam" => 0, "XML::LibXML" => 0, "XML::LibXML::XPathContext" => 0, "constant" => 0, "lib" => 0, "namespace::clean" => 0, "parent" => 0, "sort" => 0, "strict" => 0, "utf8" => 0, "vars" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); Net-Amazon-S3-0.991/META.yml0000644000175000017500000001022714264646670014246 0ustar branobrano--- abstract: 'Use the Amazon S3 - Simple Storage Service' author: - 'Branislav Zahradník ' build_requires: File::Temp: '0' FindBin: '0' HTTP::Request: '0' LWP::Simple: '0' Test::Deep: v0.111.0 Test::Exception: '0' Test::MockTime: '0' Test::Warnings: '0' lib: '0' utf8: '0' vars: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.025, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Net-Amazon-S3 recommends: VM::EC2::Security::CredentialCache: '0' requires: Carp: '0' Data::Stream::Bulk::Callback: '0' DateTime::Format::HTTP: '0' Digest::HMAC_SHA1: '0' Digest::MD5: '0' Digest::MD5::File: '0' Digest::SHA: '0' Exporter::Tiny: '0' File::Find::Rule: '0' File::stat: '0' Getopt::Long: '0' HTTP::Date: '0' HTTP::Response: '0' HTTP::Status: '0' Hash::Util: '0' IO::File: '1.14' LWP: '6.03' LWP::UserAgent::Determined: '0' MIME::Base64: '0' MIME::Types: '0' Moose: '0.85' Moose::Meta::Class: '0' Moose::Object: '0' Moose::Role: '0' Moose::Util: '0' Moose::Util::TypeConstraints: '0' MooseX::Role::Parameterized: '0' MooseX::StrictConstructor: '0.16' MooseX::Types::DateTime::MoreCoercions: '0.07' Path::Class: '0' Pod::Usage: '0' Ref::Util: '0' Regexp::Common: '0' Safe::Isa: '0' Scalar::Util: '0' Sub::Override: '0' Term::Encoding: '0' Term::ProgressBar::Simple: '0' Test::Deep: v0.111.0 Test::LWP::UserAgent: '0' Test::More: '0' Time::Piece: '0' URI: '0' URI::Escape: '0' URI::QueryParam: '0' XML::LibXML: '0' XML::LibXML::XPathContext: '0' constant: '0' namespace::clean: '0' parent: '0' sort: '0' strict: '0' warnings: '0' resources: bugtracker: https://github.com/rustyconover/net-amazon-s3/issues repository: https://github.com/rustyconover/net-amazon-s3 version: '0.991' x_contributors: - 'Aaron Crane ' - 'Ali Anari ' - 'Ali Zia ' - 'Ali ' - 'Branislav Zahradnik ' - 'Branislav Zahradník ' - 'Christian Lackas ' - 'Conor Keegan ' - 'Douglas Sims ' - 'Dylan William Hardison ' - 'Eden Crane <>' - 'Emanuele Tomasi aka targzeta ' - 'Florian Schlichting ' - 'Gabriel Andrade ' - 'Gabriel Andrade ' - 'Gavin Carr ' - 'gregor herrmann ' - 'Haruka Iwao ' - 'Jun Kuriyama ' - 'Leo Lapworth ' - 'Leon Brocard ' - 'Michael Schout ' - 'Michal Josef Špaček ' - 'Michele Beltrame ' - 'Michele Beltrame ' - 'Miquel Ruiz ' - 'Panu Ervamaa ' - 'Pavel A. Karoukin ' - 'Pedro Figueiredo ' - 'Pedro Figueiredo ' - 'Pedro Figueiredo ' - 'perlpong ' - 'Renato Santos ' - 'robert clarke ' - 'Robert Ward ' - 'rocketgithub ' - 'Rusty Conover ' - 'Rusty Conover ' - 'Rusty Conover ' - 'Rusty Conover ' - 'Sherwin Daganato ' - 'Slobodan Mišković ' - 'Steven Berler ' - 'Struan Bartlett ' - 'Stuart Skelton ' - 'Tom Hukins ' - 'toritori0318 ' - 'Yanick Champoux ' x_generated_by_perl: v5.30.0 x_serialization_backend: 'YAML::Tiny version 1.73' x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later' Net-Amazon-S3-0.991/dist.ini0000644000175000017500000000177014264646670014444 0ustar branobranoname = Net-Amazon-S3 author = Branislav Zahradník license = Perl_5 copyright_holder = Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník version = 0.991 [@Filter] -bundle = @Basic -remove = GatherDir option = for_basic [AutoPrereqs] [Clean] [CopyFilesFromBuild] copy = cpanfile copy = LICENSE copy = Makefile.PL [CPANFile] [Git::GatherDir] exclude_filename = cpanfile exclude_filename = LICENSE exclude_filename = Makefile.PL [Git::Contributors] [MetaJSON] [MetaResources] bugtracker.web = https://github.com/rustyconover/net-amazon-s3/issues repository.url = https://github.com/rustyconover/net-amazon-s3 repository.web = https://github.com/rustyconover/net-amazon-s3 repository.type = git [NextRelease] filename = CHANGES format = v%-9v %{yyyy-MM-dd}d [PkgVersion] [PodWeaver] [Prereqs] LWP = 6.03 [Prereqs / RuntimeRecommends] VM::EC2::Security::CredentialCache = 0 [ReadmeMarkdownFromPod] [Test::EOL] Net-Amazon-S3-0.991/t/0000775000175000017500000000000014264646670013240 5ustar branobranoNet-Amazon-S3-0.991/t/s3-request-object-upload-abort.t0000644000175000017500000000115214264646670021270 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'abort multipart upload' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Abort::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_upload_id => '123&456', expect_request_method => 'DELETE', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploadId=123%26456', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-bucket-tags-delete.t0000644000175000017500000000173314264646670021421 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_bucket_tags_delete ( 'API / legacy' => \& api_bucket_tags_delete_legacy, 'API / named' => \& api_bucket_tags_delete_named, 'Client' => \& client_bucket_tags_delete, ); had_no_warnings; done_testing; sub api_bucket_tags_delete_legacy { my (%args) = @_; build_default_api_bucket (%args) ->delete_tags (\ %args) ; } sub api_bucket_tags_delete_named { my (%args) = @_; build_default_api_bucket (%args) ->delete_tags (%args) ; } sub client_bucket_tags_delete { my (%args) = @_; build_default_client_bucket (%args) ->delete_tags (%args) ; } sub expect_operation_bucket_tags_delete { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Bucket::Tags::Delete', plan => { "delete tags from bucket" => { act_arguments => [ bucket => 'bucket-name', ], }, } } Net-Amazon-S3-0.991/t/client-object-acl-set.t0000644000175000017500000001030314264646670017470 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } plan tests => 10; use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_acl_set ]; expect_client_object_acl_set 'set object acl using deprecated acl_short' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl_short => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_client_object_acl_set 'set object acl using canned acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_client_object_acl_set 'set object acl using canned acl coerction' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_client_object_acl_set 'set object acl using explicit acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, expect_data => bool (1), ); expect_client_object_acl_set 'set object acl using XML content' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl_xml => 'PASSTHROUGH', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => 'PASSTHROUGH', expect_request_headers => { x_amz_acl => undef, }, expect_data => bool (1), ); expect_client_object_acl_set 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, throws => qr/^AccessDenied: Access denied error message/, ); expect_client_object_acl_set 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, throws => qr/NoSuchBucket: No such bucket error message/, ); expect_client_object_acl_set 'S3 error - Object Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::no_such_key'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, throws => qr/^NoSuchKey: No such key error message/, ); expect_client_object_acl_set 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, throws => qr/^400: Bad Request/, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-object-fetch.t0000644000175000017500000000107414264646670017773 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'get object' => ( request_class => 'Net::Amazon::S3::Operation::Object::Fetch::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_method => 'GET', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-objects-list.t0000644000175000017500000000522114264646670020346 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } plan tests => 10; expect_operation_objects_list_api ( "API / S3->list_bucket legacy" => \& api_objects_list_legacy, "API / S3->list_bucket_all legacy" => \& api_objects_list_all_legacy, "API / S3->list_bucket named" => \& api_objects_list_named, "API / S3->list_bucket_all named" => \& api_objects_list_all_named, "API / Bucket->list legacy" => \& api_objects_bucket_list_legacy, "API / Bucket->list_all legacy" => \& api_objects_bucket_list_all_legacy, "API / Bucket->list named" => \& api_objects_bucket_list_named, "API / Bucket->list_all named" => \& api_objects_bucket_list_all_named, ); expect_operation_objects_list_client ( "Client" => \& client_objects_list, ); had_no_warnings; done_testing; sub api_objects_list_legacy { my (%args) = @_; build_default_api->list_bucket (\ %args); } sub api_objects_list_named { my (%args) = @_; build_default_api->list_bucket (%args); } sub api_objects_list_all_legacy { my (%args) = @_; build_default_api->list_bucket_all (\ %args); } sub api_objects_list_all_named { my (%args) = @_; build_default_api->list_bucket_all (%args); } sub api_objects_bucket_list_legacy { my (%args) = @_; build_default_api_bucket (%args) ->list (\ %args) ; } sub api_objects_bucket_list_named { my (%args) = @_; build_default_api_bucket (%args) ->list (%args) ; } sub api_objects_bucket_list_all_legacy { my (%args) = @_; build_default_api_bucket (%args) ->list_all (\ %args) ; } sub api_objects_bucket_list_all_named { my (%args) = @_; build_default_api_bucket (%args) ->list_all (%args) ; } sub client_objects_list { my (%args) = @_; build_default_client_bucket (%args) ->list (\ %args) ->next ; } sub expect_operation_objects_list_api { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Objects::List', plan => { "list buckets" => { act_arguments => [ bucket => 'bucket-name', delimiter => 'd', max_keys => 1_000, marker => 'm', prefix => 'p' ], }, } } sub expect_operation_objects_list_client { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Objects::List', plan => { "list buckets" => { act_arguments => [ bucket => 'bucket-name', delimiter => 'd', marker => 'm', prefix => 'p' ], expect_arguments => { bucket => 'bucket-name', delimiter => 'd', marker => undef, prefix => 'p' }, }, } } Net-Amazon-S3-0.991/t/s3-request-bucket-acl-fetch.t0000644000175000017500000000102114264646670020527 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'get bucket access control' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Fetch::Request', with_bucket => 'some-bucket', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?acl', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-bucket-acl-fetch.t0000644000175000017500000000166114264646670021051 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_bucket_acl_fetch ( 'API / legacy' => \& api_bucket_acl_fetch_legacy, 'API / named' => \& api_bucket_acl_fetch_named, 'Client' => \& client_bucket_acl_fetch, ); had_no_warnings; done_testing; sub api_bucket_acl_fetch_legacy { my (%args) = @_; build_default_api_bucket (%args) ->get_acl (%args) ; } sub api_bucket_acl_fetch_named { my (%args) = @_; build_default_api_bucket (%args) ->get_acl (%args) ; } sub client_bucket_acl_fetch { my (%args) = @_; build_default_client_bucket (%args) ->acl (%args) ; } sub expect_operation_bucket_acl_fetch { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Bucket::Acl::Fetch', plan => { "fetch bucket acl" => { act_arguments => [ bucket => 'bucket-name', ], }, } } Net-Amazon-S3-0.991/t/client-object-create.t0000644000175000017500000001473314264646670017416 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_create ]; plan tests => 11; expect_client_object_create 'create object from scalar value' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_headers => { etag => '5946210c9e93ae37891dfe96c3e39614' }, expect_data => '', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => 'WUYhDJ6TrjeJHf6Ww+OWFA==', expires => undef, }, ); expect_client_object_create 'create object with deprecated acl_short' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_headers => { etag => '5946210c9e93ae37891dfe96c3e39614' }, with_acl_short => 'private', expect_data => '', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => 'WUYhDJ6TrjeJHf6Ww+OWFA==', expires => undef, x_amz_acl => 'private', }, ); expect_client_object_create 'create object with canned acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_headers => { etag => '5946210c9e93ae37891dfe96c3e39614' }, with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_data => '', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => 'WUYhDJ6TrjeJHf6Ww+OWFA==', expires => undef, x_amz_acl => 'private', }, ); expect_client_object_create 'create object with canned acl coercion' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_headers => { etag => '5946210c9e93ae37891dfe96c3e39614' }, with_acl => 'private', expect_data => '', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => 'WUYhDJ6TrjeJHf6Ww+OWFA==', expires => undef, x_amz_acl => 'private', }, ); expect_client_object_create 'create object with explicit acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_headers => { etag => '5946210c9e93ae37891dfe96c3e39614' }, with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_data => '', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => 'WUYhDJ6TrjeJHf6Ww+OWFA==', expires => undef, x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, ); expect_client_object_create 'create object with server side encryption' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_encryption => 'AES256', with_response_headers => { etag => '5946210c9e93ae37891dfe96c3e39614' }, expect_data => '', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => 'WUYhDJ6TrjeJHf6Ww+OWFA==', expires => undef, x_amz_server_side_encryption => 'AES256', }, ); expect_client_object_create 'create object with headers recognized by Client::Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_headers => { etag => '5946210c9e93ae37891dfe96c3e39614' }, with_cache_control => 'private', with_content_disposition => 'inline', with_content_encoding => 'identity', with_content_type => 'text/plain', with_expires => DateTime->new( year => 2011, month => 9, day => 9, hour => 23, minute => 36, time_zone => 'UTC', ), with_storage_class => 'reduced_redundancy', with_user_metadata => { Foo => 1, Bar => 2 }, expect_data => '', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { cache_control => 'private', content_disposition => 'inline', content_encoding => 'identity', content_length => 10, content_type => 'text/plain', content_md5 => 'WUYhDJ6TrjeJHf6Ww+OWFA==', expires => 'Fri, 09 Sep 2011 23:36:00 GMT', x_amz_meta_bar => 2, x_amz_meta_foo => 1, x_amz_storage_class => 'REDUCED_REDUNDANCY', }, ); expect_client_object_create 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_client_object_create 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => bool (0), expect_s3_error_bucket_not_found, ); expect_client_object_create 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-bucket-create.t0000644000175000017500000001006014264646670017412 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_create ]; plan tests => 11; expect_client_bucket_create 'create bucket' => ( with_bucket => 'some-bucket', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_data => all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'some-bucket'), ), ); expect_client_bucket_create 'create bucket in different region' => ( with_bucket => 'some-bucket', with_region => 'ca-central-1', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => fixture ('request::bucket_create_ca_central_1')->{content}, expect_data => all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'some-bucket'), ), ); expect_client_bucket_create 'create bucket with deprecated acl_short' => ( with_bucket => 'some-bucket', with_acl_short => 'private', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private' }, expect_data => all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'some-bucket'), ), ); expect_client_bucket_create 'create bucket with canned acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private' }, expect_data => all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'some-bucket'), ), ); expect_client_bucket_create 'create bucket with canned acl coercion' => ( with_bucket => 'some-bucket', with_acl => 'private', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private' }, expect_data => all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'some-bucket'), ), ); expect_client_bucket_create 'create bucket with explicit acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, expect_data => all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'some-bucket'), ), ); expect_client_bucket_create 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_access_denied, ); expect_client_bucket_create 'S3 error - Bucket Already Exists' => ( with_bucket => 'some-bucket', with_response_fixture ('error::bucket_already_exists'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_bucket_exists, ); expect_client_bucket_create 'S3 error - Invalid Bucket Name' => ( with_bucket => 'some-bucket', with_response_fixture ('error::invalid_bucket_name'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_s3_error_invalid_bucket_name, ); expect_client_bucket_create 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-bucket-objects-list.t0000644000175000017500000001215314264646670020556 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_objects_list ]; plan tests => 8; expect_client_bucket_objects_list 'list objects (version 1)' => ( with_bucket => 'some-bucket', with_response_fixture ('response::bucket_objects_list_v1'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?max-keys=1000' }, expect_data => methods (get_more => [ all ( obj_isa ('Net::Amazon::S3::Client::Object'), methods (bucket => methods(name => 'some-bucket')), methods (key => 'my-image.jpg'), methods (last_modified_raw => '2009-10-12T17:50:30.000Z'), methods (etag => 'fba9dede5f27731c9771645a39863328'), methods (size => 434234), ), all ( obj_isa ('Net::Amazon::S3::Client::Object'), methods (bucket => methods(name => 'some-bucket')), methods (key => 'my-third-image.jpg'), methods (last_modified_raw => '2009-10-12T17:50:30.000Z'), methods (etag => '1b2cf535f27731c974343645a3985328'), methods (size => 64994), ), ]), ); expect_client_bucket_objects_list 'list objects with filters (version 1)' => ( with_bucket => 'some-bucket', # truncated is not supported by shared examples yet (multiple requests => client reads while is truncated) with_response_fixture ('response::bucket_objects_list_v1_with_filter'), with_prefix => 'N', with_marker => 'Ned', with_max_keys => 40, expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?max-keys=1000&prefix=N' }, expect_data => methods (get_more => [ all ( obj_isa ('Net::Amazon::S3::Client::Object'), methods (bucket => methods(name => 'some-bucket')), methods (key => 'Nelson'), methods (last_modified_raw => '2006-01-01T12:00:00.000Z'), methods (etag => '828ef3fdfa96f00ad9f27c383fc9ac7f'), methods (size => 5), ), all ( obj_isa ('Net::Amazon::S3::Client::Object'), methods (bucket => methods(name => 'some-bucket')), methods (key => 'Neo'), methods (last_modified_raw => '2006-01-01T12:00:00.000Z'), methods (etag => '828ef3fdfa96f00ad9f27c383fc9ac7f'), methods (size => 4), ), ]), ); # Client doesn't support common prefixes expect_client_bucket_objects_list 'list objects with delimiter (version 1)' => ( with_bucket => 'some-bucket', with_response_fixture ('response::bucket_objects_list_v1_with_delimiter'), with_delimiter => '/', expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?delimiter=%2F&max-keys=1000' }, expect_data => methods (get_more => [ all ( obj_isa ('Net::Amazon::S3::Client::Object'), methods (bucket => methods(name => 'some-bucket')), methods (key => 'sample.jpg'), methods (last_modified_raw => '2011-02-26T01:56:20.000Z'), methods (etag => 'bf1d737a4d46a19f3bced6905cc8b902'), methods (size => 142863), ), ]), ); # Client doesn't support common prefixes expect_client_bucket_objects_list 'list objects with prefix and delimiter (version 1)' => ( with_bucket => 'some-bucket', with_response_fixture ('response::bucket_objects_list_v1_with_prefix_and_delimiter'), with_delimiter => '/', with_prefix => 'photos/2006/', expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?delimiter=%2F&max-keys=1000&prefix=photos%2F2006%2F' }, expect_data => methods (get_more => undef), ); expect_client_bucket_objects_list 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?max-keys=1000' }, expect_data => all ( obj_isa ('Data::Stream::Bulk::Callback'), code(sub { return 0, "expect throw but lives" if eval { $_[0]->get_more; 1 }; my $error = $@; Test::Deep::cmp_details $error, re(qr/^AccessDenied: Access denied error message/); }), ), ); expect_client_bucket_objects_list 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?max-keys=1000' }, expect_data => methods (get_more => undef), expect_data => all ( obj_isa ('Data::Stream::Bulk::Callback'), code(sub { return 0, "expect throw but lives" if eval { $_[0]->get_more; 1 }; my $error = $@; Test::Deep::cmp_details $error, re(qr/^NoSuchBucket: No such bucket error message/); }), ), ); expect_client_bucket_objects_list 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?max-keys=1000' }, expect_data => all ( obj_isa ('Data::Stream::Bulk::Callback'), code(sub { return 0, "expect throw but lives" if eval { $_[0]->get_more; 1 }; my $error = $@; Test::Deep::cmp_details $error, re(qr/^400: Bad Request/); }), ), ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-bucket-acl-set.t0000644000175000017500000000563114264646670020244 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 8; behaves_like_net_amazon_s3_request 'set bucket access control using (deprecated) acl_short' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Set::Request', with_bucket => 'some-bucket', with_acl_short => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?acl', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'set bucket access control using canned acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Set::Request', with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?acl', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'set bucket access control using canned acl coercion' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Set::Request', with_bucket => 'some-bucket', with_acl => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?acl', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'set bucket access control using explicit acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Set::Request', with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?acl', expect_request_headers => { 'x-amz-grant-read' => 'id="123", id="234"', 'x-amz-grant-write' => 'id="345"', }, ); behaves_like_net_amazon_s3_request 'set bucket access control with body acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Set::Request', with_bucket => 'some-bucket', with_acl_xml => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?acl', expect_request_headers => { }, ); behaves_like_net_amazon_s3_request 'set bucket access control without body or header acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Set::Request', with_bucket => 'some-bucket', throws => re( qr/need either acl_xml or acl/ ), ); behaves_like_net_amazon_s3_request 'set bucket access control with both body and header acl specified' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Acl::Set::Request', with_bucket => 'some-bucket', with_acl => 'private', with_acl_xml => 'private', throws => re( qr/can not provide both acl_xml and acl/ ), ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-object-upload-parts.t0000644000175000017500000000114114264646670021310 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'list parts' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Parts::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_upload_id => '123', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploadId=123', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-bucket-objects-delete.t0000644000175000017500000000341114264646670020335 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_objects_delete ]; plan tests => 5; expect_api_bucket_objects_delete 'delete multiple objects' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('response::bucket_objects_delete_quiet_without_errors'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_data => bool (1), expect_request_content => <<'XML', true key-1 key-2 XML ); expect_api_bucket_objects_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('error::access_denied'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_s3_error_access_denied, ); expect_api_bucket_objects_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('error::no_such_bucket'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_s3_error_bucket_not_found, ); expect_api_bucket_objects_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('error::http_bad_request'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-s3-api-error-status.pl0000644000175000017500000000041614264646670021572 0ustar branobrano use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-errors.pl" } sub expect_error { my ($code, $message) = @_; return +( expect_data => bool (0), expect_s3_err => $code, expect_s3_errstr => $message, ); } 1; Net-Amazon-S3-0.991/t/client-bucket-tags-add.t0000644000175000017500000000336314264646670017643 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } BEGIN { require "$FindBin::Bin/test-helper-tags.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_tags_add ]; plan tests => 5; expect_client_bucket_tags_add 'add tags to a bucket' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('response::http_ok_empty'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_request_content => fixture_tags_foo_bar_xml, expect_request_headers => { content_type => 'application/xml', }, expect_data => bool (1), ); expect_client_bucket_tags_add 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_access_denied, ); expect_client_bucket_tags_add 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_bucket_not_found, ); expect_client_bucket_tags_add 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-object-tags-add.t0000644000175000017500000000366414264646670017640 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } BEGIN { require "$FindBin::Bin/test-helper-tags.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_tags_add ]; plan tests => 5; expect_client_object_tags_add 'add tags to an object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('response::http_ok_empty'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_request_content => fixture_tags_foo_bar_xml, expect_request_headers => { content_type => 'application/xml', }, expect_data => bool (1), ); expect_client_object_tags_add 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_access_denied, ); expect_client_object_tags_add 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_bucket_not_found, ); expect_client_object_tags_add 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/request.t0000644000175000017500000000342014264646670015112 0ustar branobrano use strict; use warnings; use Test::More tests => 16; use Test::Warnings qw[ :no_end_test had_no_warnings ]; use Moose::Meta::Class; use Net::Amazon::S3; use Shared::Examples::Net::Amazon::S3::Request ( qw[ expect_request_class ], qw[ expect_request_instance ], ); my $request_class; sub request_class { ($request_class) = @_; expect_request_class $request_class; } sub request_path { my ($title, %params) = @_; my $request = expect_request_instance request_class => $request_class, (with_bucket => $params{with_bucket}) x exists $params{with_bucket}, (with_key => $params{with_key}) x exists $params{with_key}, ; my $request_path = $request->_build_signed_request ( method => 'GET', path => $request->_request_path, )->path; is $request_path, $params{expect}, $title, ; } request_class 'Net::Amazon::S3::Request::Service'; request_path 'service request should return empty path', expect => '', ; request_class 'Net::Amazon::S3::Request::Bucket'; request_path 'bucket request', with_bucket => 'some-bucket', expect => 'some-bucket/', ; request_class 'Net::Amazon::S3::Request::Object'; request_path 'object request with empty key', with_bucket => 'some-bucket', with_key => '', expect => 'some-bucket/', ; request_path 'object request should recognize leading slash', with_bucket => 'some-bucket', with_key => '/some/key', expect => 'some-bucket/some/key', ; request_path 'object request should sanitize key with slash sequences', with_bucket => 'some-bucket', with_key => '//some///key', expect =>'some-bucket/some/key', ; request_path 'object request should uri-escape key', with_bucket => 'some-bucket', with_key => 'some/ %/key', expect => 'some-bucket/some/%20%25/key', ; had_no_warnings; Net-Amazon-S3-0.991/t/s3-operation-object-head.t0000644000175000017500000000276114264646670020117 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_head_api ( 'API / via Bucket' => \& api_object_head_key_via_bucket, 'API / via S3' => \& api_object_head_key_via_s3, ); expect_operation_object_head_client ( 'Client' => \& client_object_exists, ); had_no_warnings; done_testing; sub api_object_head_key_via_bucket { my (%args) = @_; build_default_api_bucket (%args) ->head_key (delete $args{key}) ; } sub api_object_head_key_via_s3 { my (%args) = @_; build_default_api ->head_key (\ %args) ; } sub client_object_exists { my (%args) = @_; build_default_client_object (%args) ->exists ; } sub expect_operation_object_head_api { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Fetch', plan => { "head object" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', ], expect_arguments => { bucket => 'bucket-name', key => 'key-name', method => 'HEAD', filename => undef, }, }, } } sub expect_operation_object_head_client { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Head', plan => { "fetch object" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', ], expect_arguments => { bucket => 'bucket-name', key => 'key-name', }, }, } } Net-Amazon-S3-0.991/t/client-object-fetch.t0000644000175000017500000000550514264646670017241 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_fetch ]; plan tests => 7; expect_client_object_fetch 'fetch existing object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_code => HTTP::Status::HTTP_OK, with_response_data => 'some-value', with_response_headers => { content_length => 10, content_type => 'text/plain', etag => '8c561147ab3ce19bb8e73db4a47cc6ac', x_amz_metadata_foo => 'foo-1', date => 'Fri, 09 Sep 2011 23:36:00 GMT', }, expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => 'some-value', ); expect_client_object_fetch 'fetch range of existing object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_range => 'bytes=1024-10240', with_response_code => HTTP::Status::HTTP_OK, with_response_data => 'some-value', with_response_headers => { content_length => 10, content_type => 'text/plain', etag => '8c561147ab3ce19bb8e73db4a47cc6ac', x_amz_metadata_foo => 'foo-1', date => 'Fri, 09 Sep 2011 23:36:00 GMT', }, expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_headers => { range => 'bytes=1024-10240', }, expect_data => 'some-value', ); expect_client_object_fetch 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_client_object_fetch 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_bucket_not_found, ); expect_client_object_fetch 'S3 error - No Such Object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_object_not_found, ); expect_client_object_fetch 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-bucket-delete.t0000644000175000017500000000313414264646670016710 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_delete ]; plan tests => 6; expect_api_bucket_delete 'delete bucket' => ( with_bucket => 'some-bucket', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_data => bool (1), ); expect_api_bucket_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_access_denied, ); expect_api_bucket_delete 'S3 error - Bucket Not Empty' => ( with_bucket => 'some-bucket', with_response_fixture ('error::bucket_not_empty'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_bucket_not_empty, ); expect_api_bucket_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_bucket_not_found, ); expect_api_bucket_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-object-delete.t0000644000175000017500000000332314264646670016701 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_delete ]; plan tests => 6; expect_api_object_delete 'delete object' => ( with_bucket => 'some-bucket', with_key => 'some-key', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => bool (1), ); expect_api_object_delete 'error access denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_api_object_delete 'error no such bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_bucket_not_found, ); expect_api_object_delete 'error no such key' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_object_not_found, ); expect_api_object_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-bucket-location.t0000644000175000017500000000173314264646670021033 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_bucket_location ( 'API / legacy' => \& api_bucket_location_legacy, 'API / named' => \& api_bucket_location_named, 'Client' => \& client_bucket_location, ); had_no_warnings; done_testing; sub api_bucket_location_legacy { my (%args) = @_; build_default_api_bucket (%args) ->get_location_constraint (\ %args) ; } sub api_bucket_location_named { my (%args) = @_; build_default_api_bucket (%args) ->get_location_constraint (%args) ; } sub client_bucket_location { my (%args) = @_; build_default_client_bucket (%args) ->location_constraint (%args) ; } sub expect_operation_bucket_location { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Bucket::Location', plan => { "location bucket with name" => { act_arguments => [ bucket => 'bucket-name', ], }, } } Net-Amazon-S3-0.991/t/s3-operation-object-delete.t0000644000175000017500000000256414264646670020461 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_delete ( 'API / Bucket->delete_key / legacy' => \& api_delete_object_via_bucket, 'API / S3->delete_key / legacy' => \& api_delete_object_via_s3, 'API / Bucket->delete_key / named arguments' => \& api_delete_object_via_bucket_named, 'API / S3->delete_key / named arguments' => \& api_delete_object_via_s3_named, 'Client' => \& client_delete_object, ); had_no_warnings; done_testing; sub api_delete_object_via_bucket { my (%args) = @_; build_default_api_bucket (%args) ->delete_key ($args{key}) ; } sub api_delete_object_via_bucket_named { my (%args) = @_; build_default_api_bucket (%args) ->delete_key (%args) ; } sub api_delete_object_via_s3 { my (%args) = @_; build_default_api ->delete_key (\ %args) ; } sub api_delete_object_via_s3_named { my (%args) = @_; build_default_api ->delete_key (%args) ; } sub client_delete_object { my (%args) = @_; build_default_client_object (%args) ->delete ; } sub expect_operation_object_delete { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Delete', plan => { "delete object" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', ], }, } } Net-Amazon-S3-0.991/t/s3-request-object-add.t0000644000175000017500000000564314264646670017440 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 7; behaves_like_net_amazon_s3_request 'put object' => ( request_class => 'Net::Amazon::S3::Operation::Object::Add::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_value => 'foo', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { }, ); behaves_like_net_amazon_s3_request 'put object with deprecated acl_short' => ( request_class => 'Net::Amazon::S3::Operation::Object::Add::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl_short => 'private', with_value => 'foo', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'put object with canned acl' => ( request_class => 'Net::Amazon::S3::Operation::Object::Add::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, with_value => 'foo', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'put object with canned acl coercion' => ( request_class => 'Net::Amazon::S3::Operation::Object::Add::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => 'private', with_value => 'foo', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'put object with explicit acl' => ( request_class => 'Net::Amazon::S3::Operation::Object::Add::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , with_value => 'foo', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { 'x-amz-grant-read' => 'id="123", id="234"', 'x-amz-grant-write' => 'id="345"', }, ); behaves_like_net_amazon_s3_request 'put object with service side encryption' => ( request_class => 'Net::Amazon::S3::Operation::Object::Add::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_encryption => 'AES256', with_value => 'foo', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { 'x-amz-server-side-encryption' => 'AES256' }, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-copy.t0000644000175000017500000001000114264646670020152 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_copy ( 'API / legacy' => \& api_object_copy_legacy, 'API / legacy configuration hash' => \& api_object_copy_legacy_config, 'API / named arguments' => \& api_object_copy_named, 'API / named arguments with keys' => \& api_object_copy_named_keys, ); expect_operation_object_edit_metadata ( 'API / edit metadata legacy' => \& api_object_edit_metadata_legacy, 'API / edit metadata named' => \& api_object_edit_metadata_named, ); had_no_warnings; done_testing; sub api_object_copy_legacy { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->copy_key ( delete $args{key}, delete $args{source}, \ %args ); } sub api_object_copy_legacy_config { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->copy_key ( \ %args ); } sub api_object_copy_named { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->copy_key ( %args ); } sub api_object_copy_named_keys { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->copy_key ( delete $args{key}, delete $args{source}, %args ); } sub api_object_edit_metadata_legacy { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->edit_metadata ( delete $args{key}, \ %args ); } sub api_object_edit_metadata_named { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->edit_metadata ( %args ); } sub expect_operation_object_copy { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Add', plan => { "copy key" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', source => 'source-key', acl_short => 'object-acl', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'storage-class', x_amz_website_redirect_location => 'location-value', }, metadata => { foo => 'foo-value', }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', value => '', acl_short => 'object-acl', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'storage-class', x_amz_website_redirect_location => 'location-value', x_amz_meta_foo => 'foo-value', 'x-amz-metadata-directive' => 'REPLACE', 'x-amz-copy-source' => 'source-key', } }, }, } } sub expect_operation_object_edit_metadata { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Add', plan => { "copy key" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', acl_short => 'object-acl', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'storage-class', x_amz_website_redirect_location => 'location-value', }, metadata => { foo => 'foo-value', }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', value => '', acl_short => 'object-acl', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'storage-class', x_amz_website_redirect_location => 'location-value', x_amz_meta_foo => 'foo-value', 'x-amz-metadata-directive' => 'REPLACE', 'x-amz-copy-source' => '/bucket-name/some-key', } }, }, } } Net-Amazon-S3-0.991/t/test-helper-errors.pl0000644000175000017500000000157114264646670017345 0ustar branobrano use strict; use warnings; sub expect_error; sub expect_s3_error_access_denied { expect_error AccessDenied => 'Access denied error message'; } sub expect_s3_error_bucket_exists { expect_error BucketAlreadyExists => 'Bucket already exists error message'; } sub expect_s3_error_bucket_not_empty { expect_error BucketNotEmpty => 'Bucket not empty error message'; } sub expect_s3_error_bucket_not_found { expect_error NoSuchBucket => 'No such bucket error message'; } sub expect_s3_error_invalid_bucket_name { expect_error InvalidBucketName => 'Invalid bucket name error message'; } sub expect_s3_error_invalid_object_state { expect_error InvalidObjectState => 'Invalid object state error message'; } sub expect_s3_error_object_not_found { expect_error NoSuchKey => 'No such key error message'; } sub expect_http_error_bad_request { expect_error 400 => 'Bad Request'; } 1; Net-Amazon-S3-0.991/t/s3-operation-buckets-list.t0000644000175000017500000000121114264646670020350 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_buckets_list ( "API" => \& api_buckets_list, "Client" => \& client_buckets_list, ); had_no_warnings; done_testing; sub api_buckets_list { my (%args) = @_; build_default_api->buckets (%args); } sub client_buckets_list { my (%args) = @_; build_default_client->buckets (%args); } sub expect_operation_buckets_list { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Buckets::List', plan => { "list buckets" => { act_arguments => [ ], }, } } Net-Amazon-S3-0.991/t/s3-request-object-acl-fetch.t0000644000175000017500000000107114264646670020525 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'get object access control' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Fetch::Request', with_bucket => 'some-bucket', with_key => 'some/key', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?acl', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-bucket-tags-delete.t0000644000175000017500000000247214264646670020355 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_tags_delete ]; plan tests => 5; expect_client_bucket_tags_delete 'delete bucket tags' => ( with_bucket => 'some-bucket', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_data => bool (1), ); expect_client_bucket_tags_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_access_denied, ); expect_client_bucket_tags_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_bucket_not_found, ); expect_client_bucket_tags_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-bucket-create.t0000644000175000017500000001004714264646670016712 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_create ]; plan tests => 11; expect_api_bucket_create 'simple create bucket (default region us-east-1)' => ( with_bucket => 'some-bucket', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_data => all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'some-bucket'), ), ); expect_api_bucket_create 'create bucket in different region' => ( with_bucket => 'some-bucket', with_region => 'ca-central-1', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => fixture ('request::bucket_create_ca_central_1')->{content}, expect_data => all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'some-bucket'), ), ); expect_api_bucket_create 'create bucket with deprecated acl_short' => ( with_bucket => 'some-bucket', with_acl_short => 'private', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private' }, expect_data => all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'some-bucket'), ), ); expect_api_bucket_create 'create bucket with canned acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private' }, expect_data => all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'some-bucket'), ), ); expect_api_bucket_create 'create bucket with canned acl coercion' => ( with_bucket => 'some-bucket', with_acl => 'private', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private' }, expect_data => all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'some-bucket'), ), ); expect_api_bucket_create 'create bucket with explicit acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, expect_data => all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'some-bucket'), ), ); expect_api_bucket_create 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_access_denied, ); expect_api_bucket_create 'S3 error - Bucket Already Exists' => ( with_bucket => 'some-bucket', with_response_fixture ('error::bucket_already_exists'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_bucket_exists, ); expect_api_bucket_create 'S3 error - Invalid Bucket Name' => ( with_bucket => 'some-bucket', with_response_fixture ('error::invalid_bucket_name'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_invalid_bucket_name, ); expect_api_bucket_create 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-bucket-acl-set.t0000644000175000017500000000205114264646670020545 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_bucket_acl_set ( 'API / legacy' => \& api_bucket_acl_set_legacy, 'API / named arguments' => \& api_bucket_acl_set_named, 'Client' => \& client_bucket_acl_set, ); had_no_warnings; done_testing; sub api_bucket_acl_set_legacy { my (%args) = @_; build_default_api_bucket (%args) ->set_acl (\ %args) ; } sub api_bucket_acl_set_named { my (%args) = @_; build_default_api_bucket (%args) ->set_acl (%args) ; } sub client_bucket_acl_set { my (%args) = @_; build_default_client_bucket (%args) ->set_acl (%args) ; } sub expect_operation_bucket_acl_set { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Bucket::Acl::Set', plan => { "set bucket acl" => { act_arguments => [ bucket => 'bucket-name', acl => 'private', acl_short => 'public', acl_xml => 'some xml placeholder', ], }, } } Net-Amazon-S3-0.991/t/s3-request-object-acl-set.t0000644000175000017500000000623414264646670020235 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 8; behaves_like_net_amazon_s3_request 'set object access control with (deprecated) acl_short' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Set::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl_short => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?acl', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'set object access control with canned acl' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Set::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?acl', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'set object access control with canned acl coercion' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Set::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?acl', expect_request_headers => { 'x-amz-acl' => 'private' }, ); behaves_like_net_amazon_s3_request 'set object access control with explicit acl' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Set::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?acl', expect_request_headers => { 'x-amz-grant-read' => 'id="123", id="234"', 'x-amz-grant-write' => 'id="345"', }, ); behaves_like_net_amazon_s3_request 'set object access control with body acl' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Set::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl_xml => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?acl', expect_request_headers => { }, ); behaves_like_net_amazon_s3_request 'set object access control without body or header acl' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Set::Request', with_bucket => 'some-bucket', with_key => 'some/key', throws => re( qr/need either acl_xml or acl/ ), ); behaves_like_net_amazon_s3_request 'set object access control with both body and header acl specified' => ( request_class => 'Net::Amazon::S3::Operation::Object::Acl::Set::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => 'private', with_acl_xml => 'private', throws => re( qr/can not provide both acl_xml and acl/ ), ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-object-acl-get.t0000644000175000017500000000360114264646670016752 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } BEGIN { require "$FindBin::Bin/test-helper-s3-api-error-confess.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_acl_get ]; plan tests => 6; expect_api_object_acl_get 'get bucket acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('response::acl'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_data => fixture ('response::acl')->{content}, ); expect_api_object_acl_get 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_s3_error_access_denied, ); expect_api_object_acl_get 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_s3_error_bucket_not_found, ); expect_api_object_acl_get 'S3 error - Object Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_s3_error_object_not_found, ); expect_api_object_acl_get 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-bucket-objects-delete.t0000644000175000017500000000365714264646670021056 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_objects_delete ]; plan tests => 5; expect_client_bucket_objects_delete 'delete multiple objects' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('response::bucket_objects_delete_quiet_without_errors'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_data => all ( obj_isa ('HTTP::Response'), methods (is_success => bool (1)), ), expect_request_content => <<'XML', true key-1 key-2 XML expect_request_headers => { content_md5 => 'gAp9c7yOkifhnztMWAOlCg==', }, ); expect_client_bucket_objects_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('error::access_denied'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_s3_error_access_denied, ); expect_client_bucket_objects_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('error::no_such_bucket'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_s3_error_bucket_not_found, ); expect_client_bucket_objects_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_keys => [qw[ key-1 key-2 ]], with_response_fixture ('error::http_bad_request'), expect_request => { POST => 'https://some-bucket.s3.amazonaws.com/?delete' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-fetch.t0000644000175000017500000001143114264646670020301 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_fetch ( 'API / fetch' => \& api_object_fetch, 'API / fetch into file' => \& api_object_fetch_file, 'API / fetch / named arguments' => \& api_object_fetch_named, 'API / fetch into file / named arguments' => \& api_object_fetch_file_named, 'API / S3->get_key' => \& api_object_s3_fetch, 'API / S3->get_key / named arguments' => \& api_object_s3_fetch_named, ); expect_operation_object_head ( 'API / head key legacy' => \& api_object_head_legacy, 'API / head key named arguments' => \& api_object_head_named, ); expect_operation_object_fetch_content ( 'Client' => \& client_object_fetch_content, 'Client' => \& client_object_fetch_decoded_content, ); expect_operation_object_fetch_filename ( 'API' => \& api_object_fetch_filename, 'Client' => \& client_object_fetch_filename, ); expect_operation_object_fetch_callback ( 'Client' => \& client_object_fetch_callback, ); had_no_warnings; done_testing; sub api_object_s3_fetch { my (%args) = @_; build_default_api ->get_key (\ %args) ; } sub api_object_s3_fetch_named { my (%args) = @_; build_default_api ->get_key (%args) ; } sub api_object_fetch { my (%args) = @_; build_default_api_bucket (%args) ->get_key ( $args{key}, $args{method}, $args{filename}, ) ; } sub api_object_fetch_named { my (%args) = @_; build_default_api_bucket (%args) ->get_key (%args) ; } sub api_object_fetch_file { my (%args) = @_; build_default_api_bucket (%args) ->get_key ( $args{key}, $args{method}, \ $args{filename}, ) ; } sub api_object_fetch_file_named { my (%args) = @_; $args{filename} = \ delete $args{filename}; build_default_api_bucket (%args) ->get_key (%args) ; } sub api_object_fetch_filename { my (%args) = @_; build_default_api_bucket (%args) ->get_key_filename ( $args{key}, $args{method}, $args{filename}, ) ; } sub client_object_fetch_content { my (%args) = @_; build_default_client_object (%args) ->get ; } sub client_object_fetch_decoded_content { my (%args) = @_; build_default_client_object (%args) ->get_decoded ; } sub client_object_fetch_filename { my (%args) = @_; build_default_client_object (%args) ->get_filename ($args{filename}) ; } sub client_object_fetch_callback { my (%args) = @_; build_default_client_object (%args) ->get_callback ($args{filename}) ; } sub api_object_head_legacy { my (%args) = @_; build_default_api_bucket (%args) ->head_key ( $args{key}, ) ; } sub api_object_head_named { my (%args) = @_; build_default_api_bucket (%args) ->head_key (%args) ; } sub expect_operation_object_fetch { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Fetch', plan => { "fetch object" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', method => 'GET', filename => 'foo', ], }, } } sub expect_operation_object_fetch_content { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Fetch', plan => { "fetch object content" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', ], expect_arguments => { bucket => 'bucket-name', key => 'key-name', method => 'GET', }, }, } } sub expect_operation_object_fetch_filename { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Fetch', plan => { "fetch object into file" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', method => 'GET', filename => 'foo', ], }, } } sub expect_operation_object_fetch_callback { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Fetch', plan => { "fetch object with callback" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', method => 'GET', filename => sub { }, ], expect_arguments => { bucket => 'bucket-name', key => 'key-name', method => 'GET', filename => expect_coderef, }, }, } } sub expect_operation_object_head { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Fetch', plan => { "head key" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', method => 'HEAD', ], expect_arguments => { bucket => 'bucket-name', key => 'key-name', method => 'HEAD', filename => undef, }, }, } } Net-Amazon-S3-0.991/t/api-bucket-acl-set.t0000644000175000017500000000644714264646670017010 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_acl_set ]; plan tests => 9; expect_api_bucket_acl_set 'set bucket acl using deprecated acl_short' => ( with_bucket => 'some-bucket', with_acl_short => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_api_bucket_acl_set 'set bucket acl using canned acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_api_bucket_acl_set 'set bucket acl using canned acl coercion' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_api_bucket_acl_set 'set bucket acl using explicit acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, expect_data => bool (1), ); expect_api_bucket_acl_set 'set bucket acl using XML content' => ( with_bucket => 'some-bucket', with_acl_xml => 'PASSTHROUGH', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => 'PASSTHROUGH', expect_request_headers => { x_amz_acl => undef, }, expect_data => bool (1), ); expect_api_bucket_acl_set 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_s3_error_access_denied, ); expect_api_bucket_acl_set 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_s3_error_bucket_not_found, ); expect_api_bucket_acl_set 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-upload-complete.t0000644000175000017500000000210614264646670022301 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_upload_complete ( 'Client / named arguments' => \& client_object_upload_complete_named_arguments, 'Client / configuration hash' => \& client_object_upload_complete_configuration_hash, ); had_no_warnings; done_testing; sub client_object_upload_complete_named_arguments { my (%args) = @_; build_default_client_object (%args) ->complete_multipart_upload (%args) ; } sub client_object_upload_complete_configuration_hash { my (%args) = @_; build_default_client_object (%args) ->complete_multipart_upload (\ %args) ; } sub expect_operation_object_upload_complete { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Upload::Complete', plan => { "complete upload" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', upload_id => 42, etags => [ 'etag-1', 'etag-2' ], part_numbers => [ 1, 2 ], ], }, } } Net-Amazon-S3-0.991/t/s3-request-object-tags-add.t0000644000175000017500000000232514264646670020366 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-request.pl" } BEGIN { require "$FindBin::Bin/test-helper-tags.pl" } plan tests => 3; behaves_like_net_amazon_s3_request 'add some tags to an object' => ( request_class => 'Net::Amazon::S3::Operation::Object::Tags::Add::Request', with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, expect_request_method => 'PUT', expect_request_path => 'some-bucket/some-key?tagging', expect_request_header => { content_type => 'application/xml', }, expect_request_content => fixture_tags_foo_bar_xml, ); behaves_like_net_amazon_s3_request 'add some tags to an object version' => ( request_class => 'Net::Amazon::S3::Operation::Object::Tags::Add::Request', with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_version_id => 42, expect_request_method => 'PUT', expect_request_path => 'some-bucket/some-key?tagging&versionId=42', expect_request_header => { content_type => 'application/xml', }, expect_request_content => fixture_tags_foo_bar_xml, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-s3-api-error-confess.pl0000644000175000017500000000205714264646670021712 0ustar branobrano use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-errors.pl" } no warnings 'redefine'; sub expect_s3_error_access_denied { return +( throws => qr/Net::Amazon::S3: Amazon responded with 403 Forbidden/, expect_s3_err => 'network_error', expect_s3_errstr => '403 Forbidden', ); } sub expect_s3_error_invalid_object_state { return +( throws => qr/Net::Amazon::S3: Amazon responded with 403 Forbidden/, expect_s3_err => 'network_error', expect_s3_errstr => '403 Forbidden', ); } sub expect_s3_error_bucket_not_found { return +( expect_data => undef, expect_s3_err => undef, expect_s3_errstr => undef, ); } sub expect_s3_error_object_not_found { return +( expect_data => undef, expect_s3_err => undef, expect_s3_errstr => undef, ); } sub expect_http_error_bad_request { return +( throws => qr/Net::Amazon::S3: Amazon responded with 400 Bad Request/, expect_s3_err => 'network_error', expect_s3_errstr => '400 Bad Request', ); } 1; Net-Amazon-S3-0.991/t/client-object-delete.t0000644000175000017500000000337214264646670017412 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_delete ]; plan tests => 6; expect_client_object_delete 'delete object' => ( with_bucket => 'some-bucket', with_key => 'some-key', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => bool (1), ); expect_client_object_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_client_object_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_bucket_not_found, ); expect_client_object_delete 'S3 error - No Such Key' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_object_not_found, ); expect_client_object_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-bucket-delete.t0000644000175000017500000000255614264646670020471 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_bucket_delete ( 'API / with bucket name' => \& api_bucket_delete_identified_by_name, 'API / with bucket instance' => \& api_bucket_delete_instance, 'API / with named arguments' => \& api_bucket_delete_named, 'API / via bucket' => \& api_bucket_delete_via_bucket, 'Client' => \& client_bucket_delete, ); had_no_warnings; done_testing; sub api_bucket_delete_identified_by_name { my (%args) = @_; build_default_api->delete_bucket (\ %args); } sub api_bucket_delete_instance { my (%args) = @_; build_default_api->delete_bucket (build_default_api->bucket (delete $args{bucket})); } sub api_bucket_delete_named { my (%args) = @_; build_default_api->delete_bucket (%args); } sub api_bucket_delete_via_bucket { my (%args) = @_; build_default_api ->bucket (delete $args{bucket}) ->delete_bucket (%args) ; } sub client_bucket_delete { my (%args) = @_; build_default_client ->bucket (name => delete $args{bucket}) ->delete (%args) ; } sub expect_operation_bucket_delete { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Bucket::Delete', plan => { "delete bucket" => { act_arguments => [ bucket => 'bucket-name', ], }, } } Net-Amazon-S3-0.991/t/author-eol.t0000644000175000017500000003374114264646670015512 0ustar branobrano BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19 use Test::More 0.88; use Test::EOL; my @files = ( 'bin/s3cl', 'lib/Net/Amazon/S3.pm', 'lib/Net/Amazon/S3/ACL.pod', 'lib/Net/Amazon/S3/ACL/Canned.pm', 'lib/Net/Amazon/S3/ACL/Grantee.pm', 'lib/Net/Amazon/S3/ACL/Grantee/Email.pm', 'lib/Net/Amazon/S3/ACL/Grantee/Group.pm', 'lib/Net/Amazon/S3/ACL/Grantee/User.pm', 'lib/Net/Amazon/S3/ACL/Set.pm', 'lib/Net/Amazon/S3/Authorization.pm', 'lib/Net/Amazon/S3/Authorization/Basic.pm', 'lib/Net/Amazon/S3/Authorization/IAM.pm', 'lib/Net/Amazon/S3/Bucket.pm', 'lib/Net/Amazon/S3/Client.pm', 'lib/Net/Amazon/S3/Client/Bucket.pm', 'lib/Net/Amazon/S3/Client/Object.pm', 'lib/Net/Amazon/S3/Client/Object/Range.pm', 'lib/Net/Amazon/S3/Constants.pm', 'lib/Net/Amazon/S3/Constraint/ACL/Canned.pm', 'lib/Net/Amazon/S3/Constraint/Etag.pm', 'lib/Net/Amazon/S3/Error/Handler.pm', 'lib/Net/Amazon/S3/Error/Handler/Confess.pm', 'lib/Net/Amazon/S3/Error/Handler/Legacy.pm', 'lib/Net/Amazon/S3/Error/Handler/Status.pm', 'lib/Net/Amazon/S3/Error/Handler/X.pm', 'lib/Net/Amazon/S3/Features.pod', 'lib/Net/Amazon/S3/HTTPRequest.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch/Request.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch/Response.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Acl/Set.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Acl/Set/Request.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Acl/Set/Response.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Create.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Create/Request.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Create/Response.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Delete.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Delete/Request.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Delete/Response.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Location.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Location/Request.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Location/Response.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Tags/Add.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Tags/Add/Request.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Tags/Add/Response.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete/Request.pm', 'lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete/Response.pm', 'lib/Net/Amazon/S3/Operation/Buckets/List.pm', 'lib/Net/Amazon/S3/Operation/Buckets/List/Request.pm', 'lib/Net/Amazon/S3/Operation/Buckets/List/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Acl/Fetch.pm', 'lib/Net/Amazon/S3/Operation/Object/Acl/Fetch/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Acl/Fetch/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Acl/Set.pm', 'lib/Net/Amazon/S3/Operation/Object/Acl/Set/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Acl/Set/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Add.pm', 'lib/Net/Amazon/S3/Operation/Object/Add/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Add/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Delete.pm', 'lib/Net/Amazon/S3/Operation/Object/Delete/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Delete/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Fetch.pm', 'lib/Net/Amazon/S3/Operation/Object/Fetch/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Fetch/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Head.pm', 'lib/Net/Amazon/S3/Operation/Object/Head/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Head/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Restore.pm', 'lib/Net/Amazon/S3/Operation/Object/Restore/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Restore/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Tags/Add.pm', 'lib/Net/Amazon/S3/Operation/Object/Tags/Add/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Tags/Add/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Tags/Delete.pm', 'lib/Net/Amazon/S3/Operation/Object/Tags/Delete/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Tags/Delete/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Abort.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Abort/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Abort/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Complete.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Complete/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Complete/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Create.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Create/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Create/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Part.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Part/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Part/Response.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Parts.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Parts/Request.pm', 'lib/Net/Amazon/S3/Operation/Object/Upload/Parts/Response.pm', 'lib/Net/Amazon/S3/Operation/Objects/Delete.pm', 'lib/Net/Amazon/S3/Operation/Objects/Delete/Request.pm', 'lib/Net/Amazon/S3/Operation/Objects/Delete/Response.pm', 'lib/Net/Amazon/S3/Operation/Objects/List.pm', 'lib/Net/Amazon/S3/Operation/Objects/List/Request.pm', 'lib/Net/Amazon/S3/Operation/Objects/List/Response.pm', 'lib/Net/Amazon/S3/Request.pm', 'lib/Net/Amazon/S3/Request/Bucket.pm', 'lib/Net/Amazon/S3/Request/Object.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Header.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Header/ACL.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_length.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_md5.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_type.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Header/Copy_source.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Header/Encryption.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Method.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Method/DELETE.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Method/GET.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Method/HEAD.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Method/POST.pm', 'lib/Net/Amazon/S3/Request/Role/HTTP/Method/PUT.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Action.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Action/Acl.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Action/Delete.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Action/Location.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Action/Restore.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Action/Tagging.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Action/Uploads.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param/Delimiter.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param/Marker.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param/Max_keys.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param/Part_number.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param/Prefix.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param/Upload_id.pm', 'lib/Net/Amazon/S3/Request/Role/Query/Param/Version_id.pm', 'lib/Net/Amazon/S3/Request/Role/Tags/Add.pm', 'lib/Net/Amazon/S3/Request/Role/XML/Content.pm', 'lib/Net/Amazon/S3/Request/Service.pm', 'lib/Net/Amazon/S3/Response.pm', 'lib/Net/Amazon/S3/Role/ACL.pm', 'lib/Net/Amazon/S3/Role/Bucket.pm', 'lib/Net/Amazon/S3/Signature.pm', 'lib/Net/Amazon/S3/Signature/V2.pm', 'lib/Net/Amazon/S3/Signature/V4.pm', 'lib/Net/Amazon/S3/Signature/V4Implementation.pm', 'lib/Net/Amazon/S3/Utils.pm', 'lib/Net/Amazon/S3/Vendor.pm', 'lib/Net/Amazon/S3/Vendor/Amazon.pm', 'lib/Net/Amazon/S3/Vendor/Generic.pm', 'lib/Net/Amazon/S3/X.pm', 'lib/Shared/Examples/Net/Amazon/S3.pm', 'lib/Shared/Examples/Net/Amazon/S3/API.pm', 'lib/Shared/Examples/Net/Amazon/S3/Client.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/access_denied.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/bucket_already_exists.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/bucket_not_empty.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/http_bad_request.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/invalid_bucket_name.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/invalid_object_state.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/no_such_bucket.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/error/no_such_key.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/request/bucket_create_ca_central_1.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/acl.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_delete_quiet_without_errors.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_google_cloud_storage.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_delimiter.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_filter.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_filter_truncated.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_prefix_and_delimiter.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/create_multipart_upload_with_success.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/http_ok_empty.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_with_owner_displayname.pm', 'lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_without_owner_displayname.pm', 'lib/Shared/Examples/Net/Amazon/S3/Request.pm', 't/01api.t', 't/02client.t', 't/03token.t', 't/acl-set.t', 't/api-bucket-acl-get.t', 't/api-bucket-acl-set.t', 't/api-bucket-create.t', 't/api-bucket-delete.t', 't/api-bucket-objects-delete.t', 't/api-bucket-objects-list.t', 't/api-bucket-tags-add.t', 't/api-bucket-tags-delete.t', 't/api-build-bucket.t', 't/api-construct.t', 't/api-object-acl-get.t', 't/api-object-acl-set.t', 't/api-object-create.t', 't/api-object-delete.t', 't/api-object-fetch.t', 't/api-object-head.t', 't/api-object-tags-add.t', 't/api-object-tags-delete.t', 't/api-service-buckets-list.t', 't/author-eol.t', 't/client-bucket-acl-get.t', 't/client-bucket-acl-set.t', 't/client-bucket-create.t', 't/client-bucket-delete.t', 't/client-bucket-objects-delete.t', 't/client-bucket-objects-list.t', 't/client-bucket-tags-add.t', 't/client-bucket-tags-delete.t', 't/client-construct.t', 't/client-object-acl-set.t', 't/client-object-create.t', 't/client-object-delete.t', 't/client-object-exists.t', 't/client-object-fetch.t', 't/client-object-head.t', 't/client-object-tags-add.t', 't/client-object-tags-delete.t', 't/client-service-buckets-list.t', 't/data/s3-operation-object-add.txt', 't/error-handler-x.t', 't/issue-39-content-length-0.t', 't/issue-88-non-standard-service-port.t', 't/query-string-authentication-uri.t', 't/request.t', 't/response.t', 't/s3-operation-bucket-acl-fetch.t', 't/s3-operation-bucket-acl-set.t', 't/s3-operation-bucket-create.t', 't/s3-operation-bucket-delete.t', 't/s3-operation-bucket-location.t', 't/s3-operation-bucket-tags-add.t', 't/s3-operation-bucket-tags-delete.t', 't/s3-operation-buckets-list.t', 't/s3-operation-object-acl-fetch.t', 't/s3-operation-object-acl-set.t', 't/s3-operation-object-add.t', 't/s3-operation-object-copy.t', 't/s3-operation-object-delete.t', 't/s3-operation-object-fetch.t', 't/s3-operation-object-head.t', 't/s3-operation-object-restore.t', 't/s3-operation-object-tags-add.t', 't/s3-operation-object-tags-delete.t', 't/s3-operation-object-upload-abort.t', 't/s3-operation-object-upload-complete.t', 't/s3-operation-object-upload-create.t', 't/s3-operation-object-upload-part.t', 't/s3-operation-objects-delete.t', 't/s3-operation-objects-list.t', 't/s3-request-bucket-acl-fetch.t', 't/s3-request-bucket-acl-set.t', 't/s3-request-bucket-create.t', 't/s3-request-bucket-delete.t', 't/s3-request-bucket-location.t', 't/s3-request-bucket-objects-delete.t', 't/s3-request-bucket-objects-list.t', 't/s3-request-bucket-tags-add.t', 't/s3-request-bucket-tags-delete.t', 't/s3-request-object-acl-fetch.t', 't/s3-request-object-acl-set.t', 't/s3-request-object-add.t', 't/s3-request-object-delete.t', 't/s3-request-object-fetch.t', 't/s3-request-object-restore.t', 't/s3-request-object-tags-add.t', 't/s3-request-object-tags-delete.t', 't/s3-request-object-upload-abort.t', 't/s3-request-object-upload-complete.t', 't/s3-request-object-upload-create.t', 't/s3-request-object-upload-part.t', 't/s3-request-object-upload-parts.t', 't/s3-request-service-buckets-list.t', 't/s3-response-object-upload-create.t', 't/s3-response-service-buckets-list.t', 't/signature-v4-with-security-token.t', 't/test-helper-common.pl', 't/test-helper-errors.pl', 't/test-helper-operation.pl', 't/test-helper-s3-api-error-confess.pl', 't/test-helper-s3-api-error-status.pl', 't/test-helper-s3-api.pl', 't/test-helper-s3-client.pl', 't/test-helper-s3-request.pl', 't/test-helper-s3-response.pl', 't/test-helper-tags.pl', 't/use-api.t', 't/use-client.t', 't/utils-parse-arguments.t', 't/vendor-amazon.t', 't/vendor-generic.t', 't/vendor-info.t' ); eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files; done_testing; Net-Amazon-S3-0.991/t/02client.t0000644000175000017500000002752414264646670015055 0ustar branobrano#!perl use warnings; use strict; use lib 'lib'; use Digest::MD5::File qw(file_md5_hex); use LWP::Simple; use File::stat; use Test::More; use Test::Exception; use File::Temp qw/ :seekable /; unless ( $ENV{'AMAZON_S3_EXPENSIVE_TESTS'} ) { plan skip_all => 'Testing this module for real costs money.'; } else { plan tests => 53; } use_ok('Net::Amazon::S3'); my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'}; my $aws_secret_access_key = $ENV{'AWS_ACCESS_KEY_SECRET'}; my $s3 = Net::Amazon::S3->new( aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, retry => 1, ); my $readme_size = stat('README.md')->size; my $readme_md5hex = file_md5_hex('README.md'); my $client = Net::Amazon::S3::Client->new( s3 => $s3 ); my @buckets = $client->buckets; my $bucket_name = 'net-amazon-s3-test-' . lc($aws_access_key_id) . '-'. time; my $bucket = $client->create_bucket( name => $bucket_name, acl_short => 'public-read', location_constraint => 'EU', ); eval { is( $bucket->name, $bucket_name, 'newly created bucket has correct name' ); like( $bucket->acl, qr{[a-z0-9]{64}.+?[a-z0-9]{64}.+?FULL_CONTROLhttp://acs.amazonaws.com/groups/global/AllUsersREAD}, 'newly created bucket is public-readable' ); is( $bucket->location_constraint, 'eu-west-1', 'newly created bucket is in the EU' ); my $stream = $bucket->list; until ( $stream->is_done ) { foreach my $object ( $stream->items ) { $object->delete; } } my $count = 0; $stream = $bucket->list; until ( $stream->is_done ) { foreach my $object ( $stream->items ) { $count++; } } is( $count, 0, 'newly created bucket has no objects' ); my $object = $bucket->object( key => 'this is the key' ); ok( !$object->exists, 'object does not exist yet' ); $object->put('this is the value'); ok( $object->exists, 'object now exists yet' ); my @objects; @objects = (); $stream = $bucket->list( { prefix => 'this is the key' } ); until ( $stream->is_done ) { foreach my $object ( $stream->items ) { push @objects, $object; } } is( @objects, 1, 'bucket list with prefix finds key' ); @objects = (); $stream = $bucket->list( { prefix => 'this is not the key' } ); until ( $stream->is_done ) { foreach my $object ( $stream->items ) { push @objects, $object; } } is( @objects, 0, 'bucket list with different prefix does not find key' ); @objects = (); $stream = $bucket->list; until ( $stream->is_done ) { foreach my $object ( $stream->items ) { push @objects, $object; } } is( @objects, 1, 'bucket list finds newly created key' ); is( $objects[0]->key, 'this is the key', 'newly created object has the right key' ); is( $objects[0]->etag, '94325a12f8db22ffb6934cc5f22f6698', 'newly created object has the right etag' ); is( $objects[0]->size, '17', 'newly created object has the right size' ); is( $object->get, 'this is the value', 'newly created object has the right value' ); is( $bucket->object( key => 'this is the key' )->get, 'this is the value', 'newly created object fetched by name has the right value' ); is( get( $object->uri ), undef, 'newly created object cannot be fetched by uri' ); $object->expires('2037-01-01'); is( get( $object->query_string_authentication_uri() ), 'this is the value', 'newly created object can be fetch by authentication uri' ); my $signed_url = $object->query_string_authentication_uri({ 'response-content-disposition' => 'attachment; filename=abc.doc' }); like( $signed_url, qr/response-content-disposition/, 'cuttom response headers included in the signed uri' ); is( get( $signed_url ), 'this is the value', 'newly created object can be fetch by authentication uri with custom headers' ); $object->delete; # upload a public object $object = $bucket->object( key => 'this is the public key', acl_short => 'public-read', content_type => 'text/plain', content_encoding => 'identity', expires => '2001-02-03', ); $object->put('this is the public value'); is( get( $object->uri ), 'this is the public value', 'newly created public object is publically accessible' ); is( ( head( $object->uri ) )[0], 'text/plain', 'newly created public object has the right content type' ); is( ( head( $object->uri ) )[3], $object->expires->epoch, 'newly created public object has the right expires' ); $object->delete; # delete a non-existant object $object = $bucket->object( key => 'not here' ); throws_ok { $object->get } qr/NoSuchKey/, 'getting non-existant object throws exception'; # upload a file with put_filename $object = $bucket->object( key => 'the readme' ); $object->put_filename('README.md'); @objects = (); $stream = $bucket->list; until ( $stream->is_done ) { foreach my $object ( $stream->items ) { push @objects, $object; } } is( @objects, 1, 'have newly uploaded object' ); is( $objects[0]->key, 'the readme', 'newly uploaded object has the right key' ); is( $objects[0]->etag, $readme_md5hex, 'newly uploaded object has the right etag' ); is( $objects[0]->size, $readme_size, 'newly created object has the right size' ); ok( $objects[0]->last_modified, 'newly created object has a last modified' ); $object->delete; # upload a public object with put_filename $object = $bucket->object( key => 'the public readme', acl_short => 'public-read' ); $object->put_filename('README.md'); is( length( get( $object->uri ) ), $readme_size, 'newly uploaded public object has the right size' ); $object->delete; # upload a file with put_filename with known md5hex size and AES256 encryption $object = $bucket->object( key => 'the new readme', etag => $readme_md5hex, size => $readme_size, encryption => 'AES256' ); $object->put_filename('README.md'); @objects = (); $stream = $bucket->list; until ( $stream->is_done ) { foreach my $object ( $stream->items ) { push @objects, $object; } } is( @objects, 1, 'have newly uploaded object' ); is( $objects[0]->key, 'the new readme', 'newly uploaded object has the right key' ); is( $objects[0]->etag, $readme_md5hex, 'newly uploaded object has the right etag' ); is( $objects[0]->size, $readme_size, 'newly created object has the right size' ); ok( $objects[0]->last_modified, 'newly created object has a last modified' ); # download an object with get_filename my $tmp_fh = File::Temp->new(); $object->get_filename($tmp_fh->filename); is( stat($tmp_fh->filename)->size, $readme_size, 'download has right size' ); is( file_md5_hex($tmp_fh->filename), $readme_md5hex, 'download has right etag' ); $object->delete; # upload a public object with put_filename with known md5hex and size $object = $bucket->object( key => 'the new public readme', etag => $readme_md5hex, size => $readme_size, acl_short => 'public-read' ); $object->put_filename( 'README.md', $readme_md5hex, $readme_size ); is( length( get( $object->uri ) ), $readme_size, 'newly uploaded public object has the right size' ); $object->delete; { # upload an object using multipart upload and then abort it $object = $bucket->object( key => 'new multipart file soon to be aborted', acl_short => 'public-read' ); my $upload_id; ok( $upload_id = $object->initiate_multipart_upload, "can initiate a new multipart upload -- $upload_id" ); #put part my $put_part_response; ok( $put_part_response = $object->put_part( part_number => 1, upload_id => $upload_id, value => 'x' x ( 5 * 1024 * 1024 ) ), 'Got a successful response for PUT part' ); ok( $put_part_response->header('ETag'), 'etag ok' ); ok( my $abort_response = $object->abort_multipart_upload( upload_id => $upload_id ), 'Got a successful response for DELETE multipart upload' ); ok( !$object->exists, "object has now been deleted" ); } # upload an object using multipart upload $object = $bucket->object( key => 'new multipart file', acl_short => 'public-read' ); my $upload_id; ok($upload_id = $object->initiate_multipart_upload, "can initiate a new multipart upload"); #put part my $put_part_response; ok( $put_part_response = $object->put_part(part_number => 1, upload_id => $upload_id, value => 'x' x (5 * 1024 * 1024)), 'Got a successful response for PUT part' ); my @etags; push @etags, $put_part_response->header('ETag'); ok( $put_part_response = $object->put_part(part_number => 2, upload_id => $upload_id, value => 'z' x (1024 * 1024)), 'Got a successful response for 2nd PUT part' ); push @etags, $put_part_response->header('ETag'); # TODO list part? - We've got this, but how to expose it nicely? #complete multipart upload my $complete_upload_response; ok( $complete_upload_response = $object->complete_multipart_upload( upload_id => $upload_id, part_numbers => [1,2], etags => \@etags), "successful response for complete multipart upload" ); #get the file and check that it looks like we expect ok($object->exists, "object has now been created"); $tmp_fh = File::Temp->new(); $object->get_filename($tmp_fh->filename); is( stat($tmp_fh->filename)->size, 6 * 1024 * 1024, "downloaded file has a size equivalent to the sum of it's parts"); $tmp_fh->seek((5 * 1024 * 1024) - 1, SEEK_SET); #jump to 5MB position my $test_bytes; read($tmp_fh, $test_bytes, 2); is($test_bytes, "xz", "The second chunk of the file begins in the correct place"); #test listing a multipart object $stream = $bucket->list({prefix => 'new multipart file'}); lives_ok {my @items = $stream->items} 'Listing a multipart file does not throw an exeption'; $object->delete; #test multi-object delete #make 3 identical objects @objects =(); for my $i (1..3) { my $bulk_object = $bucket->object( key => "bulk-readme-$i", etag => $readme_md5hex, size => $readme_size ); $bulk_object->put_filename('README.md'); push @objects, $bulk_object; } #now delete 2 of those objects ok($bucket->delete_multi_object(@objects[0..1]), "executed multi delete operation"); ok( !grep($_->exists, @objects[0..1]), "target objects no longer exist"); ok( $objects[2]->exists, "object not included in multi-object delete still exists" ); $objects[2]->delete; }; $bucket->delete; Net-Amazon-S3-0.991/t/s3-operation-object-acl-set.t0000644000175000017500000000276314264646670020550 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_acl_set ( 'API / legacy' => \& api_object_acl_set, 'API / legacy with key' => \& api_object_acl_set_key, 'API / named arguments' => \& api_object_acl_set_named, 'API / named arguments with key' => \& api_object_acl_set_named_key, 'Client' => \& client_object_acl_set, ); had_no_warnings; done_testing; sub api_object_acl_set { my (%args) = @_; build_default_api_bucket (%args) ->set_acl (\ %args) ; } sub api_object_acl_set_key { my (%args) = @_; build_default_api_bucket (%args) ->set_acl (delete $args{key}, \ %args) ; } sub api_object_acl_set_named { my (%args) = @_; build_default_api_bucket (%args) ->set_acl (%args) ; } sub api_object_acl_set_named_key { my (%args) = @_; build_default_api_bucket (%args) ->set_acl (delete $args{key}, %args) ; } sub client_object_acl_set { my (%args) = @_; build_default_client_object (%args) ->set_acl (%args) ; } sub expect_operation_object_acl_set { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Acl::Set', plan => { "set object acl" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', acl => 'private', acl_short => 'public', acl_xml => 'some xml placeholder', ], }, } } Net-Amazon-S3-0.991/t/issue-88-non-standard-service-port.t0000644000175000017500000000266514264646670022027 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-common.pl" } use Test::MockTime qw[ set_fixed_time ]; use Sub::Override; use Shared::Examples::Net::Amazon::S3 ( qw[ s3_api_with_signature_4 ], qw[ expect_net_amazon_s3_feature ], ); plan tests => 3; set_fixed_time '2011-09-09T23:36:00Z'; my $orig = \& Net::Amazon::S3::Signature::V4Implementation::_canonical_request; my $cannonical_request; my $guard = Sub::Override->new ('Net::Amazon::S3::Signature::V4Implementation::_canonical_request' => sub { my ($self, @params) = @_; $cannonical_request = $self->$orig (@params); }); expect_net_amazon_s3_feature "Signature V4 query_string_authentication_uri with non-standard port" => ( feature => 'signed_uri', with_s3 => s3_api_with_signature_4 (host => 'foo:9999'), with_bucket => 'some-bucket', with_key => 'some/key', with_expire_at => time + 123_000, with_region => 'eu-west-1', expect_uri => 'https://some-bucket.foo:9999/some/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIDEXAMPLE%2F20110909%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20110909T233600Z&X-Amz-Expires=123000&X-Amz-SignedHeaders=host&X-Amz-Signature=96068503a7efe97b987532326fa52fc75c643c65dc605734450fe573b18155ea', ); ok "Cannonical request should include non-standard port in host header", got => $cannonical_request =~ m/^host:some-bucket.foo:9999/m, ; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-add.t0000644000175000017500000002007614264646670017745 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } note "Client and API capabilities differs a lot"; expect_operation_object_add_scalar ( 'API / via Bucket' => \& api_object_add_scalar_via_bucket, 'API / via S3' => \& api_object_add_scalar_via_s3, 'API / via Bucket / named arguments' => \& api_object_add_scalar_via_bucket_named, 'API / via S3 / named arguments' => \& api_object_add_scalar_via_s3_named, ); expect_operation_object_add_file ( 'API / add key wrapper' => \& api_object_add_filename, 'API / add key' => \& api_object_add_file, 'API / add key wrapper / named arguments' => \& api_object_add_filename_named, ); expect_operation_object_client_add_scalar ( 'Client' => \& client_object_add_scalar, ); expect_operation_object_client_add_file ( 'Client / add key filename' => \& client_object_add_filename, ); had_no_warnings; done_testing; sub api_object_add_scalar_via_bucket { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->add_key ( delete $args{key}, delete $args{value}, \ %args ); } sub api_object_add_scalar_via_s3 { my (%args) = _api_expand_header_arguments @_; build_default_api ->add_key ( \ %args ); } sub api_object_add_scalar_via_bucket_named { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->add_key (%args) ; } sub api_object_add_scalar_via_s3_named { my (%args) = _api_expand_header_arguments @_; build_default_api ->add_key (%args) ; } sub api_object_add_file { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->add_key ( delete $args{key}, \ delete $args{value}, \ %args ); } sub api_object_add_filename { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->add_key_filename ( delete $args{key}, delete $args{value}, \ %args ); } sub api_object_add_filename_named { my (%args) = _api_expand_header_arguments @_; build_default_api_bucket (%args) ->add_key_filename ( delete $args{key}, delete $args{value}, \ %args ); } sub client_object_add_scalar { my (%args) = @_; my $headers = delete $args{headers}; build_default_client_bucket (%args) ->object ( key => $args{key}, expires => 2_345_567_890, storage_class => $headers->{x_amz_storage_class}, website_redirect_location => $headers->{x_amz_website_redirect_location}, user_metadata => $args{metadata}, content_encoding => $headers->{content_encoding}, acl => $args{acl}, encryption => $args{encryption}, ) ->put ($args{value}) ; } sub client_object_add_filename { my (%args) = @_; my $headers = delete $args{headers}; build_default_client_bucket (%args) ->object ( key => $args{key}, expires => 2_345_567_890, storage_class => $headers->{x_amz_storage_class}, website_redirect_location => $headers->{x_amz_website_redirect_location}, user_metadata => $args{metadata}, content_encoding => $headers->{content_encoding}, acl => $args{acl}, encryption => $args{encryption}, ) ->put_filename ($args{value}) ; } sub expect_operation_object_add_scalar { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Add', plan => { "add object with value from scalar" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', value => 'foo-bar-baz', acl => 'object-acl', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'storage-class', x_amz_website_redirect_location => 'location-value', }, metadata => { foo => 'foo-value', }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', value => 'foo-bar-baz', acl => 'object-acl', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'storage-class', x_amz_website_redirect_location => 'location-value', x_amz_meta_foo => 'foo-value', 'Content-Length' => 11, } }, }, } } sub expect_operation_object_add_file { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Add', plan => { "add object with value from file" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', value => "$FindBin::Bin/data/s3-operation-object-add.txt", acl => 'private', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'standard', x_amz_website_redirect_location => 'location-value', }, metadata => { foo => 'foo-value', }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', value => expect_coderef, acl => 'private', encryption => 'object-encryption', headers => { expires => 2_345_567_890, content_encoding => 'content-encoding', x_amz_storage_class => 'standard', x_amz_website_redirect_location => 'location-value', x_amz_meta_foo => 'foo-value', 'Content-Length' => 72, expect => '100-continue', } }, }, } } sub expect_operation_object_client_add_scalar { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Add', plan => { "add object with value from scalar" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', value => 'foo-bar-baz', acl => 'private', encryption => 'object-encryption', headers => { expires => 'expires-value', content_encoding => 'content-encoding', x_amz_storage_class => 'standard', x_amz_website_redirect_location => 'location-value', }, metadata => { foo => 'foo-value', }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', value => 'foo-bar-baz', acl => obj_isa ('Net::Amazon::S3::ACL::Canned'), encryption => 'object-encryption', headers => { 'Content-Length' => 11, 'Content-Type' => 'binary/octet-stream', 'Content-MD5' => ignore, 'Content-Encoding' => 'content-encoding', 'Expires' => 'Fri, 29 Apr 2044 18:38:10 GMT', 'x-amz-meta-foo' => 'foo-value', 'x-amz-website-redirect-location' => 'location-value', } }, }, } } sub expect_operation_object_client_add_file { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Add', plan => { "add object with value from scalar" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', value => "$FindBin::Bin/data/s3-operation-object-add.txt", acl => 'private', encryption => 'object-encryption', headers => { expires => 'expires-value', content_encoding => 'content-encoding', x_amz_storage_class => 'standard', x_amz_website_redirect_location => 'location-value', }, metadata => { foo => 'foo-value', }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', value => expect_coderef, acl => obj_isa ('Net::Amazon::S3::ACL::Canned'), encryption => 'object-encryption', headers => { 'Content-Length' => 72, 'Content-Type' => 'binary/octet-stream', 'Content-MD5' => ignore, 'Content-Encoding' => 'content-encoding', 'Expires' => 'Fri, 29 Apr 2044 18:38:10 GMT', 'x-amz-meta-foo' => 'foo-value', 'x-amz-website-redirect-location' => 'location-value', } }, }, } } Net-Amazon-S3-0.991/t/api-object-tags-add.t0000644000175000017500000000363714264646670017133 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } BEGIN { require "$FindBin::Bin/test-helper-tags.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_tags_add ]; plan tests => 5; expect_api_object_tags_add 'add tags to an object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('response::http_ok_empty'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_request_content => fixture_tags_foo_bar_xml, expect_request_headers => { content_type => 'application/xml', }, expect_data => bool (1), ); expect_api_object_tags_add 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_access_denied, ); expect_api_object_tags_add 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_bucket_not_found, ); expect_api_object_tags_add 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-s3-request.pl0000644000175000017500000000042214264646670020036 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-common.pl' } use Shared::Examples::Net::Amazon::S3 ( qw[ fixture ], ); use Shared::Examples::Net::Amazon::S3::Request ( qw[ behaves_like_net_amazon_s3_request ], ); 1; Net-Amazon-S3-0.991/t/use-api.t0000644000175000017500000000027014264646670014765 0ustar branobrano use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } plan tests => 2; use_ok 'Net::Amazon::S3'; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-object-create.t0000644000175000017500000001323114264646670016701 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_create ]; plan tests => 11; expect_api_object_create 'create object from scalar value' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', expect_data => bool (1), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => undef, expires => undef, }, ); expect_api_object_create 'create object with deprecated acl_short' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_acl_short => 'private', expect_data => bool (1), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => undef, expires => undef, x_amz_acl => 'private', }, ); expect_api_object_create 'create object with canned acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_data => bool (1), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => undef, expires => undef, x_amz_acl => 'private', }, ); expect_api_object_create 'create object with canned acl coercion' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_acl => 'private', expect_data => bool (1), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => undef, expires => undef, x_amz_acl => 'private', }, ); expect_api_object_create 'create object with explicit acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_data => bool (1), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => undef, expires => undef, x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, ); expect_api_object_create 'create object with server side encryption' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_encryption => 'AES256', expect_data => bool (1), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { content_length => 10, content_md5 => undef, expires => undef, x_amz_server_side_encryption => 'AES256', }, ); expect_api_object_create 'create object with headers recognized by Client::Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_cache_control => 'private', with_content_disposition => 'inline', with_content_encoding => 'identity', with_content_type => 'text/plain', with_expires => 'Fri, 09 Sep 2011 23:36:00 GMT', with_storage_class => 'reduced_redundancy', with_user_metadata => { Foo => 1, Bar => 2 }, expect_data => bool (1), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_content => 'some value', expect_request_headers => { cache_control => 'private', content_disposition => 'inline', content_encoding => 'identity', content_length => 10, content_type => 'text/plain', content_md5 => undef, expires => 'Fri, 09 Sep 2011 23:36:00 GMT', x_amz_meta_bar => 2, x_amz_meta_foo => 1, x_amz_storage_class => 'reduced_redundancy', }, ); expect_api_object_create 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_api_object_create 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_bucket_not_found, ); expect_api_object_create 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_value => 'some value', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-bucket-acl-get.t0000644000175000017500000000267014264646670017473 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_acl_get ]; plan tests => 5; expect_client_bucket_acl_get 'get bucket acl' => ( with_bucket => 'some-bucket', with_response_fixture ('response::acl'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_data => fixture ('response::acl')->{content}, ); expect_client_bucket_acl_get 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, throws => qr/^AccessDenied: Access denied error message/, ); expect_client_bucket_acl_get 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, throws => qr/^NoSuchBucket: No such bucket error message/, ); expect_client_bucket_acl_get 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, throws => qr/^400: Bad Request/, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/query-string-authentication-uri.t0000644000175000017500000000414214264646670021707 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-common.pl" } use Test::MockTime ( qw[ set_fixed_time ], ); plan tests => 4; use Shared::Examples::Net::Amazon::S3 ( qw[ s3_api_with_signature_4 ], qw[ s3_api_with_signature_2 ], qw[ expect_net_amazon_s3_feature ], ); set_fixed_time '2011-09-09T23:36:00Z'; expect_net_amazon_s3_feature "Signature V4 query_string_authentication_uri" => ( feature => 'signed_uri', with_s3 => s3_api_with_signature_4, with_bucket => 'some-bucket', with_key => 'some/key', with_expire_at => time + 123_000, with_region => 'eu-west-1', expect_uri => 'https://some-bucket.s3-eu-west-1.amazonaws.com/some/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIDEXAMPLE%2F20110909%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20110909T233600Z&X-Amz-Expires=123000&X-Amz-SignedHeaders=host&X-Amz-Signature=93da6eea1ab776752fbde0d235f04e1513207a88a3cf1ff45fe4ad05505e45a1', ); expect_net_amazon_s3_feature "Signature V4 query_string_authentication_uri" => ( feature => 'signed_uri', with_s3 => s3_api_with_signature_4, with_bucket => 'some-bucket', with_key => 'some/key', with_expire_at => time + 123_000, with_region => 'eu-west-1', with_method => 'PUT', expect_uri => 'https://some-bucket.s3-eu-west-1.amazonaws.com/some/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIDEXAMPLE%2F20110909%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20110909T233600Z&X-Amz-Expires=123000&X-Amz-SignedHeaders=host&X-Amz-Signature=f21f29a595aefde844acbdf526e2c17887738a61464f381541c9dceb7310eed8', ); expect_net_amazon_s3_feature "Signature V2 query_string_authentication_uri" => ( feature => 'signed_uri', with_s3 => s3_api_with_signature_2, with_bucket => 'some-bucket', with_key => 'some/key', with_expire_at => time + 123_000, with_region => 'eu-west-1', expect_uri => 'https://some-bucket.s3.amazonaws.com/some/key?AWSAccessKeyId=AKIDEXAMPLE&Expires=1315734360&Signature=YtOFhJwsOcNKz5xW7dF6TlrqZT0%3D', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-bucket-delete.t0000644000175000017500000000076114264646670020155 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'delete bucket' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Delete::Request', with_bucket => 'some-bucket', expect_request_method => 'DELETE', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; Net-Amazon-S3-0.991/t/s3-request-object-tags-delete.t0000644000175000017500000000104314264646670021074 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-request.pl" } plan tests => 2; behaves_like_net_amazon_s3_request 'delete object tags' => ( request_class => 'Net::Amazon::S3::Operation::Object::Tags::Delete::Request', with_bucket => 'some-bucket', with_key => 'some-key', expect_request_method => 'DELETE', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some-key?tagging', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; Net-Amazon-S3-0.991/t/s3-operation-object-tags-add.t0000644000175000017500000000232714264646670020700 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } plan tests => 7; expect_operation_object_tags_set ( 'API / legacy' => \& api_object_tags_set_legacy, 'API / named' => \& api_object_tags_set_named, 'Client' => \& client_object_tags_set, ); had_no_warnings; done_testing; sub api_object_tags_set_legacy { my (%args) = @_; build_default_api_bucket (%args) ->add_tags (\ %args) ; } sub api_object_tags_set_named { my (%args) = @_; build_default_api_bucket (%args) ->add_tags (%args) ; } sub client_object_tags_set { my (%args) = @_; build_default_client_object (%args) ->add_tags (%args) ; } sub expect_operation_object_tags_set { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Tags::Add', plan => { "set tags on object" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', tags => { foo => 'bar' }, ], }, "set tags on object version" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', version_id => 'foo', tags => { foo => 'bar' }, ], }, } } Net-Amazon-S3-0.991/t/issue-39-content-length-0.t0000644000175000017500000000103114264646670020063 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_acl_set ]; plan tests => 2; expect_api_bucket_acl_set 'request without content should set content-length => 0' => ( with_bucket => 'some-bucket', with_acl_short => 'private', with_response_fixture ('response::acl'), expect_request_headers => { content_length => 0, }, expect_data => bool (1), ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-bucket-location.t0000644000175000017500000000103214264646670020513 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'get bucket location constraint' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Location::Request', with_bucket => 'some-bucket', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?location', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-object-restore.t0000644000175000017500000000137614264646670020372 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-s3-request.pl" } plan tests => 2; behaves_like_net_amazon_s3_request 'restore object' => ( request_class => 'Net::Amazon::S3::Operation::Object::Restore::Request', with_bucket => 'some-bucket', with_key => 'some-key', with_days => 21, with_tier => 'Standard', expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some-key?restore', expect_request_content => < 21 Standard EOXML ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/signature-v4-with-security-token.t0000644000175000017500000000142514264646670021711 0ustar branobrano use strict; use warnings; use Test::More tests => 2; use Test::Deep; use Test::Warnings qw[ :no_end_test had_no_warnings ]; use Shared::Examples::Net::Amazon::S3::API ( qw[ expect_api_bucket_create ], ); use Shared::Examples::Net::Amazon::S3 ( qw[ s3_api_with_signature_4 ], ); expect_api_bucket_create 'create bucket using Signature 4 and session token' => ( with_s3 => s3_api_with_signature_4 (aws_session_token => 'security-token'), with_bucket => 'some-bucket', with_region => 'us-east-1', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_request_headers => { 'x-amz-security-token' => 'security-token' }, expect_data => ignore, ); had_no_warnings; Net-Amazon-S3-0.991/t/s3-response-object-upload-create.t0000644000175000017500000000102414264646670021570 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-s3-response.pl" } plan tests => 2; behaves_like_s3_response 'list all my buckets with displayname' => ( response_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Response', with_response_fixture ('response::create_multipart_upload_with_success'), expect_success => 1, expect_error => 0, expect_response => methods ( upload_id => 'new-upload-id', ), ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-upload-abort.t0000644000175000017500000000173514264646670021607 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_upload_abort ( 'Client / named arguments' => \& client_object_upload_abort_named_arguments, 'Client / configuration hash' => \& client_object_upload_abort_configuration_hash, ); had_no_warnings; done_testing; sub client_object_upload_abort_named_arguments { my (%args) = @_; build_default_client_object (%args) ->abort_multipart_upload (%args) ; } sub client_object_upload_abort_configuration_hash { my (%args) = @_; build_default_client_object (%args) ->abort_multipart_upload (\ %args) ; } sub expect_operation_object_upload_abort { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Upload::Abort', plan => { "abort upload" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', upload_id => 42, ], }, } } Net-Amazon-S3-0.991/t/client-bucket-acl-set.t0000644000175000017500000000666114264646670017513 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_acl_set ]; plan tests => 9; expect_client_bucket_acl_set 'set bucket acl using deprecated acl_short' => ( with_bucket => 'some-bucket', with_acl_short => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_client_bucket_acl_set 'set bucket acl using canned acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_client_bucket_acl_set 'set bucket acl using canned acl coercion' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_client_bucket_acl_set 'set bucket acl using explicit acl' => ( with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => '', expect_request_headers => { x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, expect_data => bool (1), ); expect_client_bucket_acl_set 'set bucket acl using XML content' => ( with_bucket => 'some-bucket', with_acl_xml => 'PASSTHROUGH', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_request_content => 'PASSTHROUGH', expect_request_headers => { x_amz_acl => undef, }, expect_data => bool (1), ); expect_client_bucket_acl_set 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, throws => qr/^AccessDenied: Access denied error message/, ); expect_client_bucket_acl_set 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, throws => qr/^NoSuchBucket: No such bucket error message/, ); expect_client_bucket_acl_set 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_acl => 'private', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?acl' }, throws => qr/^400: Bad Request/, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/acl-set.t0000644000175000017500000000360614264646670014760 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } subtest "Canned ACL" => sub { use Net::Amazon::S3::ACL::Canned; my %plan = ( AUTHENTICATED_READ => 'authenticated-read', PRIVATE => 'private', AWS_EXEC_READ => 'aws-exec-read', BUCKET_OWNER_FULL_CONTROL => 'bucket-owner-full-control', BUCKET_OWNER_READ => 'bucket-owner-read', LOG_DELIVERY_WRITE => 'log-delivery-write', PUBLIC_READ => 'public-read', PUBLIC_READ_WRITE => 'public-read-write', ); plan tests => 8 * 2; for my $key (sort keys %plan) { cmp_deeply "Canned ACL builder $key should return instance of Net::Amazon::S3::ACL::Canned" => ( got => Net::Amazon::S3::ACL::Canned->$key, expect => obj_isa ('Net::Amazon::S3::ACL::Canned'), ); cmp_deeply "Canned ACL builder $key should provide HTTP headers" => ( got => { Net::Amazon::S3::ACL::Canned->$key->build_headers }, expect => { 'x-amz-acl' => $plan{$key} }, ); } done_testing; }; subtest "Explicit ACL" => sub { use Net::Amazon::S3::ACL::Set; my $acl = Net::Amazon::S3::ACL::Set->new ->grant_full_control (id => 123) ->grant_read (id => 234, Net::Amazon::S3::ACL::Grantee::Group->ALL_USERS) ->grant_write (email => 'foo@bar.baz', Net::Amazon::S3::ACL::Grantee::Group->LOG_DELIVERY) ->grant_write (id => 345, id => 456), ; cmp_deeply "ACL set should format as HTTP headers", got => { $acl->build_headers }, expect => { 'x-amz-grant-full-control' => q[id="123"], 'x-amz-grant-read' => q[id="234", uri="http://acs.amazonaws.com/groups/global/AllUsers"], 'x-amz-grant-write' => q[emailAddress="foo@bar.baz", uri="http://acs.amazonaws.com/groups/s3/LogDelivery", id="345", id="456"], }, ; done_testing; }; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-upload-part.t0000644000175000017500000000275614264646670021452 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_upload_part ( 'Client / named arguments' => \& client_object_upload_part_named_arguments, 'Client / configuration hash' => \& client_object_upload_part_configuration_hash, ); had_no_warnings; done_testing; sub client_object_upload_part_named_arguments { my (%args) = @_; build_default_client_object (%args) ->put_part (%args); } sub client_object_upload_part_configuration_hash { my (%args) = @_; build_default_client_object (%args) ->put_part (\ %args); } sub expect_operation_object_upload_part { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Upload::Part', plan => { "upload object part" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', value => 'foo-bar-baz', upload_id => 42, part_number => 1, acl_short => 'private', copy_source => 'source-key', headers => { x_amz_meta_additional => 'additional-header', }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', value => 'foo-bar-baz', upload_id => 42, part_number => 1, acl_short => 'private', copy_source => 'source-key', headers => { x_amz_meta_additional => 'additional-header', 'Content-Length' => 11, }, }, }, } } Net-Amazon-S3-0.991/t/s3-operation-bucket-tags-add.t0000644000175000017500000000173014264646670020704 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_bucket_tags_set ( 'API / legacy' => \& api_bucket_tags_set_legacy, 'API / named' => \& api_bucket_tags_set_named, 'Client' => \& client_bucket_tags_set, ); had_no_warnings; done_testing; sub api_bucket_tags_set_legacy { my (%args) = @_; build_default_api_bucket (%args) ->add_tags (\ %args) ; } sub api_bucket_tags_set_named { my (%args) = @_; build_default_api_bucket (%args) ->add_tags (%args) ; } sub client_bucket_tags_set { my (%args) = @_; build_default_client_bucket (%args) ->add_tags (%args) ; } sub expect_operation_bucket_tags_set { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Bucket::Tags::Add', plan => { "set tags on bucket" => { act_arguments => [ bucket => 'bucket-name', tags => { foo => 'bar' }, ], }, } } Net-Amazon-S3-0.991/t/s3-request-bucket-tags-add.t0000644000175000017500000000122614264646670020374 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-request.pl" } BEGIN { require "$FindBin::Bin/test-helper-tags.pl" } plan tests => 2; behaves_like_net_amazon_s3_request 'add some tags to a bucket' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Tags::Add::Request', with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, expect_request_method => 'PUT', expect_request_path => 'some-bucket/?tagging', expect_request_header => { content_type => 'application/xml', }, expect_request_content => fixture_tags_foo_bar_xml, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/vendor-amazon.t0000644000175000017500000000214114264646670016201 0ustar branobrano#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } use Net::Amazon::S3; use Net::Amazon::S3::Vendor; use Test::LWP::UserAgent; plan tests => 3; my $s3 = Net::Amazon::S3->new ( vendor => Net::Amazon::S3::Vendor::Amazon->new ( default_region => 'eu-west-42', ), aws_access_key_id => 'access-key', aws_secret_access_key => 'secret-key', ); it "should provide vendor data via compatible delegations", got => $s3, expect => methods ( host => 's3.amazonaws.com', secure => bool (1), use_virtual_host => bool (1), authorization_method => 'Net::Amazon::S3::Signature::V4', ), ; my $bucket = $s3->bucket ('foo'); $s3->ua (Test::LWP::UserAgent->new (network_fallback => 0)); $s3->ua->map_response ( sub { $_[0]->method eq 'HEAD' }, HTTP::Response->new (200 => 'OK', ['x-amz-bucket-region' => 'us-east-7']), ); it "should perform HEAD request on bucket to fetch its region", got => $bucket, expect => methods ( bucket => 'foo', region => 'us-east-7', ), ; had_no_warnings; Net-Amazon-S3-0.991/t/client-object-head.t0000644000175000017500000000451314264646670017047 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_head ]; plan tests => 6; expect_client_object_head 'head existing object' => ( -method => 'head', with_bucket => 'some-bucket', with_key => 'some-key', with_response_code => HTTP_OK, with_response_data => '', with_response_headers => { content_length => 10, content_type => 'text/plain', etag => 'some-key-etag', x_amz_metadata_foo => 'foo-1', date => 'Fri, 09 Sep 2011 23:36:00 GMT', }, expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => { ContentLength => 10, ContentType => 'text/plain', ETag => 'some-key-etag', MetadataFoo => 'foo-1', }, ); expect_client_object_head 'S3 error - Access Denied' => ( -method => 'head', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_client_object_head 'S3 error - Bucket Not Found' => ( -method => 'head', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_bucket_not_found, ); expect_client_object_head 'S3 error - Object Not Found' => ( -method => 'head', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_object_not_found, ); expect_client_object_head 'HTTP error - 400 Bad Request' => ( -method => 'head', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-object-upload-complete.t0000644000175000017500000000431714264646670021777 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 4; behaves_like_net_amazon_s3_request 'abort multipart upload with empty parts' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Complete::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_upload_id => '123&456', with_etags => [ ], with_part_numbers => [ ], expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploadId=123%26456', expect_request_headers => { 'Content-Length' => ignore, 'Content-Type' => 'application/xml', }, expect_request_content => <<'EOXML', EOXML ); behaves_like_net_amazon_s3_request 'abort multipart upload with some parts' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Complete::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_upload_id => '123&456', with_etags => [ 'etag01', 'etag02' ], with_part_numbers => [ 1, 2 ], expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploadId=123%26456', expect_request_headers => { 'Content-Length' => ignore, 'Content-Type' => 'application/xml', }, expect_request_content => <<'EOXML', 1 etag01 2 etag02 EOXML ); behaves_like_net_amazon_s3_request 'abort multipart upload with uneven argument arrays' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Complete::Request', with_bucket => 'some-bucket', with_key => 'some/ %/key', with_upload_id => '123&456', with_etags => [ 'etag01', 'etag02' ], with_part_numbers => [ 1, 2, 3 ], throws => re( qr/must have an equally sized list of etags and part numbers/ ), ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-object-upload-create.t0000644000175000017500000000715114264646670021431 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-s3-request.pl" } plan tests => 8; behaves_like_net_amazon_s3_request 'initiate multipart upload' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Request', with_bucket => 'some-bucket', with_key => 'some/key', expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploads', expect_request_headers => { }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'initiate multipart upload with deprecated acl_short' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl_short => 'private', expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploads', expect_request_headers => { 'x-amz-acl' => 'private' }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'initiate multipart upload with canned ACL' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploads', expect_request_headers => { 'x-amz-acl' => 'private' }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'initiate multipart upload with canned ACL coercion' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => 'private', expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploads', expect_request_headers => { 'x-amz-acl' => 'private' }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'initiate multipart upload with explicit ACL' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploads', expect_request_headers => { 'x-amz-grant-read' => 'id="123", id="234"', 'x-amz-grant-write' => 'id="345"', }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'initiate multipart upload with service side encryption' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_encryption => 'AES256', expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?uploads', expect_request_headers => { 'x-amz-server-side-encryption' => 'AES256' }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'initiate multipart upload with headers' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Create::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_headers => { 'x-amz-meta-test' => 99 }, expect_request_method => 'POST', expect_request_path => 'some-bucket/some/key?uploads', expect_request_headers => { 'x-amz-meta-test' => 99 }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-bucket-create.t0000644000175000017500000000317014264646670020463 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_bucket_create ( 'API / legacy' => \& api_bucket_create_legacy, 'API / named arguments' => \& api_bucket_create_named, 'API / trailing named arguments' => \& api_bucket_create_trailing_named, 'API / trailing configuration hash' => \& api_bucket_create_trailing_conf, 'Client' => \& client_bucket_create, ); had_no_warnings; done_testing; sub api_bucket_create_legacy { my (%args) = @_; build_default_api->add_bucket (\ %args); } sub api_bucket_create_named { my (%args) = @_; build_default_api->add_bucket (%args); } sub api_bucket_create_trailing_named { my (%args) = @_; build_default_api->add_bucket (delete $args{bucket}, %args); } sub api_bucket_create_trailing_conf { my (%args) = @_; build_default_api->add_bucket (delete $args{bucket}, \%args); } sub client_bucket_create { my (%args) = @_; build_default_client->create_bucket (name => delete $args{bucket}, %args); } sub expect_operation_bucket_create { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Bucket::Create', plan => { "create bucket with name" => { act_arguments => [ bucket => 'bucket-name', ], }, "create bucket with location constraint" => { act_arguments => [ bucket => 'bucket-name', location_constraint => 'eu-west-1', ], }, "create bucket with acl" => { act_arguments => [ bucket => 'bucket-name', acl_short => 'private', acl => 'public', ], }, } } Net-Amazon-S3-0.991/t/data/0000775000175000017500000000000014264646670014151 5ustar branobranoNet-Amazon-S3-0.991/t/data/s3-operation-object-add.txt0000644000175000017500000000011014264646670021215 0ustar branobranofoo-bar-baz foo-bar-baz foo-bar-baz foo-bar-baz foo-bar-baz foo-bar-baz Net-Amazon-S3-0.991/t/vendor-info.t0000644000175000017500000000406214264646670015653 0ustar branobrano#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } use Net::Amazon::S3; plan tests => 3; subtest "by default it should expect Amazon AWS" => sub { my $s3 = Net::Amazon::S3->new ( aws_access_key_id => 'access-key', aws_secret_access_key => 'secret-key', ); it "should point to Amazon AWS", got => $s3->host, expect => 's3.amazonaws.com', ; it "should use Signature 4 authentication", got => $s3->authorization_method, expect => 'Net::Amazon::S3::Signature::V4', ; it "should use secure communication", got => $s3->secure, expect => bool (1), ; it "should use virtual-host-style addressing model", got => $s3->use_virtual_host, expect => bool (1), ; it "should build vendor class instance", got => $s3->vendor, expect => all ( obj_isa ('Net::Amazon::S3::Vendor::Amazon'), methods ( host => 's3.amazonaws.com', use_virtual_host => bool (1), use_https => bool (1), authorization_method => 'Net::Amazon::S3::Signature::V4', ), ), ; }; subtest "except of Amazon AWS default signature method is still V2" => sub { my $s3 = Net::Amazon::S3->new ( aws_access_key_id => 'access-key', aws_secret_access_key => 'secret-key', host => 'my.service.local', ); it "should point user provided host", got => $s3->host, expect => 'my.service.local', ; it "should use Signature 2 authentication", got => $s3->authorization_method, expect => 'Net::Amazon::S3::Signature::V2', ; it "should use secure communication", got => $s3->secure, expect => bool (1), ; it "should use path-style addressing model", got => $s3->use_virtual_host, expect => bool (0), ; it "should build vendor class instance", got => $s3->vendor, expect => all ( obj_isa ('Net::Amazon::S3::Vendor'), methods ( host => 'my.service.local', use_virtual_host => bool (0), use_https => bool (1), authorization_method => 'Net::Amazon::S3::Signature::V2', ), ), ; }; had_no_warnings; Net-Amazon-S3-0.991/t/s3-operation-object-upload-create.t0000644000175000017500000000571514264646670021745 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_upload_create ( 'Client / named arguments' => \& client_object_upload_create_named_arguments, 'Client / configuration hash' => \& client_object_upload_create_configuration_hash, ); had_no_warnings; done_testing; sub client_object_upload_create_named_arguments { my (%args) = @_; build_default_client_bucket (%args) ->object ( key => delete $args{key}, (exists $args{encryption} ? (encryption => delete $args{encryption}) : ()), (exists $args{object_acl} ? (acl => delete $args{object_acl}) : ()), ) ->initiate_multipart_upload (%args) ; } sub client_object_upload_create_configuration_hash { my (%args) = @_; build_default_client_bucket (%args) ->object ( key => delete $args{key}, (exists $args{encryption} ? (encryption => delete $args{encryption}) : ()), (exists $args{object_acl} ? (acl => delete $args{object_acl}) : ()), ) ->initiate_multipart_upload (\ %args) ; } sub expect_operation_object_upload_create { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Upload::Create', plan => { "create upload with object acl" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', object_acl => 'private', ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', encryption => undef, acl => obj_isa ('Net::Amazon::S3::ACL::Canned'), }, }, "create upload with overloaded acl" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', acl => 'private', ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', encryption => undef, acl => 'private', }, }, "create upload with acl_short" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', acl_short => 'private', ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', encryption => undef, acl => 'private', }, }, "create upload with additional headers" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', headers => { x_amz_meta_additional => 'additional-header' }, ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', encryption => undef, headers => { x_amz_meta_additional => 'additional-header' }, }, }, "create upload with server-side encoding" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', encryption => 'AES256', ], expect_arguments => { bucket => 'bucket-name', key => 'some-key', encryption => 'AES256', }, }, } } Net-Amazon-S3-0.991/t/s3-request-bucket-objects-list.t0000644000175000017500000000406314264646670021314 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 6; behaves_like_net_amazon_s3_request 'list bucket' => ( request_class => 'Net::Amazon::S3::Operation::Objects::List::Request', with_bucket => 'some-bucket', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?max-keys=1000', expect_request_headers => { }, ); behaves_like_net_amazon_s3_request 'list bucket with prefix' => ( request_class => 'Net::Amazon::S3::Operation::Objects::List::Request', with_bucket => 'some-bucket', with_prefix => 'some-prefix', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?max-keys=1000&prefix=some-prefix', expect_request_headers => { }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'list bucket with delimiter' => ( request_class => 'Net::Amazon::S3::Operation::Objects::List::Request', with_bucket => 'some-bucket', with_delimiter => '&', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?delimiter=%26&max-keys=1000', expect_request_headers => { }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'list bucket with max-keys' => ( request_class => 'Net::Amazon::S3::Operation::Objects::List::Request', with_bucket => 'some-bucket', with_max_keys => '200', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?max-keys=200', expect_request_headers => { }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'list bucket with marker' => ( request_class => 'Net::Amazon::S3::Operation::Objects::List::Request', with_bucket => 'some-bucket', with_marker => 'x', expect_request_method => 'GET', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?marker=x&max-keys=1000', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-bucket-delete.t0000644000175000017500000000316414264646670017420 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_delete ]; plan tests => 6; expect_client_bucket_delete 'delete bucket' => ( with_bucket => 'some-bucket', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_data => bool (1), ); expect_client_bucket_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_access_denied, ); expect_client_bucket_delete 'S3 error - Bucket Not Empty' => ( with_bucket => 'some-bucket', with_response_fixture ('error::bucket_not_empty'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_bucket_not_empty, ); expect_client_bucket_delete 's3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_request_content => '', expect_s3_error_bucket_not_found, ); expect_client_bucket_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-restore.t0000644000175000017500000000130114264646670020666 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_restore ( 'Client' => \& client_object_restore, ); had_no_warnings; done_testing; sub client_object_restore { my (%args) = @_; build_default_client_object (%args) ->restore (%args) ; } sub expect_operation_object_restore { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Restore', plan => { "abort restore" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', days => 'args-days', tier => 'args-tier', ], }, } } Net-Amazon-S3-0.991/t/error-handler-x.t0000644000175000017500000000746314264646670016446 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3 qw[ s3_api_with_signature_2 ]; use Net::Amazon::S3::X; use Net::Amazon::S3::Error::Handler::X; use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_create ]; use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_bucket_create ]; it "should build exception for S3 error", got => Net::Amazon::S3::X->build ('AuthorizationHeaderMalformed'), expect => obj_isa ('Net::Amazon::S3::X::AuthorizationHeaderMalformed'), ; it "should build exception for HTTP error", got => Net::Amazon::S3::X->build ('400'), expect => obj_isa ('Net::Amazon::S3::X::400'), ; subtest "S3 API should recognize custom error handler" => sub { my $s3_api = sub { s3_api_with_signature_2 (error_handler_class => 'Net::Amazon::S3::Error::Handler::X'); }; expect_api_bucket_create 'S3 error - Access Denied' => ( with_s3 => s3_api_with_signature_2 (error_handler_class => 'Net::Amazon::S3::Error::Handler::X'), with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), throws => 'Net::Amazon::S3::X::AccessDenied', expect_s3_err => undef, expect_s3_errstr => undef, ); expect_api_bucket_create 'S3 error - Bucket Already Exists' => ( with_s3 => s3_api_with_signature_2 (error_handler_class => 'Net::Amazon::S3::Error::Handler::X'), with_bucket => 'some-bucket', with_response_fixture ('error::bucket_already_exists'), throws => 'Net::Amazon::S3::X::BucketAlreadyExists', expect_s3_err => undef, expect_s3_errstr => undef, ); expect_api_bucket_create 'S3 error - Invalid Bucket Name' => ( with_s3 => s3_api_with_signature_2 (error_handler_class => 'Net::Amazon::S3::Error::Handler::X'), with_bucket => 'some-bucket', with_response_fixture ('error::invalid_bucket_name'), throws => 'Net::Amazon::S3::X::InvalidBucketName', expect_s3_err => undef, expect_s3_errstr => undef, ); expect_api_bucket_create 'HTTP error - 400 Bad Request' => ( with_s3 => $s3_api->(), with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), throws => 'Net::Amazon::S3::X::400', expect_s3_err => undef, expect_s3_errstr => undef, ); }; subtest "S3 Client should recognize custom error handlerclass" => sub { my $s3_client = sub { Net::Amazon::S3::Client->new ( s3 => s3_api_with_signature_2, error_handler_class => 'Net::Amazon::S3::Error::Handler::X', ); }; expect_client_bucket_create 'S3 error - Access Denied' => ( with_client => $s3_client->(), with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), throws => 'Net::Amazon::S3::X::AccessDenied', ); expect_client_bucket_create 'S3 error - Bucket Already Exists' => ( with_client => $s3_client->(), with_bucket => 'some-bucket', with_response_fixture ('error::bucket_already_exists'), throws => 'Net::Amazon::S3::X::BucketAlreadyExists', ); expect_client_bucket_create 'S3 error - Invalid Bucket Name' => ( with_client => $s3_client->(), with_bucket => 'some-bucket', with_response_fixture ('error::invalid_bucket_name'), throws => 'Net::Amazon::S3::X::InvalidBucketName', ); expect_client_bucket_create 'HTTP error - 400 Bad Request' => ( with_client => $s3_client->(), with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), throws => 'Net::Amazon::S3::X::400', ); }; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-object-head.t0000644000175000017500000000467514264646670016353 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } BEGIN { require "$FindBin::Bin/test-helper-s3-api-error-confess.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_head ]; plan tests => 6; expect_api_object_head 'head existing object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_code => HTTP_OK, with_response_data => '', with_response_headers => { content_length => 10, content_type => 'text/plain', etag => 'some-key-etag', x_amz_metadata_foo => 'foo-1', date => 'Fri, 09 Sep 2011 23:36:00 GMT', }, expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => { content_type => 'text/plain', content_length => 10, etag => 'some-key-etag', value => '', date => 'Fri, 09 Sep 2011 23:36:00 GMT', 'x-amz-metadata-foo' => 'foo-1', 'content-type' => 'text/plain', 'content-length' => 10, 'client-date' => ignore, }, ); expect_api_object_head 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_api_object_head 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_bucket_not_found, ); expect_api_object_head 'S3 error - Object Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_object_not_found, ); expect_api_object_head 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-acl-fetch.t0000644000175000017500000000176214264646670021044 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } expect_operation_object_acl_fetch ( 'API / legacy' => \& api_object_acl_fetch_legacy, 'API / config hash' => \& api_object_acl_fetch_config_hash, 'API / named' => \& api_object_acl_fetch_named, ); had_no_warnings; done_testing; sub api_object_acl_fetch_legacy { my (%args) = @_; build_default_api_bucket (%args) ->get_acl ($args{key}) ; } sub api_object_acl_fetch_config_hash { my (%args) = @_; build_default_api_bucket (%args) ->get_acl ( \%args) ; } sub api_object_acl_fetch_named { my (%args) = @_; build_default_api_bucket (%args) ->get_acl (%args) ; } sub expect_operation_object_acl_fetch { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Acl::Fetch', plan => { "fetch object acl" => { act_arguments => [ bucket => 'bucket-name', key => 'key-name', ], }, } } Net-Amazon-S3-0.991/t/s3-response-service-buckets-list.t0000644000175000017500000000253714264646670021660 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-s3-response.pl" } plan tests => 3; behaves_like_s3_response 'list all my buckets with displayname' => ( response_class => 'Net::Amazon::S3::Operation::Buckets::List::Response', with_response_fixture ('response::service_list_buckets_with_owner_displayname'), expect_success => 1, expect_error => 0, expect_data => { owner_id => 'bcaf1ffd86f461ca5fb16fd081034f', owner_displayname => 'webfile', buckets => [{ name => 'quotes', creation_data => '2006-02-03T16:45:09.000Z', }, { name => 'samples', creation_data => '2006-02-03T16:41:58.000Z', }], }, ); behaves_like_s3_response 'list all my buckets without displayname' => ( response_class => 'Net::Amazon::S3::Operation::Buckets::List::Response', with_response_fixture ('response::service_list_buckets_without_owner_displayname'), expect_success => 1, expect_error => 0, expect_data => { owner_id => 'bcaf1ffd86f461ca5fb16fd081034f', owner_displayname => 'webfile', buckets => [{ name => 'quotes', creation_data => '2006-02-03T16:45:09.000Z', }, { name => 'samples', creation_data => '2006-02-03T16:41:58.000Z', }], }, ); had_no_warnings; Net-Amazon-S3-0.991/t/api-service-buckets-list.t0000644000175000017500000000331514264646670020243 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_list_all_my_buckets ]; plan tests => 5; expect_api_list_all_my_buckets 'list all my buckets with displayname' => ( with_response_fixture ('response::service_list_buckets_with_owner_displayname'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_data => { owner_id => 'bcaf1ffd86f461ca5fb16fd081034f', owner_displayname => 'webfile', buckets => [ all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'quotes'), ), all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'samples'), ), ], }, ); expect_api_list_all_my_buckets 'list all my buckets without displayname' => ( with_response_fixture ('response::service_list_buckets_without_owner_displayname'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_data => { owner_id => 'bcaf1ffd86f461ca5fb16fd081034f', owner_displayname => '', buckets => [ all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'quotes'), ), all ( obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'samples'), ), ], }, ); expect_api_list_all_my_buckets 'S3 error - Access Denied' => ( with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_s3_error_access_denied, ); expect_api_list_all_my_buckets 'HTTP error - 400 Bad Request' => ( with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-bucket-tags-delete.t0000644000175000017500000000244514264646670017650 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_tags_delete ]; plan tests => 5; expect_api_bucket_tags_delete 'delete bucket tags' => ( with_bucket => 'some-bucket', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_data => bool (1), ); expect_api_bucket_tags_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_access_denied, ); expect_api_bucket_tags_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_bucket_not_found, ); expect_api_bucket_tags_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-object-exists.t0000644000175000017500000000434714264646670017472 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_head ]; plan tests => 6; expect_client_object_head 'head existing object' => ( -method => 'exists', with_bucket => 'some-bucket', with_key => 'some-key', with_response_code => HTTP_OK, with_response_data => '', with_response_headers => { content_length => 10, content_type => 'text/plain', etag => 'some-key-etag', x_amz_metadata_foo => 'foo-1', date => 'Fri, 09 Sep 2011 23:36:00 GMT', }, expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => bool (1), ); expect_client_object_head 'S3 error - Access Denied' => ( -method => 'exists', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_client_object_head 'S3 error - Bucket Not Found' => ( -method => 'exists', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => bool (0), ); expect_client_object_head 'S3 error - Object Not Found' => ( -method => 'exists', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => bool (0), ); expect_client_object_head 'HTTP error - 400 Bad Request' => ( -method => 'exists', with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { HEAD => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-object-tags-delete.t0000644000175000017500000000227114264646670021410 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } plan tests => 7; expect_operation_object_tags_delete ( 'API / legacy' => \& api_object_tags_delete_legacy, 'API / named' => \& api_object_tags_delete_named, 'Client' => \& client_object_tags_delete, ); had_no_warnings; done_testing; sub api_object_tags_delete_legacy { my (%args) = @_; build_default_api_bucket (%args) ->delete_tags (\ %args) ; } sub api_object_tags_delete_named { my (%args) = @_; build_default_api_bucket (%args) ->delete_tags (%args) ; } sub client_object_tags_delete { my (%args) = @_; build_default_client_object (%args) ->delete_tags (%args) ; } sub expect_operation_object_tags_delete { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Object::Tags::Delete', plan => { "delete tags from object" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', ], }, "delete tags from object version" => { act_arguments => [ bucket => 'bucket-name', key => 'some-key', version_id => 'foo', ], }, } } Net-Amazon-S3-0.991/t/api-object-fetch.t0000644000175000017500000000661114264646670016533 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } BEGIN { require "$FindBin::Bin/test-helper-s3-api-error-confess.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_fetch ]; plan tests => 8; expect_api_object_fetch 'fetch existing object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_code => HTTP_OK, with_response_data => 'some-value', with_response_headers => { content_length => 10, content_type => 'text/plain', etag => 'some-key-etag', x_amz_metadata_foo => 'foo-1', date => 'Fri, 09 Sep 2011 23:36:00 GMT', }, expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_data => { content_type => 'text/plain', content_length => 10, etag => 'some-key-etag', value => 'some-value', date => 'Fri, 09 Sep 2011 23:36:00 GMT', 'x-amz-metadata-foo' => 'foo-1', 'content-type' => 'text/plain', 'content-length' => 10, 'client-date' => ignore, }, ); expect_api_object_fetch 'fetch range of existing object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_range => 'bytes=1024-1034', with_response_code => HTTP_OK, with_response_data => 'some-value', with_response_headers => { content_type => 'text/plain', etag => 'some-key-etag', }, expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_request_headers => { range => 'bytes=1024-1034', }, expect_data => ignore, ); expect_api_object_fetch 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_access_denied, ); expect_api_object_fetch 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_bucket_not_found, ); expect_api_object_fetch 'S3 error - No Such Object' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_key'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_object_not_found, ); expect_api_object_fetch 'S3 error - Invalid Object State (object archived in glacier)' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::invalid_object_state'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_s3_error_invalid_object_state, ); expect_api_object_fetch 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/some-key' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-operation.pl0000644000175000017500000000560714264646670020035 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-common.pl" } use Sub::Override; use Shared::Examples::Net::Amazon::S3 (); use Shared::Examples::Net::Amazon::S3::API (); use Shared::Examples::Net::Amazon::S3::Client (); sub build_default_api { Shared::Examples::Net::Amazon::S3::API->_default_with_api({}); } sub build_default_api_bucket (\%) { my ($args) = @_; build_default_api->bucket (delete $args->{bucket}); } sub build_default_client { Shared::Examples::Net::Amazon::S3::Client->_default_with_api({}); } sub build_default_client_bucket (\%) { my ($args) = @_; build_default_client->bucket (name => delete $args->{bucket}); } sub build_default_client_object (\%) { my ($args) = @_; build_default_client_bucket (%$args)->object (key => delete $args->{key}); } sub expect_operation { my ($title, %plan) = @_; my $guard = Sub::Override->new ( 'Net::Amazon::S3::_perform_operation', sub { my ($self, $operation, %args) = @_; delete $args{error_handler}; my ($ok, $stack); ($ok, $stack) = Test::Deep::cmp_details ($operation, $plan{expect_operation}); ($ok, $stack) = Test::Deep::cmp_details (\%args, $plan{expect_arguments}) if $ok; diag Test::Deep::deep_diag ($stack) unless ok $title, got => $ok; die bless {}, 'expect_operation'; } ); my $lives = eval { $plan{act}->(); 1 }; my $error = $@; $error = undef if Scalar::Util::blessed ($error) && ref ($error) eq 'expect_operation'; if ($lives) { fail $title; diag "_perform_operation() not called"; return; } if ($error) { fail $title; diag "unexpected_error: $@"; return; } return 1; } sub expect_operation_plan { my (%args) = @_; for my $implementation (sort keys %{ $args{implementations} }) { my $act = $args{implementations}{$implementation}; for my $title (sort keys %{ $args{plan} }) { my $plan = $args{plan}{$title}; my @act_arguments = @{ $plan->{act_arguments} || [] }; my $expect_arguments = $plan->{expect_arguments}; $expect_arguments = { @act_arguments } unless $expect_arguments; if (exists $expect_arguments->{bucket}) { my $bucket_name = delete $expect_arguments->{bucket}; $expect_arguments->{bucket} = any ( obj_isa ('Net::Amazon::S3::Bucket') & methods (bucket => $bucket_name), $bucket_name, ); } expect_operation "$implementation / $title" => act => sub { $act->(@act_arguments) }, expect_operation => $args{expect_operation},, expect_arguments => $expect_arguments, ; } } } sub _api_expand_headers { my (%args) = @_; %args = (%args, %{ $args{headers} }); delete $args{headers}; %args; } sub _api_expand_metadata { my (%args) = @_; %args = ( %args, map +( "x_amz_meta_$_" => $args{metadata}{$_} ), keys %{ $args{metadata} } ); delete $args{metadata}; %args; } sub _api_expand_header_arguments { _api_expand_headers _api_expand_metadata @_; } 1; Net-Amazon-S3-0.991/t/vendor-generic.t0000644000175000017500000000204514264646670016333 0ustar branobrano#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } use Net::Amazon::S3; use Net::Amazon::S3::Vendor::Generic; plan tests => 3; my $s3 = Net::Amazon::S3->new ( vendor => Net::Amazon::S3::Vendor::Generic->new ( host => 'my.service.local', use_https => 1, use_virtual_host => 1, authorization_method => 'Net::Amazon::S3::Signature::V4', default_region => 'eu-west-42', ), aws_access_key_id => 'access-key', aws_secret_access_key => 'secret-key', ); it "should provide vendor data via compatible delegations", got => $s3, expect => methods ( host => 'my.service.local', secure => bool (1), use_virtual_host => bool (1), authorization_method => 'Net::Amazon::S3::Signature::V4', ), ; my $bucket = $s3->bucket ('foo'); it "should return provided region as bucket's region", got => $bucket, expect => methods ( bucket => 'foo', region => 'eu-west-42', ), ; had_no_warnings; Net-Amazon-S3-0.991/t/api-bucket-tags-add.t0000644000175000017500000000334114264646670017132 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } BEGIN { require "$FindBin::Bin/test-helper-tags.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_tags_add ]; plan tests => 5; expect_api_bucket_tags_add 'add tags to a bucket' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('response::http_ok_empty'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_request_content => fixture_tags_foo_bar_xml, expect_request_headers => { content_type => 'application/xml', }, expect_data => bool (1), ); expect_api_bucket_tags_add 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_access_denied, ); expect_api_bucket_tags_add 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_s3_error_bucket_not_found, ); expect_api_bucket_tags_add 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_tags => fixture_tags_foo_bar_hashref, with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-s3-api.pl0000644000175000017500000000111214264646670017114 0ustar branobrano use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } BEGIN { require "test-helper-errors.pl" } use HTTP::Status qw[ HTTP_OK ]; use Net::Amazon::S3::Constants; use Net::Amazon::S3::ACL::Canned; use Shared::Examples::Net::Amazon::S3::Client ( qw[ fixture ], qw[ with_response_fixture ], ); use Shared::Examples::Net::Amazon::S3 ( qw[ s3_api_with_signature_2 ], ); sub expect_error { my ($code, $message) = @_; return +( expect_data => bool (0), expect_s3_err => $code, expect_s3_errstr => $message, ); } 1; Net-Amazon-S3-0.991/t/api-object-tags-delete.t0000644000175000017500000000353214264646670017637 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_object_tags_delete ]; plan tests => 6; expect_client_object_tags_delete 'delete tags from an object' => ( with_bucket => 'some-bucket', with_key => 'some-key', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_data => bool (1), ); expect_client_object_tags_delete 'delete tags from an object version' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_version_id => 42, expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging&versionId=42' }, expect_data => bool (1), ); expect_client_object_tags_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_access_denied, ); expect_client_object_tags_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_bucket_not_found, ); expect_client_object_tags_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/api-build-bucket.t0000644000175000017500000000265514264646670016554 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } use Scalar::Util; plan tests => 6; sub build_bucket; sub test_method_bucket; SKIP: { require_ok ('Net::Amazon::S3') or skip "Cannot load module", 2; test_method_bucket "bucket (STRING) should return respective bucket object", build_bucket ('foo'), obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'foo'), ; test_method_bucket "bucket (bucket => STRING) should return respective bucket object", build_bucket (bucket => 'foo'), obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'foo'), ; test_method_bucket "bucket (STRING, region => STRING) should return respective bucket object", build_bucket ('foo', region => 'bar'), obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'foo', region =>'bar'), ; my $bar = build_bucket ('bar'); test_method_bucket "bucket (Instance) should return its argument", scalar build_bucket ($bar), obj_isa ('Net::Amazon::S3::Bucket'), methods (bucket => 'bar'), code (sub { return 1 if Scalar::Util::refaddr ($_[0]) == Scalar::Util::refaddr ($bar); return 0, "Object is has different address" }), ; } had_no_warnings; done_testing; sub build_bucket { my $s3 = bless {}, 'Net::Amazon::S3'; $s3->bucket (@_); } sub test_method_bucket { my ($title, $bucket, @plan) = @_; it $title, got => $bucket, expect => all (@plan); } Net-Amazon-S3-0.991/t/use-client.t0000644000175000017500000000030014264646670015464 0ustar branobrano use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } plan tests => 2; use_ok 'Net::Amazon::S3::Client'; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/01api.t0000644000175000017500000003423214264646670014341 0ustar branobrano#!perl use warnings; use strict; use lib 'lib'; use Digest::MD5::File qw(file_md5_hex); use Test::More; use Test::Deep; use FindBin; my $DEFAULT_TEST_LOCATIONS = 'us-east-1,eu-west-1'; plan skip_all => 'Testing this module for real costs money. Enable it by setting true value to env variable AMAZON_S3_EXPENSIVE_TESTS' unless $ENV{'AMAZON_S3_EXPENSIVE_TESTS'}; plan skip_all => 'Required env variable AWS_ACCESS_KEY_ID not set.' unless $ENV{'AWS_ACCESS_KEY_ID'}; plan skip_all => 'Required env variable AWS_ACCESS_KEY_SECRET not set.' unless $ENV{'AWS_ACCESS_KEY_SECRET'}; diag "AMAZON_S3_TEST_LOCATIONS not set, using default $DEFAULT_TEST_LOCATIONS" unless $ENV{'AMAZON_S3_TEST_LOCATIONS'}; my @locations = split /,/, ($ENV{'AMAZON_S3_TEST_LOCATIONS'} || $DEFAULT_TEST_LOCATIONS); plan tests => 37 * @locations + 1; use_ok('Net::Amazon::S3'); use vars qw/$OWNER_ID $OWNER_DISPLAYNAME/; my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'}; my $aws_secret_access_key = $ENV{'AWS_ACCESS_KEY_SECRET'}; my $s3 = Net::Amazon::S3->new( { aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, retry => 1, } ); # list all buckets that i own my $response = $s3->buckets; $OWNER_ID = $response->{owner_id}; $OWNER_DISPLAYNAME = $response->{owner_displayname}; for my $location ( @locations ) { my $TEST_SUITE_LENGTH = 36; # without last delete ok my $bucket_obj; SKIP: { # create a bucket # make sure it's a valid hostname for EU testing my $bucketname = 'net-amazon-s3-test-' . lc($aws_access_key_id) . '-' . time; # for testing # my $bucket = $s3->bucket($bucketname); $bucket->delete_bucket; exit; $bucket_obj = $s3->add_bucket( { bucket => $bucketname, acl_short => 'public-read', location_constraint => $location } ) or skip $s3->err . ": " . $s3->errstr, $TEST_SUITE_LENGTH; isa_ok $bucket_obj, "Net::Amazon::S3::Bucket"; my $expected_location = $location; $expected_location = 'us-east-1' unless defined $expected_location; $expected_location = 'eu-west-1' if $expected_location eq 'EU'; is( $bucket_obj->get_location_constraint, $expected_location, "bucket created in expected region" ); like_acl_allusers_read($bucket_obj); ok( $bucket_obj->set_acl( { acl_short => 'private' } ), 'make bucket private using query parameters' ); unlike_acl_allusers_read($bucket_obj); # another way to get a bucket object (does no network I/O, # assumes it already exists). Read Net::Amazon::S3::Bucket. $bucket_obj = $s3->bucket($bucketname); isa_ok $bucket_obj, "Net::Amazon::S3::Bucket"; # fetch contents of the bucket # note prefix, marker, max_keys options can be passed in $response = $bucket_obj->list or skip $s3->err . ": " . $s3->errstr, $TEST_SUITE_LENGTH - 6; cmp_deeply $response, superhashof({ bucket => $bucketname, prefix => '', marker => '', max_keys => 1_000, is_truncated => 0, keys => [], }, "list empty bucket"); is( undef, $bucket_obj->get_key("non-existing-key"), "get non existing key" ); my $keyname = 'testing.txt'; { # Create a publicly readable key, then turn it private with a short acl. # This key will persist past the end of the block. my $value = 'T'; $bucket_obj->add_key( $keyname, $value, { content_type => 'text/plain', 'x-amz-meta-colour' => 'orange', acl_short => 'public-read', } ); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname", 200, "can access the publicly readable key" ); like_acl_allusers_read( $bucket_obj, $keyname ); ok( $bucket_obj->set_acl( { key => $keyname, acl_short => 'private' } ), "change key policy of private using acl_short"); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname", 403, "cannot access the private key" ); unlike_acl_allusers_read( $bucket_obj, $keyname ); ok( $bucket_obj->set_acl( { key => $keyname, acl_xml => acl_xml_from_acl_short('public-read') } ), "change key policy to public using acl_xml" ); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname", 200, "can access the publicly readable key after acl_xml set" ); like_acl_allusers_read( $bucket_obj, $keyname ); ok( $bucket_obj->set_acl( { key => $keyname, acl_xml => acl_xml_from_acl_short('private') } ), "change key policy to private using acl_xml" ); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname", 403, "cannot access the private key after acl_xml set" ); unlike_acl_allusers_read( $bucket_obj, $keyname ); } { # Create a private key, then make it publicly readable with a short # acl. Delete it at the end so we're back to having a single key in # the bucket. my $keyname2 = 'testing2.txt'; my $value = 'T2'; $bucket_obj->add_key( $keyname2, $value, { content_type => 'text/plain', 'x-amz-meta-colour' => 'blue', acl_short => 'private', } ); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname2", 403, "cannot access the private key" ); unlike_acl_allusers_read( $bucket_obj, $keyname2 ); ok( $bucket_obj->set_acl( { key => $keyname2, acl_short => 'public-read' } ), "change private key to public" ); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname2", 200, "can access the publicly readable key" ); like_acl_allusers_read( $bucket_obj, $keyname2 ); $bucket_obj->delete_key($keyname2); } { # Copy a key, keeping metadata my $keyname2 = 'testing2.txt'; $bucket_obj->copy_key( $keyname2, "/$bucketname/$keyname" ); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname2", 403, "cannot access the private key" ); # Overwrite, making publically readable $bucket_obj->copy_key( $keyname2, "/$bucketname/$keyname", { acl_short => 'public-read' } ); sleep 1; is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname2", 200, "can access the publicly readable key" ); # Now copy it over itself, making it private $bucket_obj->edit_metadata( $keyname2, { short_acl => 'private' } ); is_request_response_code( "http://$bucketname.s3.amazonaws.com/$keyname2", 403, "cannot access the private key" ); # Get rid of it, bringing us back to only one key $bucket_obj->delete_key($keyname2); # Expect a nonexistent key copy to fail ok( !$bucket_obj->copy_key( "newkey", "/$bucketname/$keyname2" ), "Copying a nonexistent key fails" ); } # list keys in the bucket $response = $bucket_obj->list or skip $s3->err . ": " . $s3->errstr, $TEST_SUITE_LENGTH - 28; cmp_deeply $response, superhashof({ bucket => $bucketname, prefix => '', marker => '', max_keys => 1_000, is_truncated => 0, keys => [ superhashof({ key => $keyname, # the etag is the MD5 of the value etag => 'b9ece18c950afbfa6b0fdbfa4ff731d3', size => 1, owner_id => $OWNER_ID, owner_displayname => $OWNER_DISPLAYNAME, })], }), "list bucket with 1 key"; # You can't delete a bucket with things in it ok( !$bucket_obj->delete_bucket(), "cannot delete non-empty bucket" ); $bucket_obj->delete_key($keyname); # now play with the file methods my $README_FILE = "$FindBin::Bin/../README.md"; my $README_DEST = "$FindBin::Bin/README.md"; my $readme_md5 = file_md5_hex($README_FILE); my $readme_size = -s $README_FILE; $keyname .= "2"; $bucket_obj->add_key_filename( $keyname, $README_FILE, { content_type => 'text/plain', 'x-amz-meta-colour' => 'orangy', } ); $response = $bucket_obj->get_key($keyname); cmp_deeply $response, superhashof({ content_type => 'text/plain', value => re( qr/Amazon Digital Services/ ), etag => $readme_md5, 'x-amz-meta-colour' => 'orangy', content_length => $readme_size, }), "fetch key-from-file into memory"; unlink($README_DEST); $response = $bucket_obj->get_key_filename( $keyname, undef, $README_DEST ); cmp_deeply $response, superhashof({ content_type => 'text/plain', value => '', etag => $readme_md5, 'x-amz-meta-colour' => 'orangy', content_length => $readme_size, }), "fetch key-from-file into file"; is( file_md5_hex($README_DEST), $readme_md5, "downloaded key-from-file checksum match" ); $bucket_obj->delete_key($keyname); # try empty files $keyname .= "3"; $bucket_obj->add_key( $keyname, '' ); $response = $bucket_obj->get_key($keyname); cmp_deeply $response, superhashof({ value => '', etag => 'd41d8cd98f00b204e9800998ecf8427e', content_type => 'binary/octet-stream', content_length => 0, }), "fetch empty key into memory"; $bucket_obj->delete_key($keyname); # how about using add_key_filename? my $EMPTY_FILE = "$FindBin::Bin/empty"; $keyname .= '4'; open FILE, ">", $EMPTY_FILE or skip "Can't open $EMPTY_FILE for write: $!", $TEST_SUITE_LENGTH - 34; close FILE; $bucket_obj->add_key_filename( $keyname, $EMPTY_FILE ); $response = $bucket_obj->get_key($keyname); cmp_deeply $response, superhashof({ value => '', etag => 'd41d8cd98f00b204e9800998ecf8427e', content_type => 'binary/octet-stream', content_length => 0, }), "fetch empty-key-from-file into memory"; $bucket_obj->delete_key($keyname); unlink $EMPTY_FILE; # fetch contents of the bucket # note prefix, marker, max_keys options can be passed in $response = $bucket_obj->list or skip $s3->err . ": " . $s3->errstr, $TEST_SUITE_LENGTH - 35; cmp_deeply $response, superhashof({ bucket => $bucketname, prefix => '', marker => '', max_keys => 1_000, is_truncated => 0, keys => [], }), "list bucket with all keys deleted"; } ok( $bucket_obj->delete_bucket() ); } # see more docs in Net::Amazon::S3::Bucket # local test methods sub is_request_response_code { my ( $url, $code, $message ) = @_; my $request = HTTP::Request->new( 'GET', $url ); #warn $request->as_string(); my $response = $s3->ua->request($request); is( $response->code, $code, $message ); } sub like_acl_allusers_read { my ( $bucketobj, $keyname ) = @_; my $message = acl_allusers_read_message( 'like', @_ ); like( $bucketobj->get_acl($keyname), qr(AllUsers.+READ), $message ); } sub unlike_acl_allusers_read { my ( $bucketobj, $keyname ) = @_; my $message = acl_allusers_read_message( 'unlike', @_ ); unlike( $bucketobj->get_acl($keyname), qr(AllUsers.+READ), $message ); } sub acl_allusers_read_message { my ( $like_or_unlike, $bucketobj, $keyname ) = @_; my $message = $like_or_unlike . "_acl_allusers_read: " . $bucketobj->bucket; $message .= " - $keyname" if $keyname; return $message; } sub acl_xml_from_acl_short { my $acl_short = shift || 'private'; my $public_read = ''; if ( $acl_short eq 'public-read' ) { $public_read = qq~ http://acs.amazonaws.com/groups/global/AllUsers READ ~; } return qq~ $OWNER_ID $OWNER_DISPLAYNAME $OWNER_ID $OWNER_DISPLAYNAME FULL_CONTROL $public_read ~; } Net-Amazon-S3-0.991/t/client-service-buckets-list.t0000644000175000017500000000366714264646670020762 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-client.pl" } use Shared::Examples::Net::Amazon::S3::Client qw[ expect_client_list_all_my_buckets ]; plan tests => 5; expect_client_list_all_my_buckets 'list all my buckets with displayname' => ( with_response_fixture ('response::service_list_buckets_with_owner_displayname'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_data => [ all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'quotes'), methods (owner_id => 'bcaf1ffd86f461ca5fb16fd081034f'), methods (owner_display_name => 'webfile'), ), all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'samples'), methods (owner_id => 'bcaf1ffd86f461ca5fb16fd081034f'), methods (owner_display_name => 'webfile'), ), ], ); expect_client_list_all_my_buckets 'list all my buckets without displayname' => ( with_response_fixture ('response::service_list_buckets_without_owner_displayname'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_data => [ all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'quotes'), methods (owner_id => 'bcaf1ffd86f461ca5fb16fd081034f'), methods (owner_display_name => ''), ), all ( obj_isa ('Net::Amazon::S3::Client::Bucket'), methods (name => 'samples'), methods (owner_id => 'bcaf1ffd86f461ca5fb16fd081034f'), methods (owner_display_name => ''), ), ], ); expect_client_list_all_my_buckets 'S3 error - Access Denied' => ( with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_s3_error_access_denied, ); expect_client_list_all_my_buckets 'HTTP error - 400 Bad Request' => ( with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://s3.amazonaws.com/' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-bucket-tags-delete.t0000644000175000017500000000077314264646670021114 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-request.pl" } plan tests => 2; behaves_like_net_amazon_s3_request 'delete bucket tags' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Tags::Delete::Request', with_bucket => 'some-bucket', expect_request_method => 'DELETE', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?tagging', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; Net-Amazon-S3-0.991/t/test-helper-s3-response.pl0000644000175000017500000000776214264646670020222 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-common.pl' } use Shared::Examples::Net::Amazon::S3 qw[ with_response_fixture ]; use HTTP::Response; use HTTP::Status; sub expect_response_class { my ($response_class) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return use_ok $response_class; } sub expect_response_instance { my (%params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; my $class = delete $params{response_class}; my $content = delete $params{with_response_data}; my $code = delete $params{with_response_code}; my $message = delete $params{with_response_message} // HTTP::Status::status_message ($code); my $header = delete $params{with_response_header} // {}; for (grep m/^with_response_header_/, keys %params) { m/^with_response_header_(.*)/; $header->{$1} //= $params{$_}; } $header->{content_length} //= length $content if $content && length $content; my $http_response = HTTP::Response->new ( $code, $message, [ %$header ], $content ); $http_response->request ($params{with_origin_request}) if $params{with_origin_request}; return $class->new ( http_response => $http_response ); } sub behaves_like_s3_response { my ($title, %params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; subtest $title => sub { plan tests => 1 + scalar grep exists $params{$_}, qw[ expect_success ], qw[ expect_error ], qw[ expect_redirect ], qw[ expect_internal_response ], qw[ expect_xml_content ], qw[ expect_response ], qw[ expect_response_data ], qw[ expect_error_code ], qw[ expect_error_message ], qw[ expect_error_resource ], qw[ expect_error_request_id ], ; expect_response_class $params{response_class}; my $response = expect_response_instance %params; cmp_deeply "expect response is success" => ( if => exists $params{expect_success}, got => sub { scalar $response->is_success }, expect => sub { bool ($params{expect_success}) }, ); cmp_deeply "expect response is error" => ( if => exists $params{expect_error}, got => sub { scalar $response->is_error }, expect => sub { bool ($params{expect_error}) }, ); cmp_deeply "expect response is redirect" => ( if => exists $params{expect_redirect}, got => sub { scalar $response->is_redirect }, expect => sub { bool ($params{expect_redirect}) }, ); cmp_deeply "expect internal response" => ( if => exists $params{expect_internal_response}, got => sub { scalar $response->is_internal_response }, expect => sub { bool ($params{expect_internal_response}) }, ); cmp_deeply "expect response xml content" => ( if => exists $params{expect_xml_content}, got => sub { scalar $response->is_xml_content }, expect => sub { bool ($params{expect_xml_content}) }, ); cmp_deeply "expect response error code" => ( if => exists $params{expect_error_code}, got => sub { $response->error_code }, expect => $params{expect_error_code}, ); cmp_deeply "expect response error message" => ( if => exists $params{expect_error_message}, got => sub { $response->error_message }, expect => $params{expect_error_message}, ); cmp_deeply "expect response error resource" => ( if => exists $params{expect_error_resource}, got => sub { $response->error_resource }, expect => $params{expect_error_resource}, ); cmp_deeply "expect response error request id" => ( if => exists $params{expect_error_request_id}, got => sub { $response->error_request_id }, expect => $params{expect_error_request_id}, ); cmp_deeply "expect response data" => ( if => exists $params{expect_response_data}, got => sub { $response->data }, expect => sub { bool ($params{expect_response_data}) }, ); cmp_deeply "expect response" => ( if => exists $params{expect_response}, got => $response, expect => $params{expect_response}, ); done_testing; }; } 1; Net-Amazon-S3-0.991/t/utils-parse-arguments.t0000644000175000017500000000675214264646670017710 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-common.pl" } use Scalar::Util; use Net::Amazon::S3; plan tests => 5; sub act; subtest "parse_arguments() " => sub { local *act = sub { Net::Amazon::S3::Utils->parse_arguments (@_) }; cmp_deeply "_parse_arguments() should recognize required positional arguments" => ( got => { act (['bucket-arg', 'key-arg'], [qw[ bucket key ]]) }, expect => { bucket => 'bucket-arg', key => 'key-arg' }, ); cmp_deeply "_parse_arguments() should recognize required positional argument specified as named argument" => ( got => { act (['key-arg', bucket => 'bucket-arg'], [qw[ bucket key ]]) }, expect => { bucket => 'bucket-arg', key => 'key-arg' }, ); cmp_deeply "_parse_arguments() should recognize required positional argument specified as named arguments" => ( got => { act ([key => 'key-arg', bucket => 'bucket-arg'], [qw[ bucket key ]]) }, expect => { bucket => 'bucket-arg', key => 'key-arg' }, ); cmp_deeply "_parse_arguments() should recognize required positional argument specified via configuration hash" => ( got => { act (['key-arg', { bucket => 'bucket-arg' }], [qw[ bucket key ]]) }, expect => { bucket => 'bucket-arg', key => 'key-arg' }, ); cmp_deeply "_parse_arguments() should recognize required positional arguments specified via configuration hash" => ( got => { act ([{ key => 'key-arg', bucket => 'bucket-arg' }], [qw[ bucket key ]]) }, expect => { bucket => 'bucket-arg', key => 'key-arg' }, ); cmp_deeply "_parse_arguments() should recognize combination of named arguments and configuration hash" => ( got => { act ([ key => 'key-arg', { bucket => 'bucket-arg' }], [qw[ bucket key ]]) }, expect => { bucket => 'bucket-arg', key => 'key-arg' }, ); cmp_deeply "_parse_arguments() should recognize alias of required positional argument" => ( got => { act (['key-arg', { name => 'bucket-arg' }], [qw[ bucket key ]], { name => 'bucket' }) }, expect => { bucket => 'bucket-arg', key => 'key-arg' }, ); }; subtest "parse_arguments_with_bucket()" => sub { local *act = sub { Net::Amazon::S3::Utils->parse_arguments_with_bucket (@_) }; cmp_deeply "should accept bucket as positional argument" => ( got => { act (['bucket-arg', optional => 'optional-arg']) }, expect => { bucket => 'bucket-arg', optional => 'optional-arg' }, ); cmp_deeply "should accept bucket as named argument" => ( got => { act ([bucket => 'bucket-arg', optional => 'optional-arg']) }, expect => { bucket => 'bucket-arg', optional => 'optional-arg' }, ); cmp_deeply "should accept bucket's alias" => ( got => { act ([name => 'bucket-arg', optional => 'optional-arg']) }, expect => { bucket => 'bucket-arg', optional => 'optional-arg' }, ); }; subtest "parse_arguments_with_bucket_and_object()" => sub { local *act = sub { Net::Amazon::S3::Utils->parse_arguments_with_bucket_and_object (@_) }; cmp_deeply "should accept bucket and key as positional arguments" => ( got => { act (['bucket-arg', 'key-arg', optional => 'optional-arg']) }, expect => { bucket => 'bucket-arg', key => 'key-arg', optional => 'optional-arg' }, ); }; subtest "parse_arguments_with_object()" => sub { local *act = sub { Net::Amazon::S3::Utils->parse_arguments_with_object (@_) }; cmp_deeply "should accept key as positional arguments" => ( got => { act (['key-arg', optional => 'optional-arg']) }, expect => { key => 'key-arg', optional => 'optional-arg' }, ); }; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-operation-objects-delete.t0000644000175000017500000000153714264646670020643 0ustar branobrano#!perl use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-operation.pl" } # plan tests => 4; expect_operation_objects_delete ( 'API' => \& api_objects_delete, 'Client' => \& client_objects_delete, ); had_no_warnings; done_testing; sub api_objects_delete { my (%args) = @_; build_default_api_bucket (%args) ->delete_multi_object (@{ $args{keys} }) ; } sub client_objects_delete { my (%args) = @_; build_default_client_bucket (%args) ->delete_multi_object (@{ $args{keys} }) ; } sub expect_operation_objects_delete { expect_operation_plan implementations => +{ @_ }, expect_operation => 'Net::Amazon::S3::Operation::Objects::Delete', plan => { "delete multiple objects" => { act_arguments => [ bucket => 'bucket-name', keys => [ 'key-1', 'key-2', 'key-3' ], ], }, } } Net-Amazon-S3-0.991/t/api-bucket-acl-get.t0000644000175000017500000000257714264646670016774 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } BEGIN { require "$FindBin::Bin/test-helper-s3-api-error-confess.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_acl_get ]; plan tests => 5; expect_api_bucket_acl_get 'get bucket acl' => ( with_bucket => 'some-bucket', with_response_fixture ('response::acl'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_data => fixture ('response::acl')->{content}, ); expect_api_bucket_acl_get 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_s3_error_access_denied, ); expect_api_bucket_acl_get 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_s3_error_bucket_not_found, ); expect_api_bucket_acl_get 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?acl' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-object-delete.t0000644000175000017500000000105014264646670020136 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'delete object' => ( request_class => 'Net::Amazon::S3::Operation::Object::Delete::Request', with_bucket => 'some-bucket', with_key => 'some/key', expect_request_method => 'DELETE', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-common.pl0000644000175000017500000000306714264646670017323 0ustar branobrano use strict; use warnings; use utf8; use Test::Deep v0.111 qw[ !cmp_deeply !bool !code ]; use Test::More import => [qw[ !ok !is !is_deeply ]]; use Test::Warnings qw[ :no_end_test had_no_warnings ]; use Safe::Isa qw[]; use Ref::Util qw[]; sub __expand_lazy_param { my ($param) = @_; return $param->() if Ref::Util::is_plain_coderef ($param); return $param; } sub ok { my ($title, %params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return if exists $params{if} && ! __expand_lazy_param ($params{if}); Test::More::ok __expand_lazy_param ($params{got}), __expand_lazy_param ($title), ; } sub it { my ($title, %params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return if exists $params{if} && ! __expand_lazy_param ($params{if}); Test::Deep::cmp_deeply __expand_lazy_param ($params{got}), __expand_lazy_param ($params{expect}), __expand_lazy_param ($title), ; } sub is { my ($title, %params) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; return if exists $params{if} && ! __expand_lazy_param ($params{if}); Test::More::is __expand_lazy_param ($params{got}), __expand_lazy_param ($params{expect}), __expand_lazy_param ($title), ; } sub cmp_deeply { goto \⁢ } sub bool { my ($param) = @_; return $param if $param->$Safe::Isa::_isa ('Test::Deep::Cmp'); return Test::Deep::bool ($param); } sub code (&) { goto \& Test::Deep::code; } sub expect_coderef { return code { return Ref::Util::is_plain_coderef ($_[0]) ? (1) : (0, "Expect CODEREF") }; } 1; Net-Amazon-S3-0.991/t/client-object-tags-delete.t0000644000175000017500000000350214264646670020341 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_tags_delete ]; plan tests => 6; expect_api_object_tags_delete 'delete tags from an object' => ( with_bucket => 'some-bucket', with_key => 'some-key', expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_data => bool (1), ); expect_api_object_tags_delete 'delete tags from an object version' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_version_id => 42, expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging&versionId=42' }, expect_data => bool (1), ); expect_api_object_tags_delete 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::access_denied'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_access_denied, ); expect_api_object_tags_delete 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::no_such_bucket'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_s3_error_bucket_not_found, ); expect_api_object_tags_delete 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_response_fixture ('error::http_bad_request'), expect_request => { DELETE => 'https://some-bucket.s3.amazonaws.com/some-key?tagging' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-s3-client.pl0000644000175000017500000000070314264646670017626 0ustar branobrano use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-common.pl" } BEGIN { require "test-helper-errors.pl" } use HTTP::Status qw[ HTTP_OK ]; use Shared::Examples::Net::Amazon::S3::Client ( qw[ fixture ], qw[ with_response_fixture ], ); use Shared::Examples::Net::Amazon::S3 ( qw[ s3_api_with_signature_2 ], ); sub expect_error { my ($code, $message) = @_; +( throws => qr/^${code}: $message/ ); } 1; Net-Amazon-S3-0.991/t/api-construct.t0000644000175000017500000000136614264646670016224 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-common.pl' } use Net::Amazon::S3; it "can construct API instance with list arguments", got => Net::Amazon::S3->new ( aws_access_key_id => 'foo', aws_secret_access_key => 'bar', ), expect => all ( obj_isa ('Net::Amazon::S3'), methods (aws_access_key_id => 'foo'), methods (aws_secret_access_key => 'bar'), ), ; it "can construct API instance with hashref arguments", got => Net::Amazon::S3->new ({ aws_access_key_id => 'foo', aws_secret_access_key => 'bar', }), expect => all ( obj_isa ('Net::Amazon::S3'), methods (aws_access_key_id => 'foo'), methods (aws_secret_access_key => 'bar'), ), ; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-service-buckets-list.t0000644000175000017500000000072014264646670021502 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'list all buckets' => ( request_class => 'Net::Amazon::S3::Operation::Buckets::List::Request', expect_request_method => 'GET', expect_request_uri => 'https://s3.amazonaws.com/', expect_request_headers => { }, expect_request_content => '', ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-bucket-objects-delete.t0000644000175000017500000000323214264646670021600 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 4; behaves_like_net_amazon_s3_request 'delete multi object with empty keys' => ( request_class => 'Net::Amazon::S3::Operation::Objects::Delete::Request', with_bucket => 'some-bucket', with_keys => [], expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?delete', expect_request_headers => superhashof ({ 'Content-Type' => 'application/xml', }), expect_request_content => <<'EOXML', true EOXML ); behaves_like_net_amazon_s3_request 'delete multi object with some keys' => ( request_class => 'Net::Amazon::S3::Operation::Objects::Delete::Request', with_bucket => 'some-bucket', with_keys => [ 'some/key', '' ], expect_request_method => 'POST', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/?delete', expect_request_headers => superhashof ({ 'Content-Type' => 'application/xml', }), expect_request_content => <<'EOXML', true some/key <another/key> EOXML ); behaves_like_net_amazon_s3_request 'delete multi object with more than 1_000 keys' => ( request_class => 'Net::Amazon::S3::Operation::Objects::Delete::Request', with_bucket => 'some-bucket', with_keys => [ 0 .. 1_000 ], throws => re( qr/The maximum number of keys is 1000/ ), ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/client-construct.t0000644000175000017500000000337314264646670016731 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-common.pl' } use Net::Amazon::S3; it "can construct Client instance with list arguments", got => Net::Amazon::S3::Client->new ( s3 => Net::Amazon::S3->new ( aws_access_key_id => 'foo', aws_secret_access_key => 'bar', ), ), expect => all ( obj_isa ('Net::Amazon::S3::Client'), methods (s3 => all ( obj_isa ('Net::Amazon::S3'), methods (aws_access_key_id => 'foo'), methods (aws_secret_access_key => 'bar'), )), ), ; it "can construct Client instance with hashref arguments", got => Net::Amazon::S3::Client->new ({ s3 => Net::Amazon::S3->new ( aws_access_key_id => 'foo', aws_secret_access_key => 'bar', ), }), expect => all ( obj_isa ('Net::Amazon::S3::Client'), methods (s3 => all ( obj_isa ('Net::Amazon::S3'), methods (aws_access_key_id => 'foo'), methods (aws_secret_access_key => 'bar'), )), ), ; it "can construct Client instance with Net::Amazon::S3's list arguments", got => Net::Amazon::S3::Client->new ( aws_access_key_id => 'foo', aws_secret_access_key => 'bar', ), expect => all ( obj_isa ('Net::Amazon::S3::Client'), methods (s3 => all ( obj_isa ('Net::Amazon::S3'), methods (aws_access_key_id => 'foo'), methods (aws_secret_access_key => 'bar'), )), ), ; it "can construct Client instance with Net::Amazon::S3's hashref arguments", got => Net::Amazon::S3::Client->new ({ aws_access_key_id => 'foo', aws_secret_access_key => 'bar', }), expect => all ( obj_isa ('Net::Amazon::S3::Client'), methods (s3 => all ( obj_isa ('Net::Amazon::S3'), methods (aws_access_key_id => 'foo'), methods (aws_secret_access_key => 'bar'), )), ), ; had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-object-upload-part.t0000644000175000017500000000121114264646670021123 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 2; behaves_like_net_amazon_s3_request 'put object' => ( request_class => 'Net::Amazon::S3::Operation::Object::Upload::Part::Request', with_bucket => 'some-bucket', with_key => 'some/key', with_value => 'foo', with_upload_id => '123', with_part_number => '1', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/some/key?partNumber=1&uploadId=123', expect_request_headers => { }, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/s3-request-bucket-create.t0000644000175000017500000001213414264646670020153 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require 'test-helper-s3-request.pl' } plan tests => 11; sub h ($) { +{ 'Content-Length' => ignore, 'Content-Type' => ignore, %{ $_[0] } }; } behaves_like_net_amazon_s3_request 'create bucket' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'create bucket with deprecated acl_short' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl_short => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-acl' => 'private' }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'create bucket with canned acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-acl' => 'private' }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'create bucket with canned acl coercion' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl => 'private', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-acl' => 'private' }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'create bucket with exact acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-grant-read' => 'id="123", id="234"', 'x-amz-grant-write' => 'id="345"', }, expect_request_content => '', ); behaves_like_net_amazon_s3_request 'create bucket in region' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_location_constraint => 'ca-central-1', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { }, expect_request_content => fixture ('request::bucket_create_ca_central_1')->{content}, ); behaves_like_net_amazon_s3_request 'create bucket in region with deprecated acl_short' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl_short => 'private', with_location_constraint => 'ca-central-1', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-acl' => 'private' }, expect_request_content => fixture ('request::bucket_create_ca_central_1')->{content}, ); behaves_like_net_amazon_s3_request 'create bucket in region with canned acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, with_location_constraint => 'ca-central-1', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-acl' => 'private' }, expect_request_content => fixture ('request::bucket_create_ca_central_1')->{content}, ); behaves_like_net_amazon_s3_request 'create bucket in region with canned acl coercion' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl_short => 'private', with_location_constraint => 'ca-central-1', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-acl' => 'private' }, expect_request_content => fixture ('request::bucket_create_ca_central_1')->{content}, ); behaves_like_net_amazon_s3_request 'create bucket in region with exact acl' => ( request_class => 'Net::Amazon::S3::Operation::Bucket::Create::Request', with_bucket => 'some-bucket', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , with_location_constraint => 'ca-central-1', expect_request_method => 'PUT', expect_request_uri => 'https://some-bucket.s3.amazonaws.com/', expect_request_headers => h { 'x-amz-grant-read' => 'id="123", id="234"', 'x-amz-grant-write' => 'id="345"', }, expect_request_content => fixture ('request::bucket_create_ca_central_1')->{content}, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/response.t0000644000175000017500000001032414264646670015261 0ustar branobrano#!perl use strict; use warnings; use FindBin; use lib $FindBin::Bin; BEGIN { require "test-helper-s3-response.pl" } plan tests => 8; use HTTP::Request; use HTTP::Response; use HTTP::Status qw[ status_message ]; use Net::Amazon::S3::Response; sub with_fixture_http_error; sub with_fixture_cant_connect_internal_response; sub with_fixture_common_response_headers; behaves_like_s3_response "S3 error response - NoSuchKey" => ( response_class => 'Net::Amazon::S3::Response', with_response_fixture ('error::no_such_key'), expect_success => 0, expect_error => 1, expect_redirect => 0, expect_internal_response => 0, expect_xml_content => 1, expect_error_code => 'NoSuchKey', expect_error_message => 'No such key error message', expect_error_resource => '/some-resource', expect_error_request_id => '4442587FB7D0A2F9', ); behaves_like_s3_response "S3 error response - AccessDenied" => ( response_class => 'Net::Amazon::S3::Response', with_response_fixture ('error::access_denied'), expect_error => 1, expect_success => 0, expect_error_code => 'AccessDenied', expect_error_message => 'Access denied error message', ); behaves_like_s3_response "HTTP error - 403 Forbidden" => ( response_class => 'Net::Amazon::S3::Response', with_fixture_http_error, expect_error => 1, expect_success => 0, expect_redirect => 0, expect_xml_content => 0, expect_internal_response => 0, expect_error_code => '403', expect_error_message => 'Forbidden', expect_error_resource => 'https://my-bucket.amazonaws.com/some-resource', expect_error_request_id => undef, ); behaves_like_s3_response "Internal response - Can't connect" => ( response_class => 'Net::Amazon::S3::Response', with_fixture_cant_connect_internal_response, expect_error => 1, expect_success => 0, expect_redirect => 0, expect_xml_content => 0, expect_internal_response => 1, expect_error_code => '500', expect_error_message => "Can't connect to my.bucket.name.s3.amazonaws.com:443", ); behaves_like_s3_response "S3 response - Common Response Headers" => ( response_class => 'Net::Amazon::S3::Response', with_fixture_common_response_headers, expect_response => all ( methods (etag => "2468"), methods (server => "AmazonS3"), methods (delete_marker => "some-delete-marker"), methods (id_2 => 'some-id-2'), methods (request_id => 'some-request-id'), methods (version_id => 'some-version-id'), ), ); behaves_like_s3_response "S3 response - content type text/xml" => ( response_class => 'Net::Amazon::S3::Response', with_content_type ('text/xml'), expect_response => all ( methods (is_xml_content => bool (1)), ), ); behaves_like_s3_response "S3 response - vendor content type" => ( response_class => 'Net::Amazon::S3::Response', with_content_type ('application/vnd.foo.bar+xml'), expect_response => all ( methods (is_xml_content => bool (1)), ), ); had_no_warnings; done_testing; sub with_fixture_http_error { +( with_response_code => 403, with_origin_request => HTTP::Request->new (GET => 'https://my-bucket.amazonaws.com/some-resource'), ); } sub with_fixture_cant_connect_internal_response { +( with_response_code => 500, with_response_message => "Can't connect to my.bucket.name.s3.amazonaws.com:443", with_response_header_content_type => 'text/plain', with_response_header_client_warning => 'Internal response', ); } sub with_fixture_common_response_headers { +( with_response_code => 403, with_response_header => { server => 'AmazonS3', content_type => 'application/xml', etag => '"2468"', x_amz_delete_marker => 'some-delete-marker', x_amz_id_2 => 'some-id-2', x_amz_request_id => 'some-request-id', x_amz_version_id => 'some-version-id', }, ); } sub with_content_type { my ($content_type) = @_; +( with_response_code => 200, with_response_header => { content_type => $content_type, }, with_response_data => << ' XML', XML ); } Net-Amazon-S3-0.991/t/api-bucket-objects-list.t0000644000175000017500000001306614264646670020055 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_bucket_objects_list ]; plan tests => 9; expect_api_bucket_objects_list 'list objects (version 1)' => ( with_bucket => 'some-bucket', with_response_fixture ('response::bucket_objects_list_v1'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/' }, expect_data => { bucket => 'some-bucket', prefix => '', marker => '', next_marker => '', max_keys => 1000, is_truncated => bool (0), keys => [ { key => 'my-image.jpg', last_modified => '2009-10-12T17:50:30.000Z', etag => 'fba9dede5f27731c9771645a39863328', size => 434234, storage_class => 'STANDARD', owner_id => '75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a', owner_displayname => 'mtd@amazon.com', }, { key => 'my-third-image.jpg', last_modified => '2009-10-12T17:50:30.000Z', etag => '1b2cf535f27731c974343645a3985328', size => 64994, storage_class => 'STANDARD_IA', owner_id => '75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a', owner_displayname => 'mtd@amazon.com', } ], }, ); expect_api_bucket_objects_list 'list objects (version 1) with filters' => ( with_bucket => 'some-bucket', with_response_fixture ('response::bucket_objects_list_v1_with_filter_truncated'), with_prefix => 'N', with_marker => 'Ned', with_max_keys => 40, expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?marker=Ned&max-keys=40&prefix=N' }, expect_data => { bucket => 'some-bucket', prefix => 'N', marker => 'Ned', next_marker => '', max_keys => 40, is_truncated => bool (1), keys => [ { key => 'Nelson', last_modified => '2006-01-01T12:00:00.000Z', etag => '828ef3fdfa96f00ad9f27c383fc9ac7f', size => 5, storage_class => 'STANDARD', owner_id => 'bcaf161ca5fb16fd081034f', owner_displayname => 'webfile', }, { key => 'Neo', last_modified => '2006-01-01T12:00:00.000Z', etag => '828ef3fdfa96f00ad9f27c383fc9ac7f', size => 4, storage_class => 'STANDARD', owner_id => 'bcaf1ffd86a5fb16fd081034f', owner_displayname => 'webfile', } ], }, ); expect_api_bucket_objects_list 'list objects (version 1) with delimiter' => ( with_bucket => 'some-bucket', with_response_fixture ('response::bucket_objects_list_v1_with_delimiter'), with_delimiter => '/', expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?delimiter=%2F' }, expect_data => { bucket => 'some-bucket', prefix => '', marker => '', next_marker => '', max_keys => 1000, is_truncated => bool (0), keys => [ { key => 'sample.jpg', last_modified => '2011-02-26T01:56:20.000Z', etag => 'bf1d737a4d46a19f3bced6905cc8b902', size => 142863, storage_class => 'STANDARD', owner_id => 'canonical-user-id', owner_displayname => 'display-name', } ], common_prefixes => [ 'photos', ], }, ); expect_api_bucket_objects_list 'list objects (version 1) with prefix and delimiter' => ( with_bucket => 'some-bucket', with_response_fixture ('response::bucket_objects_list_v1_with_prefix_and_delimiter'), with_delimiter => '/', with_prefix => 'photos/2006/', expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/?delimiter=%2F&prefix=photos%2F2006%2F' }, expect_data => { bucket => 'some-bucket', prefix => 'photos/2006/', marker => '', next_marker => '', max_keys => 1000, is_truncated => bool (0), keys => [], common_prefixes => [ 'photos/2006/February', 'photos/2006/January', ], }, ); expect_api_bucket_objects_list 'list objects (version 1) on Google Cloud Storage' => ( with_bucket => 'gcs-bucket', with_response_fixture ('response::bucket_objects_list_v1_google_cloud_storage'), with_s3 => s3_api_with_signature_2(host => 'storage.googleapis.com'), expect_request => { GET => 'https://gcs-bucket.storage.googleapis.com/' }, expect_data => { bucket => 'gcs-bucket', prefix => '', marker => '', max_keys => '', next_marker => 'next/marker/is/foo', is_truncated => bool (1), keys => [ { key => 'path/to/value', last_modified => '2017-04-21T22:06:03.413Z', etag => '1f52bad2879ca96dacd7a40f33001230', size => 742213, storage_class => '', owner_id => '', owner_displayname => '', }, { key => 'path/to/value2', last_modified => '2018-04-21T22:06:03.413Z', etag => '1f52bad2889ca96dacd7a40f33001230', size => 742214, storage_class => '', owner_id => '', owner_displayname => '', } ], }, ); expect_api_bucket_objects_list 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_response_fixture ('error::access_denied'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/' }, expect_s3_error_access_denied, ); expect_api_bucket_objects_list 'S3 error - No Such Bucket' => ( with_bucket => 'some-bucket', with_response_fixture ('error::no_such_bucket'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/' }, expect_s3_error_bucket_not_found, ); expect_api_bucket_objects_list 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_response_fixture ('error::http_bad_request'), expect_request => { GET => 'https://some-bucket.s3.amazonaws.com/' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/test-helper-tags.pl0000644000175000017500000000056114264646670016765 0ustar branobrano#!perl use strict; use warnings; sub fixture_tags_foo_bar_xml { <<'EOXML', bar baz foo bar EOXML } sub fixture_tags_foo_bar_hashref { +{ foo => 'bar', 'bar' => 'baz' }, } 1; Net-Amazon-S3-0.991/t/api-object-acl-set.t0000644000175000017500000001002314264646670016762 0ustar branobrano use strict; use warnings; use FindBin; BEGIN { require "$FindBin::Bin/test-helper-s3-api.pl" } use Shared::Examples::Net::Amazon::S3::API qw[ expect_api_object_acl_set ]; plan tests => 10; expect_api_object_acl_set 'set object acl using deprecated acl_short' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl_short => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_api_object_acl_set 'set object acl using canned acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => Net::Amazon::S3::ACL::Canned->PRIVATE, with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_api_object_acl_set 'set object acl using canned acl coerction' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_acl => 'private', }, expect_data => bool (1), ); expect_api_object_acl_set 'set object acl using explicit acl' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => Net::Amazon::S3::ACL::Set->new ->grant_read (id => '123', id => '234') ->grant_write (id => '345') , with_response_fixture ('response::acl'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => '', expect_request_headers => { x_amz_grant_read => 'id="123", id="234"', x_amz_grant_write => 'id="345"', }, expect_data => bool (1), ); expect_api_object_acl_set 'set object acl using XML content' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl_xml => 'PASSTHROUGH', expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_request_content => 'PASSTHROUGH', expect_request_headers => { x_amz_acl => undef, }, expect_data => bool (1), ); expect_api_object_acl_set 'S3 error - Access Denied' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::access_denied'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_s3_error_access_denied, ); expect_api_object_acl_set 'S3 error - Bucket Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::no_such_bucket'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_s3_error_bucket_not_found, ); expect_api_object_acl_set 'S3 error - Object Not Found' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::no_such_key'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_s3_error_object_not_found, ); expect_api_object_acl_set 'HTTP error - 400 Bad Request' => ( with_bucket => 'some-bucket', with_key => 'some-key', with_acl => 'private', with_response_fixture ('error::http_bad_request'), expect_request => { PUT => 'https://some-bucket.s3.amazonaws.com/some-key?acl' }, expect_http_error_bad_request, ); had_no_warnings; done_testing; Net-Amazon-S3-0.991/t/03token.t0000644000175000017500000000163114264646670014707 0ustar branobrano#!perl use warnings; use strict; use lib 'lib'; use Test::More; use Test::Exception; unless ( $ENV{'AWS_ACCESS_KEY_ID'} and $ENV{'AWS_ACCESS_KEY_SECRET'} and $ENV{'AWS_ACCESS_TOKEN'} ) { plan skip_all => 'Need these vars in ENV: AWS_ACCESS_KEY_ID, ' . 'AWS_ACCESS_KEY_SECRET, AWS_ACCESS_TOKEN'; } else { plan tests => 1 + 1; } use_ok('Net::Amazon::S3'); my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'}; my $aws_secret_access_key = $ENV{'AWS_ACCESS_KEY_SECRET'}; my $aws_session_token = $ENV{'AWS_ACCESS_TOKEN'}; my $s3 = Net::Amazon::S3->new( { aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, aws_session_token => $aws_session_token, retry => 1, } ); # list all buckets that i own my $response = $s3->buckets; ok($response, "Authentication with token succeded"); Net-Amazon-S3-0.991/examples/0000775000175000017500000000000014264646670014613 5ustar branobranoNet-Amazon-S3-0.991/examples/backup_cpan.pl0000755000175000017500000000763314264646670017430 0ustar branobrano#!/home/acme/bin/perl use strict; use warnings; use lib 'lib'; use Data::Stream::Bulk::Path::Class; use Net::Amazon::S3; use Perl6::Say; use Path::Class; use Set::Object; use Term::ProgressBar::Simple; use List::Util qw(sum); use Digest::MD5::File qw(file_md5_hex); use BerkeleyDB::Manager; use Cwd; use Config; my $m = BerkeleyDB::Manager->new( home => Path::Class::Dir->new(cwd), db_class => 'BerkeleyDB::Hash', create => 1, ); my $db = $m->open_db( file => 'md5_cache' ); my $s3 = Net::Amazon::S3->new( aws_access_key_id => 'XXX', aws_secret_access_key => 'XXX', retry => 1, ); my $client = Net::Amazon::S3::Client->new( s3 => $s3 ); my $bucket = $client->bucket( name => 'minicpan' ); my $root = '/home/acme/Public/minicpan/'; my $file_stream = Data::Stream::Bulk::Path::Class->new( dir => Path::Class::Dir->new($root), only_files => 1, ); my %files; my $file_set = Set::Object->new(); until ( $file_stream->is_done ) { foreach my $filename ( $file_stream->items ) { my $key = $filename->relative($root)->stringify; #[rootname]path/to/file.txt:,,, my $stat = $filename->stat; my $ctime = $stat->ctime; my $mtime = $stat->mtime; my $size = $stat->size; my $inodenum = $stat->ino; my $cachekey = "$key:$ctime,$mtime,$size,$inodenum"; $db->db_get( $cachekey, my $md5_hex ); if ($md5_hex) { #say "hit $cachekey $md5hex"; } else { $md5_hex = file_md5_hex($filename) || die "Failed to find MD5 for $filename"; $m->txn_do( sub { $db->db_put( $cachekey, $md5_hex ); } ); #say "miss $cachekey $md5_hex"; } $files{$key} = { filename => $filename, key => $key, md5_hex => $md5_hex, size => -s $filename, }; $file_set->insert($key); } } my %objects; my $s3_set = Set::Object->new(); my $object_stream = $bucket->list; until ( $object_stream->is_done ) { foreach my $object ( $object_stream->items ) { my $key = $object->key; $objects{$key} = { filename => file( $root, $key )->stringify, key => $key, md5_hex => $object->etag, size => $object->size, }; # say $object->key . ' ' . $object->size . ' ' . $object->etag; $s3_set->insert( $object->key ); } } my @to_add; my @to_delete; foreach my $key ( sort keys %files ) { my $file = $files{$key}; my $object = $objects{$key}; if ($object) { if ( $file->{md5_hex} eq $object->{md5_hex} ) { # say "$key same"; } else { # say "$key different"; push @to_add, $file; } } else { #say "$key missing"; push @to_add, $file; } } foreach my $key ( sort keys %objects ) { my $object = $objects{$key}; my $file = $files{$key}; if ($file) { } else { # say "$key to delete"; push @to_delete, $object; } } my $total_size = sum map { file( $_->{filename} )->stat->size } @to_add; $total_size += scalar(@to_delete); my $progress = Term::ProgressBar::Simple->new($total_size); foreach my $file (@to_add) { my $key = $file->{key}; my $filename = $file->{filename}; my $md5_hex = $file->{md5_hex}; my $size = $file->{size}; # say "put $key"; $progress += $size; my $object = $bucket->object( key => $key, etag => $md5_hex, size => $size ); $object->put_filename($filename); } foreach my $object (@to_delete) { my $key = $object->{key}; my $filename = $object->{filename}; my $object = $bucket->object(key => $key); # say "delete $key"; $object->delete; $progress++; } Net-Amazon-S3-0.991/MANIFEST0000644000175000017500000002761214264646670014134 0ustar branobrano# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.025. CHANGES LICENSE MANIFEST META.json META.yml Makefile.PL README README.md README.mkdn bin/s3cl cpanfile dist.ini examples/backup_cpan.pl lib/Net/Amazon/S3.pm lib/Net/Amazon/S3/ACL.pod lib/Net/Amazon/S3/ACL/Canned.pm lib/Net/Amazon/S3/ACL/Grantee.pm lib/Net/Amazon/S3/ACL/Grantee/Email.pm lib/Net/Amazon/S3/ACL/Grantee/Group.pm lib/Net/Amazon/S3/ACL/Grantee/User.pm lib/Net/Amazon/S3/ACL/Set.pm lib/Net/Amazon/S3/Authorization.pm lib/Net/Amazon/S3/Authorization/Basic.pm lib/Net/Amazon/S3/Authorization/IAM.pm lib/Net/Amazon/S3/Bucket.pm lib/Net/Amazon/S3/Client.pm lib/Net/Amazon/S3/Client/Bucket.pm lib/Net/Amazon/S3/Client/Object.pm lib/Net/Amazon/S3/Client/Object/Range.pm lib/Net/Amazon/S3/Constants.pm lib/Net/Amazon/S3/Constraint/ACL/Canned.pm lib/Net/Amazon/S3/Constraint/Etag.pm lib/Net/Amazon/S3/Error/Handler.pm lib/Net/Amazon/S3/Error/Handler/Confess.pm lib/Net/Amazon/S3/Error/Handler/Legacy.pm lib/Net/Amazon/S3/Error/Handler/Status.pm lib/Net/Amazon/S3/Error/Handler/X.pm lib/Net/Amazon/S3/Features.pod lib/Net/Amazon/S3/HTTPRequest.pm lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch.pm lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch/Request.pm lib/Net/Amazon/S3/Operation/Bucket/Acl/Fetch/Response.pm lib/Net/Amazon/S3/Operation/Bucket/Acl/Set.pm lib/Net/Amazon/S3/Operation/Bucket/Acl/Set/Request.pm lib/Net/Amazon/S3/Operation/Bucket/Acl/Set/Response.pm lib/Net/Amazon/S3/Operation/Bucket/Create.pm lib/Net/Amazon/S3/Operation/Bucket/Create/Request.pm lib/Net/Amazon/S3/Operation/Bucket/Create/Response.pm lib/Net/Amazon/S3/Operation/Bucket/Delete.pm lib/Net/Amazon/S3/Operation/Bucket/Delete/Request.pm lib/Net/Amazon/S3/Operation/Bucket/Delete/Response.pm lib/Net/Amazon/S3/Operation/Bucket/Location.pm lib/Net/Amazon/S3/Operation/Bucket/Location/Request.pm lib/Net/Amazon/S3/Operation/Bucket/Location/Response.pm lib/Net/Amazon/S3/Operation/Bucket/Tags/Add.pm lib/Net/Amazon/S3/Operation/Bucket/Tags/Add/Request.pm lib/Net/Amazon/S3/Operation/Bucket/Tags/Add/Response.pm lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete.pm lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete/Request.pm lib/Net/Amazon/S3/Operation/Bucket/Tags/Delete/Response.pm lib/Net/Amazon/S3/Operation/Buckets/List.pm lib/Net/Amazon/S3/Operation/Buckets/List/Request.pm lib/Net/Amazon/S3/Operation/Buckets/List/Response.pm lib/Net/Amazon/S3/Operation/Object/Acl/Fetch.pm lib/Net/Amazon/S3/Operation/Object/Acl/Fetch/Request.pm lib/Net/Amazon/S3/Operation/Object/Acl/Fetch/Response.pm lib/Net/Amazon/S3/Operation/Object/Acl/Set.pm lib/Net/Amazon/S3/Operation/Object/Acl/Set/Request.pm lib/Net/Amazon/S3/Operation/Object/Acl/Set/Response.pm lib/Net/Amazon/S3/Operation/Object/Add.pm lib/Net/Amazon/S3/Operation/Object/Add/Request.pm lib/Net/Amazon/S3/Operation/Object/Add/Response.pm lib/Net/Amazon/S3/Operation/Object/Delete.pm lib/Net/Amazon/S3/Operation/Object/Delete/Request.pm lib/Net/Amazon/S3/Operation/Object/Delete/Response.pm lib/Net/Amazon/S3/Operation/Object/Fetch.pm lib/Net/Amazon/S3/Operation/Object/Fetch/Request.pm lib/Net/Amazon/S3/Operation/Object/Fetch/Response.pm lib/Net/Amazon/S3/Operation/Object/Head.pm lib/Net/Amazon/S3/Operation/Object/Head/Request.pm lib/Net/Amazon/S3/Operation/Object/Head/Response.pm lib/Net/Amazon/S3/Operation/Object/Restore.pm lib/Net/Amazon/S3/Operation/Object/Restore/Request.pm lib/Net/Amazon/S3/Operation/Object/Restore/Response.pm lib/Net/Amazon/S3/Operation/Object/Tags/Add.pm lib/Net/Amazon/S3/Operation/Object/Tags/Add/Request.pm lib/Net/Amazon/S3/Operation/Object/Tags/Add/Response.pm lib/Net/Amazon/S3/Operation/Object/Tags/Delete.pm lib/Net/Amazon/S3/Operation/Object/Tags/Delete/Request.pm lib/Net/Amazon/S3/Operation/Object/Tags/Delete/Response.pm lib/Net/Amazon/S3/Operation/Object/Upload/Abort.pm lib/Net/Amazon/S3/Operation/Object/Upload/Abort/Request.pm lib/Net/Amazon/S3/Operation/Object/Upload/Abort/Response.pm lib/Net/Amazon/S3/Operation/Object/Upload/Complete.pm lib/Net/Amazon/S3/Operation/Object/Upload/Complete/Request.pm lib/Net/Amazon/S3/Operation/Object/Upload/Complete/Response.pm lib/Net/Amazon/S3/Operation/Object/Upload/Create.pm lib/Net/Amazon/S3/Operation/Object/Upload/Create/Request.pm lib/Net/Amazon/S3/Operation/Object/Upload/Create/Response.pm lib/Net/Amazon/S3/Operation/Object/Upload/Part.pm lib/Net/Amazon/S3/Operation/Object/Upload/Part/Request.pm lib/Net/Amazon/S3/Operation/Object/Upload/Part/Response.pm lib/Net/Amazon/S3/Operation/Object/Upload/Parts.pm lib/Net/Amazon/S3/Operation/Object/Upload/Parts/Request.pm lib/Net/Amazon/S3/Operation/Object/Upload/Parts/Response.pm lib/Net/Amazon/S3/Operation/Objects/Delete.pm lib/Net/Amazon/S3/Operation/Objects/Delete/Request.pm lib/Net/Amazon/S3/Operation/Objects/Delete/Response.pm lib/Net/Amazon/S3/Operation/Objects/List.pm lib/Net/Amazon/S3/Operation/Objects/List/Request.pm lib/Net/Amazon/S3/Operation/Objects/List/Response.pm lib/Net/Amazon/S3/Request.pm lib/Net/Amazon/S3/Request/Bucket.pm lib/Net/Amazon/S3/Request/Object.pm lib/Net/Amazon/S3/Request/Role/HTTP/Header.pm lib/Net/Amazon/S3/Request/Role/HTTP/Header/ACL.pm lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_length.pm lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_md5.pm lib/Net/Amazon/S3/Request/Role/HTTP/Header/Content_type.pm lib/Net/Amazon/S3/Request/Role/HTTP/Header/Copy_source.pm lib/Net/Amazon/S3/Request/Role/HTTP/Header/Encryption.pm lib/Net/Amazon/S3/Request/Role/HTTP/Method.pm lib/Net/Amazon/S3/Request/Role/HTTP/Method/DELETE.pm lib/Net/Amazon/S3/Request/Role/HTTP/Method/GET.pm lib/Net/Amazon/S3/Request/Role/HTTP/Method/HEAD.pm lib/Net/Amazon/S3/Request/Role/HTTP/Method/POST.pm lib/Net/Amazon/S3/Request/Role/HTTP/Method/PUT.pm lib/Net/Amazon/S3/Request/Role/Query/Action.pm lib/Net/Amazon/S3/Request/Role/Query/Action/Acl.pm lib/Net/Amazon/S3/Request/Role/Query/Action/Delete.pm lib/Net/Amazon/S3/Request/Role/Query/Action/Location.pm lib/Net/Amazon/S3/Request/Role/Query/Action/Restore.pm lib/Net/Amazon/S3/Request/Role/Query/Action/Tagging.pm lib/Net/Amazon/S3/Request/Role/Query/Action/Uploads.pm lib/Net/Amazon/S3/Request/Role/Query/Param.pm lib/Net/Amazon/S3/Request/Role/Query/Param/Delimiter.pm lib/Net/Amazon/S3/Request/Role/Query/Param/Marker.pm lib/Net/Amazon/S3/Request/Role/Query/Param/Max_keys.pm lib/Net/Amazon/S3/Request/Role/Query/Param/Part_number.pm lib/Net/Amazon/S3/Request/Role/Query/Param/Prefix.pm lib/Net/Amazon/S3/Request/Role/Query/Param/Upload_id.pm lib/Net/Amazon/S3/Request/Role/Query/Param/Version_id.pm lib/Net/Amazon/S3/Request/Role/Tags/Add.pm lib/Net/Amazon/S3/Request/Role/XML/Content.pm lib/Net/Amazon/S3/Request/Service.pm lib/Net/Amazon/S3/Response.pm lib/Net/Amazon/S3/Role/ACL.pm lib/Net/Amazon/S3/Role/Bucket.pm lib/Net/Amazon/S3/Signature.pm lib/Net/Amazon/S3/Signature/V2.pm lib/Net/Amazon/S3/Signature/V4.pm lib/Net/Amazon/S3/Signature/V4Implementation.pm lib/Net/Amazon/S3/Utils.pm lib/Net/Amazon/S3/Vendor.pm lib/Net/Amazon/S3/Vendor/Amazon.pm lib/Net/Amazon/S3/Vendor/Generic.pm lib/Net/Amazon/S3/X.pm lib/Shared/Examples/Net/Amazon/S3.pm lib/Shared/Examples/Net/Amazon/S3/API.pm lib/Shared/Examples/Net/Amazon/S3/Client.pm lib/Shared/Examples/Net/Amazon/S3/Fixture.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/access_denied.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/bucket_already_exists.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/bucket_not_empty.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/http_bad_request.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/invalid_bucket_name.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/invalid_object_state.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/no_such_bucket.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/error/no_such_key.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/request/bucket_create_ca_central_1.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/acl.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_delete_quiet_without_errors.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_google_cloud_storage.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_delimiter.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_filter.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_filter_truncated.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/bucket_objects_list_v1_with_prefix_and_delimiter.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/create_multipart_upload_with_success.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/http_ok_empty.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_with_owner_displayname.pm lib/Shared/Examples/Net/Amazon/S3/Fixture/response/service_list_buckets_without_owner_displayname.pm lib/Shared/Examples/Net/Amazon/S3/Request.pm perlcritic.rc t/01api.t t/02client.t t/03token.t t/acl-set.t t/api-bucket-acl-get.t t/api-bucket-acl-set.t t/api-bucket-create.t t/api-bucket-delete.t t/api-bucket-objects-delete.t t/api-bucket-objects-list.t t/api-bucket-tags-add.t t/api-bucket-tags-delete.t t/api-build-bucket.t t/api-construct.t t/api-object-acl-get.t t/api-object-acl-set.t t/api-object-create.t t/api-object-delete.t t/api-object-fetch.t t/api-object-head.t t/api-object-tags-add.t t/api-object-tags-delete.t t/api-service-buckets-list.t t/author-eol.t t/client-bucket-acl-get.t t/client-bucket-acl-set.t t/client-bucket-create.t t/client-bucket-delete.t t/client-bucket-objects-delete.t t/client-bucket-objects-list.t t/client-bucket-tags-add.t t/client-bucket-tags-delete.t t/client-construct.t t/client-object-acl-set.t t/client-object-create.t t/client-object-delete.t t/client-object-exists.t t/client-object-fetch.t t/client-object-head.t t/client-object-tags-add.t t/client-object-tags-delete.t t/client-service-buckets-list.t t/data/s3-operation-object-add.txt t/error-handler-x.t t/issue-39-content-length-0.t t/issue-88-non-standard-service-port.t t/query-string-authentication-uri.t t/request.t t/response.t t/s3-operation-bucket-acl-fetch.t t/s3-operation-bucket-acl-set.t t/s3-operation-bucket-create.t t/s3-operation-bucket-delete.t t/s3-operation-bucket-location.t t/s3-operation-bucket-tags-add.t t/s3-operation-bucket-tags-delete.t t/s3-operation-buckets-list.t t/s3-operation-object-acl-fetch.t t/s3-operation-object-acl-set.t t/s3-operation-object-add.t t/s3-operation-object-copy.t t/s3-operation-object-delete.t t/s3-operation-object-fetch.t t/s3-operation-object-head.t t/s3-operation-object-restore.t t/s3-operation-object-tags-add.t t/s3-operation-object-tags-delete.t t/s3-operation-object-upload-abort.t t/s3-operation-object-upload-complete.t t/s3-operation-object-upload-create.t t/s3-operation-object-upload-part.t t/s3-operation-objects-delete.t t/s3-operation-objects-list.t t/s3-request-bucket-acl-fetch.t t/s3-request-bucket-acl-set.t t/s3-request-bucket-create.t t/s3-request-bucket-delete.t t/s3-request-bucket-location.t t/s3-request-bucket-objects-delete.t t/s3-request-bucket-objects-list.t t/s3-request-bucket-tags-add.t t/s3-request-bucket-tags-delete.t t/s3-request-object-acl-fetch.t t/s3-request-object-acl-set.t t/s3-request-object-add.t t/s3-request-object-delete.t t/s3-request-object-fetch.t t/s3-request-object-restore.t t/s3-request-object-tags-add.t t/s3-request-object-tags-delete.t t/s3-request-object-upload-abort.t t/s3-request-object-upload-complete.t t/s3-request-object-upload-create.t t/s3-request-object-upload-part.t t/s3-request-object-upload-parts.t t/s3-request-service-buckets-list.t t/s3-response-object-upload-create.t t/s3-response-service-buckets-list.t t/signature-v4-with-security-token.t t/test-helper-common.pl t/test-helper-errors.pl t/test-helper-operation.pl t/test-helper-s3-api-error-confess.pl t/test-helper-s3-api-error-status.pl t/test-helper-s3-api.pl t/test-helper-s3-client.pl t/test-helper-s3-request.pl t/test-helper-s3-response.pl t/test-helper-tags.pl t/use-api.t t/use-client.t t/utils-parse-arguments.t t/vendor-amazon.t t/vendor-generic.t t/vendor-info.t Net-Amazon-S3-0.991/perlcritic.rc0000644000175000017500000000052314264646670015461 0ustar branobranoseverity = 5 only = 1 force = 0 verbose = 4 top = 50 theme = (pbp || security) && bugs include = NamingConventions ClassHierarchies CodeLayout::TabIndentSpaceAlign exclude = Variables Modules::RequirePackage RequireUseStrict RequireUseWarnings criticism-fatal = 1 color = 1 allow-unsafe = 1 pager = less Net-Amazon-S3-0.991/README.mkdn0000644000175000017500000005700314264646670014610 0ustar branobrano# NAME Net::Amazon::S3 - Use the Amazon S3 - Simple Storage Service # VERSION version 0.991 # SYNOPSIS use Net::Amazon::S3; use Net::Amazon::S3::Authorization::Basic; use Net::Amazon::S3::Authorization::IAM; my $aws_access_key_id = 'fill me in'; my $aws_secret_access_key = 'fill me in too'; my $s3 = Net::Amazon::S3->new ( authorization_context => Net::Amazon::S3::Authorization::Basic->new ( aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, ), retry => 1, ); # or use an IAM role. my $s3 = Net::Amazon::S3->new ( authorization_context => Net::Amazon::S3::Authorization::IAM->new ( aws_access_key_id => $aws_access_key_id, aws_secret_access_key => $aws_secret_access_key, ), retry => 1, ); # a bucket is a globally-unique directory # list all buckets that i own my $response = $s3->buckets; foreach my $bucket ( @{ $response->{buckets} } ) { print "You have a bucket: " . $bucket->bucket . "\n"; } # create a new bucket my $bucketname = 'acmes_photo_backups'; my $bucket = $s3->add_bucket( { bucket => $bucketname } ) or die $s3->err . ": " . $s3->errstr; # or use an existing bucket $bucket = $s3->bucket($bucketname); # store a file in the bucket $bucket->add_key_filename( '1.JPG', 'DSC06256.JPG', { content_type => 'image/jpeg', }, ) or die $s3->err . ": " . $s3->errstr; # store a value in the bucket $bucket->add_key( 'reminder.txt', 'this is where my photos are backed up' ) or die $s3->err . ": " . $s3->errstr; # list files in the bucket $response = $bucket->list_all or die $s3->err . ": " . $s3->errstr; foreach my $key ( @{ $response->{keys} } ) { my $key_name = $key->{key}; my $key_size = $key->{size}; print "Bucket contains key '$key_name' of size $key_size\n"; } # fetch file from the bucket $response = $bucket->get_key_filename( '1.JPG', 'GET', 'backup.jpg' ) or die $s3->err . ": " . $s3->errstr; # fetch value from the bucket $response = $bucket->get_key('reminder.txt') or die $s3->err . ": " . $s3->errstr; print "reminder.txt:\n"; print " content length: " . $response->{content_length} . "\n"; print " content type: " . $response->{content_type} . "\n"; print " etag: " . $response->{content_type} . "\n"; print " content: " . $response->{value} . "\n"; # delete keys $bucket->delete_key('reminder.txt') or die $s3->err . ": " . $s3->errstr; $bucket->delete_key('1.JPG') or die $s3->err . ": " . $s3->errstr; # and finally delete the bucket $bucket->delete_bucket or die $s3->err . ": " . $s3->errstr; # DESCRIPTION This module provides a Perlish interface to Amazon S3. From the developer blurb: "Amazon S3 is storage for the Internet. It is designed to make web-scale computing easier for developers. Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of web sites. The service aims to maximize benefits of scale and to pass those benefits on to developers". To find out more about S3, please visit: http://s3.amazonaws.com/ To use this module you will need to sign up to Amazon Web Services and provide an "Access Key ID" and " Secret Access Key". If you use this module, you will incurr costs as specified by Amazon. Please check the costs. If you use this module with your Access Key ID and Secret Access Key you must be responsible for these costs. I highly recommend reading all about S3, but in a nutshell data is stored in values. Values are referenced by keys, and keys are stored in buckets. Bucket names are global. Note: This is the legacy interface, please check out [Net::Amazon::S3::Client](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AClient) instead. Development of this code happens here: https://github.com/rustyconover/net-amazon-s3 ## Bucket names with dots, HTTPS, and Signature V4 At the moment Amazon S3 doesn't play well with HTTPS and virtual bucket hosts if bucket name contains dots. Due the current implementation of Signature V4 handling you should use workaround consisting of usage of region hostnames my $bucket_region = $global_s3->bucket ($bucket)->_head_region; my $region_s3 = Net::Amazon:S3->new ( ..., vendor => Net::Amazon::S3::Vendor::Amazon->new ( host => "s3-$bucket_region.amazonaws.com", use_virtual_host => 0, ), ); my $bucket = $region_s3->bucket ($bucket); And use bucket instance / region s3 connection. # METHODS ## new Create a new S3 client object. Takes some arguments: - authorization\_context Class that provides authorization information. See one of available implementations for more - [Net::Amazon::S3::Authorization::Basic](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AAuthorization%3A%3ABasic) - [Net::Amazon::S3::Authorization::IAM](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AAuthorization%3A%3AIAM) - vendor Instance of [Net::Amazon::S3::Vendor](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AVendor) holding vendor specific deviations. S3 became widely used object storage protocol with many vendors providing different feature sets and different compatibility level. One common difference is bucket's HEAD request to determine its region. To maintain currently known differences along with any differencies that may rise in feature it's better to hold vendor specification in dedicated classes. This also allows users to build their own fine-tuned vendor classes. - [Net::Amazon::S3::Vendor::Amazon](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AVendor%3A%3AAmazon) - [Net::Amazon::S3::Vendor::Generic](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AVendor%3A%3AGeneric) - aws\_access\_key\_id Deprecated. When used it's used to create authorization context. Use your Access Key ID as the value of the AWSAccessKeyId parameter in requests you send to Amazon Web Services (when required). Your Access Key ID identifies you as the party responsible for the request. - aws\_secret\_access\_key Deprecated. When used it's used to create authorization context. Since your Access Key ID is not encrypted in requests to AWS, it could be discovered and used by anyone. Services that are not free require you to provide additional information, a request signature, to verify that a request containing your unique Access Key ID could only have come from you. DO NOT INCLUDE THIS IN SCRIPTS OR APPLICATIONS YOU DISTRIBUTE. YOU'LL BE SORRY - aws\_session\_token Deprecated. When used it's used to create authorization context. If you are using temporary credentials provided by the AWS Security Token Service, set the token here, and it will be added to the request in order to authenticate it. - use\_iam\_role Deprecated. When used it's used to create authorization context. If you'd like to use IAM provided temporary credentials, pass this option with a true value. - secure Deprecated. Set this to `0` if you don't want to use SSL-encrypted connections when talking to S3. Defaults to `1`. To use SSL-encrypted connections, LWP::Protocol::https is required. See [#vendor](https://metacpan.org/pod/%23vendor) and [Net::Amazon::S3::Vendor](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AVendor). - keep\_alive\_cache\_size Set this to `0` to disable Keep-Alives. Default is `10`. - timeout How many seconds should your script wait before bailing on a request to S3? Defaults to 30. - retry If this library should retry upon errors. This option is recommended. This uses exponential backoff with retries after 1, 2, 4, 8, 16, 32 seconds, as recommended by Amazon. Defaults to off. When retry is on, request will be automatically retried when one of following HTTP statuses happens - 408 - Request Timeout - 500 - Internal Server Error - 502 - Bad Gateway - 503 - Service Unavailable - 504 - Gateway Timeout For more details see [LWP::UserAgent::Determined](https://metacpan.org/pod/LWP%3A%3AUserAgent%3A%3ADetermined). - host Deprecated. The S3 host endpoint to use. Defaults to 's3.amazonaws.com'. This allows you to connect to any S3-compatible host. See [#vendor](https://metacpan.org/pod/%23vendor) and [Net::Amazon::S3::Vendor](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AVendor). - use\_virtual\_host Deprecated. Use the virtual host method ('bucketname.s3.amazonaws.com') instead of specifying the bucket at the first part of the path. This is particularly useful if you want to access buckets not located in the US-Standard region (such as EU, Asia Pacific or South America). See [http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html](http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html) for the pros and cons. See [#vendor](https://metacpan.org/pod/%23vendor) and [Net::Amazon::S3::Vendor](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AVendor). - authorization\_method Deprecated. Authorization implementation package name. This library provides [Net::Amazon::S3::Signature::V2](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3ASignature%3A%3AV2) and [Net::Amazon::S3::Signature::V4](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3ASignature%3A%3AV4) Default is Signature 4 if host is `s3.amazonaws.com`, Signature 2 otherwise See [#vendor](https://metacpan.org/pod/%23vendor) and [Net::Amazon::S3::Vendor](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AVendor). - error\_handler\_class Error handler class name (package name), see [Net::Amazon::S3::Error::Handler](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AError%3A%3AHandler) for more. Default: [Net::Amazon::S3::Error::Handler::Legacy](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AError%3A%3AHandler%3A%3ALegacy) - error\_handler Instance of error handler class. ### Notes When using [Net::Amazon::S3](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3) in child processes using fork (such as in combination with the excellent [Parallel::ForkManager](https://metacpan.org/pod/Parallel%3A%3AForkManager)) you should create the S3 object in each child, use a fresh LWP::UserAgent in each child, or disable the [LWP::ConnCache](https://metacpan.org/pod/LWP%3A%3AConnCache) in the parent: $s3->ua( LWP::UserAgent->new( keep_alive => 0, requests_redirectable => [qw'GET HEAD DELETE PUT POST'] ); ## buckets Returns undef on error, else hashref of results ## add\_bucket # Create new bucket with default location my $bucket = $s3->add_bucket ('new-bucket'); # Create new bucket in another location my $bucket = $s3->add_bucket ('new-bucket', location_constraint => 'eu-west-1'); my $bucket = $s3->add_bucket ('new-bucket', { location_constraint => 'eu-west-1' }); my $bucket = $s3->add_bucket (bucket => 'new-bucket', location_constraint => 'eu-west-1'); my $bucket = $s3->add_bucket ({ bucket => 'new-bucket', location_constraint => 'eu-west-1' }); Method creates and returns new bucket. In case of error it reports it and returns `undef` (refer ["ERROR HANDLING"](#error-handling)). Recognized positional arguments (refer ["CALLING CONVENTION"](#calling-convention)) - bucket Required, recognized as positional. The name of the bucket you want to add. Recognized optional arguments - acl acl => 'private' acl => Net::Amazon::S3::ACL::Canned->PRIVATE acl => Net::Amazon::S3::ACL::Set->grant_read (email => 'foo@bar.baz') _Available since v0.94_ Set ACL to the newly created bucket. Refer [Net::Amazon::S3::ACL](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AACL) for possibilities. - acl\_short (deprecated) _Deprecated since v0.94_ When specified its value is used to populate `acl` argument (unless it exists). - location\_constraint Optional. Sets the location constraint of the new bucket. If left unspecified, the default S3 datacenter location will be used. This library recognizes regions according Amazon S3 documentation - → [https://docs.aws.amazon.com/general/latest/gr/rande.html#s3\_region](https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region) - → [https://docs.aws.amazon.com/AmazonS3/latest/API/API\_CreateBucket.html#API\_CreateBucket\_RequestSyntax](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html#API_CreateBucket_RequestSyntax) Provides operation [CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html). ## bucket BUCKET # build bucket with guessed region $s3->bucket ('foo'); $s3->bucket (bucket => 'foo'); $s3->bucket (name => 'foo'); # build with explicit region $s3->bucket ('foo', region => 'bar'); Returns an (unverified) bucket object from an account. Does no network access. However, when guessing region, `HeadRegion` operation may be called before first network access. Region is mandatory when using Signature V4 authorization, which is default for AWS. AWS limits number of HTTP requests, see [https://aws.amazon.com/premiumsupport/knowledge-center/s3-request-limit-avoid-throttling/](https://aws.amazon.com/premiumsupport/knowledge-center/s3-request-limit-avoid-throttling/) ## delete\_bucket $s3->delete_bucket ($bucket); $s3->delete_bucket (bucket => $bucket); Deletes bucket from account. Returns `true` if the bucket is successfully deleted. Returns `false` and reports an error otherwise (refer ["ERROR HANDLING"](#error-handling)) Positional arguments (refer ["CALLING CONVENTION"](#calling-convention)) - bucket Required. The name of the bucket or [Net::Amazon::S3::Bucket](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3ABucket) instance you want to delete. Provides operation ["DeleteBucket"](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html) ## list\_bucket List all keys in this bucket. Takes a hashref of arguments: MANDATORY - bucket The name of the bucket you want to list keys on OPTIONAL - prefix Restricts the response to only contain results that begin with the specified prefix. If you omit this optional argument, the value of prefix for your query will be the empty string. In other words, the results will be not be restricted by prefix. - delimiter If this optional, Unicode string parameter is included with your request, then keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection. These rolled-up keys are not returned elsewhere in the response. For example, with prefix="USA/" and delimiter="/", the matching keys "USA/Oregon/Salem" and "USA/Oregon/Portland" would be summarized in the response as a single "USA/Oregon" element in the CommonPrefixes collection. If an otherwise matching key does not contain the delimiter after the prefix, it appears in the Contents collection. Each element in the CommonPrefixes collection counts as one against the MaxKeys limit. The rolled-up keys represented by each CommonPrefixes element do not. If the Delimiter parameter is not present in your request, keys in the result set will not be rolled-up and neither the CommonPrefixes collection nor the NextMarker element will be present in the response. - max-keys This optional argument limits the number of results returned in response to your query. Amazon S3 will return no more than this number of results, but possibly less. Even if max-keys is not specified, Amazon S3 will limit the number of results in the response. Check the IsTruncated flag to see if your results are incomplete. If so, use the Marker parameter to request the next page of results. For the purpose of counting max-keys, a 'result' is either a key in the 'Contents' collection, or a delimited prefix in the 'CommonPrefixes' collection. So for delimiter requests, max-keys limits the total number of list results, not just the number of keys. - marker This optional parameter enables pagination of large result sets. `marker` specifies where in the result set to resume listing. It restricts the response to only contain results that occur alphabetically after the value of marker. To retrieve the next page of results, use the last key from the current page of results as the marker in your next request. See also `next_marker`, below. If `marker` is omitted,the first page of results is returned. Returns undef on error and a hashref of data on success: The hashref looks like this: { bucket => $bucket_name, prefix => $bucket_prefix, common_prefixes => [$prefix1,$prefix2,...] marker => $bucket_marker, next_marker => $bucket_next_available_marker, max_keys => $bucket_max_keys, is_truncated => $bucket_is_truncated_boolean keys => [$key1,$key2,...] } Explanation of bits of that: - common\_prefixes If list\_bucket was requested with a delimiter, common\_prefixes will contain a list of prefixes matching that delimiter. Drill down into these prefixes by making another request with the prefix parameter. - is\_truncated B flag that indicates whether or not all results of your query were returned in this response. If your results were truncated, you can make a follow-up paginated request using the Marker parameter to retrieve the rest of the results. - next\_marker A convenience element, useful when paginating with delimiters. The value of `next_marker`, if present, is the largest (alphabetically) of all key names and all CommonPrefixes prefixes in the response. If the `is_truncated` flag is set, request the next page of results by setting `marker` to the value of `next_marker`. This element is only present in the response if the `delimiter` parameter was sent with the request. Each key is a hashref that looks like this: { key => $key, last_modified => $last_mod_date, etag => $etag, # An MD5 sum of the stored content. size => $size, # Bytes storage_class => $storage_class # Doc? owner_id => $owner_id, owner_displayname => $owner_name } ## list\_bucket\_all List all keys in this bucket without having to worry about 'marker'. This is a convenience method, but may make multiple requests to S3 under the hood. Takes the same arguments as list\_bucket. ## \_perform\_operation my $response = $s3->_perform_operation ('Operation' => ( # ... operation request parameters )); Internal operation implementation method, takes request construction parameters, performs necessary HTTP requests(s) and returns Response instance. Method takes same named parameters as realted Request class. Method provides available contextual parameters by default (eg s3, bucket) Method invokes contextual error handler. # CALLING CONVENTION _Available since v0.97_ - calling convention extentend In order to make method calls somehow consistent, backward compatible, and extendable, API's methods support multiple ways how to provide their arguments - plain named arguments (preferred) method (named => 'argument', another => 'argument'); - trailing configuration hash method ({ named => 'argument', another => 'argument' }); method (positional, { named => 'argument', another => 'argument' } ); Last argument of every method can be configuration hash, treated as additional named arguments. Can be combined with named arguments. - positional arguments with optional named arguments method (positional, named => 'argument', another => 'argument'); method (positional, { named => 'argument', another => 'argument' } ); For methods supporting mandatory positional arguments additional named arguments and/or configuration hash is supported. Named arguments or configuration hash can specify value of positional arguments as well removing it from list of required positional arguments for given call (see example) $s3->bucket->add_key ('key', 'value', acl => $acl); $s3->bucket->add_key ('value', key => 'key', acl => $acl); $s3->bucket->add_key (key => 'key', value => 'value', acl => $acl); # ERROR HANDLING [Net::Amazon::S3](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3) supports pluggable error handling via [Net::Amazon::S3::Error::Handler](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AError%3A%3AHandler). When response ends up with an error, every method reports it, and in case it receives control back (no exception), it returns `undef`. Default error handling for [Net::Amazon::S3](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3) is [Net::Amazon::S3::Error::Handler::Legacy](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3AError%3A%3AHandler%3A%3ALegacy) which (mostly) sets `err` and `errstr`. # LICENSE This module contains code modified from Amazon that contains the following notice: # This software code is made available "AS IS" without warranties of any # kind. You may copy, display, modify and redistribute the software # code either by itself or as incorporated into your code; provided that # you do not remove any proprietary notices. Your use of this software # code is at your own risk and you waive any claim against Amazon # Digital Services, Inc. or its affiliates with respect to your use of # this software code. (c) 2006 Amazon Digital Services, Inc. or its # affiliates. # TESTING Testing S3 is a tricky thing. Amazon wants to charge you a bit of money each time you use their service. And yes, testing counts as using. Because of this, the application's test suite skips anything approaching a real test unless you set these three environment variables: - AMAZON\_S3\_EXPENSIVE\_TESTS Doesn't matter what you set it to. Just has to be set - AWS\_ACCESS\_KEY\_ID Your AWS access key - AWS\_ACCESS\_KEY\_SECRET Your AWS sekkr1t passkey. Be forewarned that setting this environment variable on a shared system might leak that information to another user. Be careful. # AUTHOR Leon Brocard and unknown Amazon Digital Services programmers. Brad Fitzpatrick - return values, Bucket object Pedro Figueiredo - since 0.54 Branislav Zahradník - since v0.81 # SEE ALSO [Net::Amazon::S3::Bucket](https://metacpan.org/pod/Net%3A%3AAmazon%3A%3AS3%3A%3ABucket) # AUTHOR Branislav Zahradník # COPYRIGHT AND LICENSE This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Net-Amazon-S3-0.991/LICENSE0000644000175000017500000004431614264646670014010 0ustar branobranoThis software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End