API::Client
HTTP API Thin-Client Abstraction
method: create method: delete method: dispatch method: fetch method: patch method: prepare method: process method: resource method: serialize method: update
package main;
use API::Client;
my $client = API::Client->new(url => 'https://httpbin.org');
# $client->resource('post');
# $client->update(json => {...});
Types::Standard
Data::Object::Role::Buildable Data::Object::Role::Stashable Data::Object::Role::Throwable
debug: ro, opt, Bool fatal: ro, opt, Bool logger: ro, opt, InstanceOf["FlightRecorder"] name: ro, opt, Str retries: ro, opt, Int timeout: ro, opt, Int url: ro, opt, InstanceOf["Mojo::URL"] user_agent: ro, opt, InstanceOf["Mojo::UserAgent"] version: ro, opt, Str
This package provides an abstraction and method for rapidly developing HTTP API clients. While this module can be used to interact with APIs directly, API::Client was designed to be consumed (subclassed) by higher-level purpose-specific API clients.
+=head1 THIN CLIENT
The thin API client library is advantageous as it has complete API coverage and can easily adapt to changes in the API with minimal effort. As a thin-client superclass, this module does not map specific HTTP requests to specific routines, nor does it provide parameter validation, pagination, or other conventions found in typical API client implementations; Instead, it simply provides a simple and consistent mechanism for dynamically generating HTTP requests. Additionally, this module has support for debugging and retrying API calls as well as throwing exceptions when 4xx and 5xx server response codes are returned.
Building up an HTTP request is extremely easy, simply call the "resource" to create a new object instance representing the API endpoint you wish to issue a request against.
# given: synopsis
my $resource = $client->resource('get');
# GET /get
my $get = $client->resource('get')->dispatch;
# HEAD /head
my $head = $client->resource('head')->dispatch(
method => 'head'
);
# PATCH /patch
my $patch = $client->resource('patch')->dispatch(
method => 'patch'
);
[$get, $head, $patch]
Because each call to "resource" returns a new object instance configured with a path (resource locator) based on the supplied parameters, reuse and request isolation are made simple, i.e., you will only need to configure the client once in your application.
# given: synopsis
# https://httpbin.org/users
my $users = $client->resource('users');
# https://httpbin.org/users/c09e91a
my $user = $client->resource('users', 'c09e91a');
# https://httpbin.org/users/c09e91a
my $new_user = $users->resource('c09e91a');
[$users, $user, $new_user]
This example illustrates how you might fetch an API resource.
# given: synopsis
my $tx1 = $client->resource('get')->fetch(
query => {active => 1}
);
# is equivalent to
my $tx2 = $client->resource('get')->dispatch(
method => 'get',
query => {active => 1}
);
[$tx1, $tx2]
This example illustrates how you might create a new API resource.
# given: synopsis
my $tx1 = $client->resource('post')->create(
json => {active => 1}
);
# is equivalent to
my $tx2 = $client->resource('post')->dispatch(
method => 'post',
json => {active => 1}
);
[$tx1, $tx2]
This example illustrates how you might update a new API resource.
# given: synopsis
my $tx1 = $client->resource('put')->update(
json => {active => 1}
);
# is equivalent to
my $tx2 = $client->resource('put')->dispatch(
method => 'put',
json => {active => 1}
);
[$tx1, $tx2]
This example illustrates how you might delete a new API resource.
# given: synopsis
my $tx1 = $client->resource('delete')->delete(
json => {active => 1}
);
# is equivalent to
my $tx2 = $client->resource('delete')->dispatch(
method => 'delete',
json => {active => 1}
);
[$tx1, $tx2]
An HTTP request is only issued when the "dispatch" method is called, directly or indirectly. Those calls return a Mojo::Transaction object which provides access to the request and response objects.
# given: synopsis
my $tx1 = $client->resource('patch')->patch(
json => {active => 1}
);
# is equivalent to
my $tx2 = $client->resource('patch')->dispatch(
method => 'patch',
json => {active => 1}
);
[$tx1, $tx2]
This package was designed to be subclassed and provides hooks into the client building and request dispatching processes. Specifically, there are three useful hooks (i.e. methods, which if present are used to build up the client object and requests), which are, the auth hook, which should return a Tuple[Str, Str] which is used to configure the basic auth header, the base hook which should return a Tuple[Str] which is used to configure the base URL, and the headers hook, which should return a ArrayRef[Tuple[Str, Str]] which are used to configure the HTTP request headers.
package Hookbin;
use Data::Object::Class;
extends 'API::Client';
sub auth {
['admin', 'secret']
}
sub headers {
[['Accept', '*/*']]
}
sub base {
['https://httpbin.org/get']
}
package main;
my $hookbin = Hookbin->new;
The dispatch method issues a request to the API resource represented by the object.
dispatch(Str :$method = 'get', Any %args) : InstanceOf["Mojo::Transaction"]
=example-1 dispatch
# given: synopsis
$client->resource('get')->dispatch;
=example-2 dispatch
# given: synopsis
$client->resource('post')->dispatch(
method => 'post', body => 'active=1'
);
=example-3 dispatch
# given: synopsis
$client->resource('get')->dispatch(
method => 'get', query => {active => 1}
);
=example-4 dispatch
# given: synopsis
$client->resource('post')->dispatch(
method => 'post', json => {active => 1}
);
=example-5 dispatch
# given: synopsis
$client->resource('post')->dispatch(
method => 'post', form => {active => 1}
);
=example-6 dispatch
# given: synopsis
$client->resource('put')->dispatch(
method => 'put', json => {active => 1}
);
=example-7 dispatch
# given: synopsis
$client->resource('patch')->dispatch(
method => 'patch', json => {active => 1}
);
=example-8 dispatch
# given: synopsis
$client->resource('delete')->dispatch(
method => 'delete', json => {active => 1}
);
The create method issues a POST request to the API resource represented by the object.
create(Any %args) : InstanceOf["Mojo::Transaction"]
=example-1 create
# given: synopsis
$client->resource('post')->create(
json => {active => 1}
);
The delete method issues a DELETE request to the API resource represented by the object.
delete(Any %args) : InstanceOf["Mojo::Transaction"]
=example-1 delete
# given: synopsis
$client->resource('delete')->delete;
The fetch method issues a GET request to the API resource represented by the object.
fetch(Any %args) : InstanceOf["Mojo::Transaction"]
=example-1 fetch
# given: synopsis
$client->resource('get')->fetch;
The patch method issues a PATCH request to the API resource represented by the object.
patch(Any %args) : InstanceOf["Mojo::Transaction"]
=example-1 patch
# given: synopsis
$client->resource('patch')->patch(
json => {active => 1}
);
The prepare method acts as a before hook triggered before each request where you can modify the transactor objects.
prepare(Object $ua, Object $tx, Any %args) : Object
=example-1 prepare
# given: synopsis
require Mojo::UserAgent;
require Mojo::Transaction::HTTP;
$client->prepare(
Mojo::UserAgent->new,
Mojo::Transaction::HTTP->new
);
The process method acts as an after hook triggered after each response where you can modify the transactor objects.
process(Object $ua, Object $tx, Any %args) : Object
=example-1 process
# given: synopsis
require Mojo::UserAgent;
require Mojo::Transaction::HTTP;
$client->process(
Mojo::UserAgent->new,
Mojo::Transaction::HTTP->new
);
The resource method returns a new instance of the object for the API resource endpoint specified.
resource(Str @segments) : Object
=example-1 resource
# given: synopsis
$client->resource('status', 200);
The serialize method serializes and returns the object as a hashref.
serialize() : HashRef
=example-1 serialize
# given: synopsis
$client->serialize;
The update method issues a PUT request to the API resource represented by the object.
update(Any %args) : InstanceOf["Mojo::Transaction"]
=example-1 update
# given: synopsis
$client->resource('put')->update(
json => {active => 1}
);
44 POD Errors
The following errors were encountered while parsing the POD:
- Around line 10:
Unknown directive: =name
- Around line 16:
Unknown directive: =abstract
- Around line 22:
Unknown directive: =includes
- Around line 37:
Unknown directive: =synopsis
- Around line 51:
Unknown directive: =libraries
- Around line 57:
Unknown directive: =integrates
- Around line 65:
Unknown directive: =attributes
- Around line 79:
Unknown directive: =description
- Around line 100:
Unknown directive: =scenario
- Around line 106:
Unknown directive: =example
- Around line 129:
Unknown directive: =scenario
- Around line 136:
Unknown directive: =example
- Around line 153:
Unknown directive: =scenario
- Around line 157:
Unknown directive: =example
- Around line 176:
Unknown directive: =scenario
- Around line 180:
Unknown directive: =example
- Around line 199:
Unknown directive: =scenario
- Around line 203:
Unknown directive: =example
- Around line 222:
Unknown directive: =scenario
- Around line 226:
Unknown directive: =example
- Around line 245:
Unknown directive: =scenario
- Around line 251:
Unknown directive: =example
- Around line 270:
Unknown directive: =scenario
- Around line 282:
Unknown directive: =example
- Around line 308:
Unknown directive: =method
- Around line 313:
Unknown directive: =signature
- Around line 381:
Unknown directive: =method
- Around line 386:
Unknown directive: =signature
- Around line 400:
Unknown directive: =method
- Around line 405:
Unknown directive: =signature
- Around line 417:
Unknown directive: =method
- Around line 422:
Unknown directive: =signature
- Around line 434:
Unknown directive: =method
- Around line 439:
Unknown directive: =signature
- Around line 453:
Unknown directive: =method
- Around line 458:
Unknown directive: =signature
- Around line 476:
Unknown directive: =method
- Around line 481:
Unknown directive: =signature
- Around line 499:
Unknown directive: =method
- Around line 504:
Unknown directive: =signature
- Around line 516:
Unknown directive: =method
- Around line 520:
Unknown directive: =signature
- Around line 532:
Unknown directive: =method
- Around line 537:
Unknown directive: =signature