Apertur-SDK

 view release on metacpan or  search on metacpan

lib/Apertur/SDK/HTTPClient.pm  view on Meta::CPAN

        die $err if $err;
    }
    else {
        $res = $self->{ua}->request($req);
    }
    my $status = $res->code;

    if ($status >= 400) {
        $self->_handle_error($res);
    }

    if ($status == 204) {
        return undef;
    }

    return decode_json($res->decoded_content);
}

sub request_raw {
    my ($self, $method, $path, %opts) = @_;

    my $url = $self->{base_url} . $path;
    my $headers = $opts{headers} || {};

    $headers->{'Authorization'} = $self->{auth_header}
        if $self->{auth_header};

    my $req = HTTP::Request->new(uc($method), $url);
    for my $key (keys %$headers) {
        $req->header($key => $headers->{$key});
    }

    my $res = $self->{ua}->request($req);
    my $status = $res->code;

    if ($status >= 400) {
        $self->_handle_error($res);
    }

    return $res->content;
}

sub _handle_error {
    my ($self, $res) = @_;
    my $status = $res->code;

    my $body = {};
    eval {
        $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__

=head1 NAME

Apertur::SDK::HTTPClient - HTTP wrapper for the Apertur API

=head1 SYNOPSIS

    use Apertur::SDK::HTTPClient;

    my $http = Apertur::SDK::HTTPClient->new(
        base_url => 'https://api.aptr.ca',
        api_key  => 'aptr_live_...',
    );

    my $data = $http->request('GET', '/api/v1/stats');
    my $raw  = $http->request_raw('GET', '/api/v1/upload-sessions/uuid/qr');

=head1 DESCRIPTION

Low-level HTTP client used internally by all Apertur SDK resource classes.
Handles JSON serialisation, bearer token authentication, multipart uploads,
and maps HTTP error responses to typed exception objects.

=head1 METHODS

=over 4

=item B<new(%args)>

Constructor. Accepts C<base_url>, C<api_key>, and C<oauth_token>.

=item B<request($method, $path, %opts)>

Sends a JSON API request and returns the decoded response as a hashref
or arrayref. Returns C<undef> for 204 No Content responses.



( run in 2.337 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )