| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Net::Amazon::S3::Response; | 
| 2 |  |  |  |  |  |  | # ABSTRACT: Behaviour common to most S3 responses. | 
| 3 |  |  |  |  |  |  | $Net::Amazon::S3::Response::VERSION = '0.99'; | 
| 4 | 99 |  |  | 99 |  | 798 | use Moose; | 
|  | 99 |  |  |  |  | 256 |  | 
|  | 99 |  |  |  |  | 864 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 99 |  |  | 99 |  | 679159 | use Carp (); | 
|  | 99 |  |  |  |  | 308 |  | 
|  | 99 |  |  |  |  | 2425 |  | 
| 7 | 99 |  |  | 99 |  | 74252 | use XML::LibXML; | 
|  | 99 |  |  |  |  | 3223368 |  | 
|  | 99 |  |  |  |  | 781 |  | 
| 8 | 99 |  |  | 99 |  | 17136 | use XML::LibXML::XPathContext; | 
|  | 99 |  |  |  |  | 269 |  | 
|  | 99 |  |  |  |  | 2436 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 99 |  |  | 99 |  | 620 | use Net::Amazon::S3::Constants; | 
|  | 99 |  |  |  |  | 258 |  | 
|  | 99 |  |  |  |  | 2226 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 | 99 |  |  | 99 |  | 630 | use namespace::clean; | 
|  | 99 |  |  |  |  | 241 |  | 
|  | 99 |  |  |  |  | 1055 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | has http_response => ( | 
| 15 |  |  |  |  |  |  | is => 'ro', | 
| 16 |  |  |  |  |  |  | required => 1, | 
| 17 |  |  |  |  |  |  | handles => [ | 
| 18 |  |  |  |  |  |  | qw[ code ], | 
| 19 |  |  |  |  |  |  | qw[ message ], | 
| 20 |  |  |  |  |  |  | qw[ is_success ], | 
| 21 |  |  |  |  |  |  | qw[ is_redirect ], | 
| 22 |  |  |  |  |  |  | qw[ status_line ], | 
| 23 |  |  |  |  |  |  | qw[ content ], | 
| 24 |  |  |  |  |  |  | qw[ decoded_content ], | 
| 25 |  |  |  |  |  |  | qw[ header ], | 
| 26 |  |  |  |  |  |  | qw[ headers ], | 
| 27 |  |  |  |  |  |  | qw[ header_field_names ], | 
| 28 |  |  |  |  |  |  | ], | 
| 29 |  |  |  |  |  |  | ); | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | has xml_document => ( | 
| 32 |  |  |  |  |  |  | is          => 'ro', | 
| 33 |  |  |  |  |  |  | init_arg    => undef, | 
| 34 |  |  |  |  |  |  | lazy        => 1, | 
| 35 |  |  |  |  |  |  | builder     => '_build_xml_document', | 
| 36 |  |  |  |  |  |  | ); | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | has xpath_context => ( | 
| 39 |  |  |  |  |  |  | is          => 'ro', | 
| 40 |  |  |  |  |  |  | init_arg    => undef, | 
| 41 |  |  |  |  |  |  | lazy        => 1, | 
| 42 |  |  |  |  |  |  | builder     => '_build_xpath_context', | 
| 43 |  |  |  |  |  |  | ); | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | has error_code => ( | 
| 46 |  |  |  |  |  |  | is          => 'ro', | 
| 47 |  |  |  |  |  |  | init_arg    => undef, | 
| 48 |  |  |  |  |  |  | lazy        => 1, | 
| 49 |  |  |  |  |  |  | builder     => '_build_error_code', | 
| 50 |  |  |  |  |  |  | ); | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | has error_message => ( | 
| 53 |  |  |  |  |  |  | is          => 'ro', | 
| 54 |  |  |  |  |  |  | init_arg    => undef, | 
| 55 |  |  |  |  |  |  | lazy        => 1, | 
| 56 |  |  |  |  |  |  | builder     => '_build_error_message', | 
| 57 |  |  |  |  |  |  | ); | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | has error_resource => ( | 
| 60 |  |  |  |  |  |  | is          => 'ro', | 
| 61 |  |  |  |  |  |  | init_arg    => undef, | 
| 62 |  |  |  |  |  |  | lazy        => 1, | 
| 63 |  |  |  |  |  |  | builder     => '_build_error_resource', | 
| 64 |  |  |  |  |  |  | ); | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | has error_request_id => ( | 
| 67 |  |  |  |  |  |  | is          => 'ro', | 
| 68 |  |  |  |  |  |  | init_arg    => undef, | 
| 69 |  |  |  |  |  |  | lazy        => 1, | 
| 70 |  |  |  |  |  |  | builder     => '_build_error_request_id', | 
| 71 |  |  |  |  |  |  | ); | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | has _data => ( | 
| 74 |  |  |  |  |  |  | is          => 'ro', | 
| 75 |  |  |  |  |  |  | init_arg    => undef, | 
| 76 |  |  |  |  |  |  | lazy        => 1, | 
| 77 |  |  |  |  |  |  | builder     => '_build_data', | 
| 78 |  |  |  |  |  |  | ); | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | sub _parse_data; | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | sub connection { | 
| 83 | 0 |  |  | 0 | 1 | 0 | return $_[0]->header ('Connection'); | 
| 84 |  |  |  |  |  |  | } | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | sub content_length { | 
| 87 | 3 |  | 100 | 3 | 1 | 121 | return $_[0]->http_response->content_length || 0; | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | sub content_type { | 
| 91 | 209 |  |  | 209 | 1 | 6191 | return $_[0]->http_response->content_type; | 
| 92 |  |  |  |  |  |  | } | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | sub date { | 
| 95 | 0 |  |  | 0 | 0 | 0 | return $_[0]->header ('Date'); | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | sub etag { | 
| 99 | 4 |  |  | 4 | 1 | 9302 | return $_[0]->_decode_etag ($_[0]->header ('ETag')); | 
| 100 |  |  |  |  |  |  | } | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | sub server { | 
| 103 | 1 |  |  | 1 | 1 | 178 | return $_[0]->header ('Server'); | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | sub delete_marker { | 
| 107 | 1 |  |  | 1 | 1 | 227 | return $_[0]->header (Net::Amazon::S3::Constants::HEADER_DELETE_MARKER); | 
| 108 |  |  |  |  |  |  | } | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | sub id_2 { | 
| 111 | 1 |  |  | 1 | 1 | 241 | return $_[0]->header (Net::Amazon::S3::Constants::HEADER_ID_2); | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | sub request_id { | 
| 115 | 2 |  |  | 2 | 1 | 227 | return $_[0]->header (Net::Amazon::S3::Constants::HEADER_REQUEST_ID); | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | sub version_id { | 
| 119 | 1 |  |  | 1 | 1 | 222 | return $_[0]->header (Net::Amazon::S3::Constants::HEADER_VERSION_ID); | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | sub is_xml_content { | 
| 123 | 206 |  |  | 206 | 1 | 16560 | my ($self) = @_; | 
| 124 |  |  |  |  |  |  |  | 
| 125 | 206 |  | 100 |  |  | 970 | return $self->content_type =~ m:[/+]xml\b: && $self->decoded_content; | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | sub is_error { | 
| 129 | 434 |  |  | 434 | 1 | 10400 | my ($self) = @_; | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 434 | 100 |  |  |  | 13190 | return 1 if $self->http_response->is_error; | 
| 132 | 91 | 50 |  |  |  | 1395 | return 1 if $self->findvalue ('/Error'); | 
| 133 | 91 |  |  |  |  | 5383 | return; | 
| 134 |  |  |  |  |  |  | } | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | sub is_internal_response { | 
| 137 | 3 |  |  | 3 | 1 | 1794 | my ($self) = @_; | 
| 138 |  |  |  |  |  |  |  | 
| 139 | 3 |  |  |  |  | 16 | my $header = $self->header ('Client-Warning'); | 
| 140 | 3 |  | 66 |  |  | 312 | return !! ($header && $header eq 'Internal response'); | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | sub findvalue { | 
| 144 | 239 |  |  | 239 | 0 | 757 | my ($self, @path) = @_; | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 239 | 100 |  |  |  | 7124 | return '' unless $self->xpath_context; | 
| 147 | 187 |  |  |  |  | 5300 | $self->xpath_context->findvalue (@path); | 
| 148 |  |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | sub findnodes { | 
| 151 | 0 |  |  | 0 | 0 | 0 | my ($self, @path) = @_; | 
| 152 |  |  |  |  |  |  |  | 
| 153 | 0 | 0 |  |  |  | 0 | return unless $self->xpath_context; | 
| 154 | 0 |  |  |  |  | 0 | $self->xpath_context->findnodes (@path); | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | sub _build_data { | 
| 158 | 14 |  |  | 14 |  | 38 | my ($self) = @_; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 14 | 50 |  |  |  | 62 | return $self->is_success | 
| 161 |  |  |  |  |  |  | ? $self->_parse_data | 
| 162 |  |  |  |  |  |  | : undef | 
| 163 |  |  |  |  |  |  | ; | 
| 164 |  |  |  |  |  |  | } | 
| 165 |  |  |  |  |  |  | sub _build_error_code { | 
| 166 | 111 |  |  | 111 |  | 325 | my ($self) = @_; | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | return | 
| 169 | 111 | 50 |  |  |  | 360 | unless $self->is_error; | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 111 | 100 |  |  |  | 4121 | return $self->http_response->code | 
| 172 |  |  |  |  |  |  | unless $self->xpath_context; | 
| 173 |  |  |  |  |  |  |  | 
| 174 | 77 |  |  |  |  | 377 | return $self->findvalue ('/Error/Code'); | 
| 175 |  |  |  |  |  |  | } | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | sub _build_error_message { | 
| 178 | 101 |  |  | 101 |  | 281 | my ($self) = @_; | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | return | 
| 181 | 101 | 50 |  |  |  | 442 | unless $self->is_error; | 
| 182 |  |  |  |  |  |  |  | 
| 183 | 101 | 100 |  |  |  | 3790 | return $self->http_response->message | 
| 184 |  |  |  |  |  |  | unless $self->xpath_context; | 
| 185 |  |  |  |  |  |  |  | 
| 186 | 69 |  |  |  |  | 340 | return $self->findvalue ('/Error/Message'); | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | sub _build_error_resource { | 
| 190 | 2 |  |  | 2 |  | 6 | my ($self) = @_; | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | return | 
| 193 | 2 | 50 |  |  |  | 5 | unless $self->is_error; | 
| 194 |  |  |  |  |  |  |  | 
| 195 | 2 | 100 |  |  |  | 108 | return "${\ $self->http_response->request->uri }" | 
|  | 1 |  |  |  |  | 31 |  | 
| 196 |  |  |  |  |  |  | unless $self->xpath_context; | 
| 197 |  |  |  |  |  |  |  | 
| 198 | 1 |  |  |  |  | 4 | return $self->findvalue ('/Error/Resource'); | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | sub _build_error_request_id { | 
| 202 | 2 |  |  | 2 |  | 5 | my ($self) = @_; | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | return | 
| 205 | 2 | 50 |  |  |  | 6 | unless $self->is_error; | 
| 206 |  |  |  |  |  |  |  | 
| 207 | 2 | 100 |  |  |  | 73 | return $self->request_id | 
| 208 |  |  |  |  |  |  | unless $self->xpath_context; | 
| 209 |  |  |  |  |  |  |  | 
| 210 | 1 |  |  |  |  | 3 | return $self->findvalue ('/Error/RequestId'); | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | sub _build_xml_document { | 
| 214 | 201 |  |  | 201 |  | 536 | my ($self) = @_; | 
| 215 |  |  |  |  |  |  |  | 
| 216 | 201 | 100 |  |  |  | 864 | return unless $self->is_xml_content; | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  | # TODO: A 200 OK response can contain valid or invalid XML | 
| 219 | 115 |  |  |  |  | 113050 | return XML::LibXML->new->parse_string ($self->http_response->decoded_content); | 
| 220 |  |  |  |  |  |  | } | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | sub _build_xpath_context { | 
| 223 | 201 |  |  | 201 |  | 542 | my ($self) = @_; | 
| 224 |  |  |  |  |  |  |  | 
| 225 | 201 |  |  |  |  | 6239 | my $doc = $self->xml_document; | 
| 226 | 201 | 100 |  |  |  | 5055 | return unless $doc; | 
| 227 |  |  |  |  |  |  |  | 
| 228 | 115 |  |  |  |  | 4816 | my $xpc = XML::LibXML::XPathContext->new ($doc); | 
| 229 |  |  |  |  |  |  |  | 
| 230 | 115 |  | 100 |  |  | 2217 | my $s3_ns = $doc->documentElement->lookupNamespaceURI | 
| 231 |  |  |  |  |  |  | || 'http://s3.amazonaws.com/doc/2006-03-01/'; | 
| 232 | 115 |  |  |  |  | 647 | $xpc->registerNs (s3 => $s3_ns); | 
| 233 |  |  |  |  |  |  |  | 
| 234 | 115 |  |  |  |  | 8085 | return $xpc; | 
| 235 |  |  |  |  |  |  | } | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | sub _decode_etag { | 
| 238 | 4 |  |  | 4 |  | 291 | my ($self, $etag) = @_; | 
| 239 |  |  |  |  |  |  |  | 
| 240 | 4 |  |  |  |  | 25 | $etag =~ s/ (?:^") | (?:"$) //gx; | 
| 241 | 4 |  |  |  |  | 28 | return $etag; | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | 1; | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | __END__ | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | =pod | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | =encoding utf-8 | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | =head1 NAME | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | Net::Amazon::S3::Response - Behaviour common to most S3 responses. | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | =head1 VERSION | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | version 0.99 | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | package Command::Response; | 
| 263 |  |  |  |  |  |  | extends 'Net::Amazon::S3::Response'; | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | ... | 
| 266 |  |  |  |  |  |  | my $response = Command::Response->new ( | 
| 267 |  |  |  |  |  |  | http_response => $http_response, | 
| 268 |  |  |  |  |  |  | ); | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | Response handler base class providing functionality common to most S3 responses. | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | =head1 EXTENDING | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | L<Net::Amazon::S3::Response> provides methods to cache response data. | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | =over | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | =item _data | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | Read-only accessor initialized by C<_build_data> | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | =item _build_data | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | Data builder, by default calls C<_parse_data> if response is success and provides | 
| 287 |  |  |  |  |  |  | valid XML document. | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | =item _parse_data | 
| 290 |  |  |  |  |  |  |  | 
| 291 |  |  |  |  |  |  | Abstract (undefined in parent) method to be implemented by children. | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | =back | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | =head1 METHODS | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | =head2 Constructor | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  | Constructor accepts only one (required) parameter - C<http_response>. | 
| 300 |  |  |  |  |  |  | It should act like L<HTTP::Response>. | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | =head2 Response classification methods | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | =over | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | =item is_success | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | True if response is a success response, false otherwise. | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | Successful response may contain invalid XML. | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | =item is_redirect | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | True if response is a redirect. | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | =item is_error | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | True if response is an error response, false otherwise. | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | Response is considered to be an error either when response code is an HTTP | 
| 321 |  |  |  |  |  |  | error (4xx or 5xx) or response content is an error XML document. | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | See also L<"S3 Error Response"|https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html> | 
| 324 |  |  |  |  |  |  | for more details. | 
| 325 |  |  |  |  |  |  |  | 
| 326 |  |  |  |  |  |  | =item is_internal_response | 
| 327 |  |  |  |  |  |  |  | 
| 328 |  |  |  |  |  |  | True if response is generated by user agent itself (eg: Cannot connect) | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | =item is_xml_content | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | True if response data is a valid XML document | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | =back | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | =head2 Error handling | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | Apart error classifition L<Net::Amazon::S3::Response> provides also common | 
| 339 |  |  |  |  |  |  | error data accessors. | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | Error data are available only in case of error response. | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | =over | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | =item error_code | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | Either content of C<Error/Code> XML element or HTTP response code. | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | =item error_message | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | Either content of C<Error/Message> XML element or HTTP response message. | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | =item error_request_id | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | Content of C<Error/RequestId> XML element if available, C<x-amz-request-id> header | 
| 356 |  |  |  |  |  |  | if available, empty list otherwise. | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | =item error_resource | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | Content of c<Error/Resource> if available, request uri otherwise. | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | =back | 
| 363 |  |  |  |  |  |  |  | 
| 364 |  |  |  |  |  |  | =head2 Common Response Headers | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | See L<"S3 Common Response Headers"|https://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html> | 
| 367 |  |  |  |  |  |  | for more details. | 
| 368 |  |  |  |  |  |  |  | 
| 369 |  |  |  |  |  |  | =over | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | =item content_length | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  | =item content_type | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | =item connection | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | =item etag | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | ETag with trimmed leading/trailing quotes. | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | =item server | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | =item delete_marker | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | =item request_id | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | =item id_2 | 
| 388 |  |  |  |  |  |  |  | 
| 389 |  |  |  |  |  |  | =item version_id | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | =back | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | =head2 XML Document parsing | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | =over | 
| 396 |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  | =item xml_document | 
| 398 |  |  |  |  |  |  |  | 
| 399 |  |  |  |  |  |  | Lazy built instance of L<XML::LibXML>. | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | Available only if response is XML response and contains valid XML document. | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | =item xpath_context | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | Lazy built instance of L<XML::LibXML::XPathContext>. | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | Available only if response is XML response and contains valid XML document | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | =back | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | =head2 HTTP Response methods | 
| 412 |  |  |  |  |  |  |  | 
| 413 |  |  |  |  |  |  | Further methods delegated to C<http_response>. | 
| 414 |  |  |  |  |  |  | Refer L<HTTP::Response> for description. | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | =over | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | =item code | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | =item message | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | =item status_line | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | =item content | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | =item decoded_content | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | =item header | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | =item headers | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  | =item header_field_names | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | =back | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | =head1 AUTHOR | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | Branislav Zahradník <barney@cpan.org> | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | This module is part of L<Net::Amazon::S3>. | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | =head1 AUTHOR | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | Branislav Zahradník <barney@cpan.org> | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | This software is copyright (c) 2021 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník. | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | This is free software; you can redistribute it and/or modify it under | 
| 453 |  |  |  |  |  |  | the same terms as the Perl 5 programming language system itself. | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | =cut |