File Coverage

blib/lib/Amazon/S3/Thin/ResponseParser.pm
Criterion Covered Total %
statement 34 34 100.0
branch 5 6 83.3
condition n/a
subroutine 9 9 100.0
pod 2 2 100.0
total 50 51 98.0


line stmt bran cond sub pod time code
1             package Amazon::S3::Thin::ResponseParser;
2 3     3   263829 use strict;
  3         14  
  3         93  
3 3     3   13 use warnings;
  3         7  
  3         84  
4 3     3   1734 use XML::LibXML;
  3         115403  
  3         21  
5 3     3   406 use XML::LibXML::XPathContext;
  3         7  
  3         1400  
6              
7             our $VERSION = "0.01";
8              
9             sub new {
10 2     2 1 209 my ($class, %args) = @_;
11              
12 2 50       18 my $xml = exists $args{xml} ? $args{xml} : XML::LibXML->new();
13              
14 2         45 return bless {
15             xml => $xml,
16             }, $class;
17             }
18              
19             sub _xpc {
20 6     6   12 my ($self, $content) = @_;
21 6         25 my $doc = $self->{xml}->parse_string($content);
22 6         1300 my $xpc = XML::LibXML::XPathContext->new($doc);
23 6         47 $xpc->registerNs('s3' => 'http://s3.amazonaws.com/doc/2006-03-01/');
24 6         16 return $xpc;
25             }
26              
27             sub list_objects {
28 6     6 1 17182 my ($self, $content) = @_;
29              
30 6         16 my $xpc = $self->_xpc($content);
31              
32 6 100       20 if ($xpc->findnodes('/Error')) {
33             # https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
34 1         152 my $error = {
35             code => $xpc->findvalue('/Error/Code'),
36             message => $xpc->findvalue('/Error/Message'),
37             request_id => $xpc->findvalue('/Error/RequestId'),
38             resource => $xpc->findvalue('/Error/Resource'),
39             };
40 1         237 return (undef, $error);
41             }
42              
43             # https://docs.aws.amazon.com/AmazonS3/latest/API/v2-RESTBucketGET.html
44             my $result = {
45             contents => [ map {
46             +{
47 6         481 etag => _remove_quote($xpc->findvalue('./s3:ETag', $_)),
48             key => $xpc->findvalue('./s3:Key', $_),
49             last_modified => $xpc->findvalue('./s3:LastModified', $_),
50             owner => {
51             display_name => $xpc->findvalue('./s3:Owner/s3:DisplayName', $_),
52             id => $xpc->findvalue('./s3:Owner/s3:ID', $_),
53             },
54             size => $xpc->findvalue('./s3:Size', $_),
55             storage_class => $xpc->findvalue('./s3:StorageClass', $_),
56             }
57             } $xpc->findnodes('/s3:ListBucketResult/s3:Contents') ],
58             common_prefixes => [ map {
59 5         395 +{
60 2         465 owner => {
61             display_name => $xpc->findvalue('./s3:Owner/s3:DisplayName', $_),
62             id => $xpc->findvalue('./s3:Owner/s3:ID', $_),
63             },
64             prefix => $xpc->findvalue('./s3:Prefix', $_),
65             }
66             } $xpc->findnodes('/s3:ListBucketResult/s3:CommonPrefixes') ],
67             delimiter => $xpc->findvalue('/s3:ListBucketResult/s3:Delimiter'),
68             encoding_type => $xpc->findvalue('/s3:ListBucketResult/s3:EncodingType'),
69             is_truncated => _boolean($xpc->findvalue('/s3:ListBucketResult/s3:IsTruncated')),
70             max_keys => $xpc->findvalue('/s3:ListBucketResult/s3:MaxKeys'),
71             name => $xpc->findvalue('/s3:ListBucketResult/s3:Name'),
72             prefix => $xpc->findvalue('/s3:ListBucketResult/s3:Prefix'),
73             # v1
74             # https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html
75             marker => $xpc->findvalue('/s3:ListBucketResult/s3:Marker'),
76             next_marker => $xpc->findvalue('/s3:ListBucketResult/s3:NextMarker'),
77             # v2
78             continuation_token => $xpc->findvalue('/s3:ListBucketResult/s3:ContinuationToken'),
79             next_continuation_token => $xpc->findvalue('/s3:ListBucketResult/s3:NextContinuationToken'),
80             key_count => $xpc->findvalue('/s3:ListBucketResult/s3:KeyCount'),
81             start_after => $xpc->findvalue('/s3:ListBucketResult/s3:StartAfter'),
82             };
83 5         1828 return ($result, undef);
84             }
85              
86             sub _boolean {
87 5     5   2103 my $s = shift;
88 5 100       20 return $s eq 'true' ? 1 : 0;
89             }
90              
91             sub _remove_quote {
92 6     6   388 my $s = shift;
93 6         49 $s =~ s/^"|"$//g;
94 6         19 return $s;
95             }
96              
97             1;
98             __END__