Skip Menu |

This queue is for tickets about the Furl-S3 CPAN distribution.

Report information
The Basics
Id: 123308
Status: new
Priority: 0/
Queue: Furl-S3

People
Owner: Nobody in particular
Requestors: DAKKAR [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.02
Fixed in: (no value)



Subject: non-S3 HTTP errors are not caught
Furl::S3 passes all unsuccessful responses to Furl::S3::Error. The latter tries to extract all information from the XML body of the S3 error responses. But there are many other error conditions that don't involve S3: timeouts, connection refused, DNS failures... This patch makes Furl::S3::Error handle such failures, instead of dieing with a libxml parsing error.
Subject: fix-http-error-handling.patch
diff --git c/lib/Furl/S3/Error.pm w/lib/Furl/S3/Error.pm index 16ce7d1..c4e5051 100644 --- c/lib/Furl/S3/Error.pm +++ w/lib/Furl/S3/Error.pm @@ -30,7 +30,8 @@ sub stringify { sub _parse_xml { my( $self, $xml ) = @_; - my $doc = XML::LibXML->new->parse_string( $xml ); + my $doc = eval { XML::LibXML->new->parse_string( $xml ) }; + return unless $doc; # parse failure, it's probably not an S3 error my $code = $doc->findvalue('/Error/Code'); my $message = $doc->findvalue('/Error/Message'); my $request_id = $doc->findvalue('/Error/RequestId'); diff --git c/t/03_error.t w/t/03_error.t new file mode 100644 index 0000000..097a854 --- /dev/null +++ w/t/03_error.t @@ -0,0 +1,78 @@ +#!perl +use strict; +use Test::More; +use Furl::S3::Error;; + +subtest 'can handle S3 errors' => sub { + my $err = eval { + Furl::S3::Error->new({ + 'code' => 403, + 'msg' => 'Forbidden', + 'headers' => { + 'content-type' => 'application/xml', + 'date' => 'Mon, 16 Oct 2017 11:11:17 GMT', + 'transfer-encoding' => 'chunked', + 'server' => 'AmazonS3', + }, + 'ver' => 1, + 'body' => <<'ENDBODY', +<?xml version="1.0" encoding="UTF-8"?> +<Error> + <Code>AllAccessDisabled</Code> + <Message>All access to this object has been disabled</Message> + <RequestId>myrequest</RequestId> + <HostId>myhost</HostId> +</Error> +ENDBODY + }); + }; + ok($err, 'it should live') or diag $@; + is( + $err->code, + 'AllAccessDisabled', + 'code should be extracted', + ); + is( + $err->message, + 'All access to this object has been disabled', + 'message should be extracted', + ); + is( + $err->request_id, + 'myrequest', + 'request_id should be extracted', + ); + is( + $err->host_id, + 'myhost', + 'host_id should be extracted', + ); +}; + +subtest 'it can handle HTTP errors' => sub { + my $err = eval { + Furl::S3::Error->new({ + 'code' => 500, + 'msg' => 'Internal Response: Cannot resolve host name: blahblah.localhost (port: 80), Connection timed out at lib/Furl/S3.pm line 217', + 'body' => 'Cannot resolve host name: blahblah.localhost (port: 80), Connection timed out at lib/Furl/S3.pm line 217', + 'headers' => [ + 'Content-Length' => 105, + 'X-Internal-Response' => 1, + ], + 'ver' => 0, + }); + }; + ok($err, 'it should live') or diag $@; + is( + $err->http_code, + 500, + 'http_code should be extracted', + ); + like( + $err->http_status, + qr{Cannot resolve}, + 'http_status should be extracted', + ); +}; + +done_testing;