Apertur-SDK
view release on metacpan or search on metacpan
$server_key->{publicKey},
filename => 'photo.jpg',
mimeType => 'image/jpeg',
);
print "Uploaded: $image->{id}\n";
```
## Error Handling
All API errors throw typed exceptions that inherit from `Apertur::SDK::Error`. Catch the specific subclass you care about, or catch the base class as a fallback. See [Error Handling documentation](https://docs.apertur.ca/errors).
```perl
use Apertur::SDK;
use Apertur::SDK::Error;
use Apertur::SDK::Error::Authentication;
use Apertur::SDK::Error::NotFound;
use Apertur::SDK::Error::RateLimit;
use Apertur::SDK::Error::Validation;
my $client = Apertur::SDK->new(api_key => 'aptr_live_...');
lib/Apertur/SDK.pm view on Meta::CPAN
sandbox environment.
# API key
my $client = Apertur::SDK->new(api_key => 'aptr_live_...');
# OAuth token
my $client = Apertur::SDK->new(oauth_token => $access_token);
=head1 ERROR HANDLING
All API errors throw typed L<Apertur::SDK::Error> objects:
use Apertur::SDK;
use Apertur::SDK::Error::Authentication;
use Apertur::SDK::Error::NotFound;
use Apertur::SDK::Error::RateLimit;
use Apertur::SDK::Error::Validation;
eval {
my $session = $client->sessions->create(label => 'test');
};
lib/Apertur/SDK/Error.pm view on Meta::CPAN
sub new {
my ($class, %args) = @_;
return bless {
status_code => $args{status_code} // 0,
code => $args{code} // '',
message => $args{message} // 'Unknown error',
}, $class;
}
sub throw {
my ($class, %args) = @_;
die $class->new(%args);
}
sub status_code { return $_[0]->{status_code} }
sub code { return $_[0]->{code} }
sub message { return $_[0]->{message} }
sub _stringify {
my ($self) = @_;
lib/Apertur/SDK/Error.pm view on Meta::CPAN
=head1 NAME
Apertur::SDK::Error - Base exception class for Apertur API errors
=head1 SYNOPSIS
use Apertur::SDK::Error;
eval {
Apertur::SDK::Error->throw(
status_code => 500,
code => 'INTERNAL',
message => 'Something went wrong',
);
};
if (my $err = $@) {
if (ref $err && $err->isa('Apertur::SDK::Error')) {
warn "API error: " . $err->message;
}
}
=head1 DESCRIPTION
Base error class for all Apertur SDK errors. All API errors are represented
as blessed objects that can be thrown with C<die> and caught with C<eval>.
=head1 METHODS
=over 4
=item B<new(%args)>
Constructor. Accepted keys: C<status_code>, C<code>, C<message>.
=item B<throw(%args)>
Class method that creates and throws (via C<die>) a new error.
=item B<status_code>
Returns the HTTP status code.
=item B<code>
Returns the error code string (e.g. C<NOT_FOUND>).
=item B<message>
lib/Apertur/SDK/HTTPClient.pm view on Meta::CPAN
$body = decode_json($res->decoded_content);
};
if ($@) {
$body = { message => "HTTP $status" };
}
my $message = $body->{message} || "HTTP $status";
my $code = $body->{code};
if ($status == 401) {
Apertur::SDK::Error::Authentication->throw(message => $message);
}
elsif ($status == 404) {
Apertur::SDK::Error::NotFound->throw(message => $message);
}
elsif ($status == 429) {
my $retry_after = $res->header('Retry-After');
$retry_after = defined $retry_after ? int($retry_after) : undef;
Apertur::SDK::Error::RateLimit->throw(
message => $message,
retry_after => $retry_after,
);
}
elsif ($status == 400) {
Apertur::SDK::Error::Validation->throw(message => $message);
}
else {
Apertur::SDK::Error->throw(
status_code => $status,
code => $code,
message => $message,
);
}
}
1;
__END__
t/01_client.t view on Meta::CPAN
retry_after => 30,
);
isa_ok($rl, 'Apertur::SDK::Error');
is($rl->status_code, 429, 'rate limit status_code');
is($rl->retry_after, 30, 'rate limit retry_after');
my $val = Apertur::SDK::Error::Validation->new(message => 'Bad input');
isa_ok($val, 'Apertur::SDK::Error');
is($val->status_code, 400, 'validation status_code');
# Test throw mechanism
eval { Apertur::SDK::Error::NotFound->throw(message => 'Gone') };
my $caught = $@;
isa_ok($caught, 'Apertur::SDK::Error::NotFound');
is($caught->message, 'Gone', 'thrown error message');
};
# --- Signature verification ---
subtest 'Signature verification' => sub {
plan tests => 6;
use Apertur::SDK::Signature qw(
verify_webhook_signature
verify_event_signature
( run in 0.559 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )