germania-kg/jsonapi-client

There is no license information available for the latest version (0.1.2) of this package.

Convenience wrapper for simple retrievals from Germania's JSON APIs with Cache support

0.1.2 2022-05-30 14:06 UTC

This package is auto-updated.

Last update: 2024-10-29 05:59:52 UTC


README

Germania KG · JsonAPI Client

Server-side PHP wrapper for simple retrievals from Germania's JSON APIs with Cache support.

Installation

$ composer require germania-kg/jsonapi-client

Usage

The Guzzle Factory

The JsonApiClient requires a Guzzle Client which will perform the API requests. You may either bring your own Guzzle instance or use the GuzzleFactory, which is useful for API endpoints that require a “bearer” Access token.

<?php
use Germania\JsonApiClient\GuzzleFactory;

// Have your Web API endpoint and Access token at hand
$api = "https://api.example.com/"
$token = "manymanyletters"; 

// Setup a Guzzle Client that will ask the Web API
$guzzle = (new GuzzleFactory)( $api, $token);

The JsonApiClient

The JsonApiClient requires the above Guzzle Client as well as a PSR-6 Cache ItemPool. It optionally accepts a PSR-3 Logger and/or a PSR-3 Loglevel name for errors.

<?php
use Germania\JsonApiClient\JsonApiClient;
use Germania\JsonApiClient\GuzzleFactory;
use GuzzleHttp\Client;

$guzzle = new Client( ... );
$guzzle = (new GuzzleFactory)( $api, $token);

$cache  = new \Stash\Pool( ... );
$logger = new \Monolog\Logger( ... );

$api_client = new JsonApiClient($guzzle, $cache );
$api_client = new JsonApiClient($guzzle, $cache, $logger );
$api_client = new JsonApiClient($guzzle, $cache, $logger, "alert" );

Customizing

Error loglevel: Loglevel name to use when Guzzle fails. Defaults to error.

$api_client->error_loglevel = "error";

Request method: This library is built for GET and is not intended or tested for POST, DELETE and such.

$api_client->request_method = "GET";

Cache life time: The cache lifetime will be taken from the API response and fallback to this value:

$api_client->cache_lifetime_default = 3600;  

Security considerations: The caching engine

Results are stored in the PSR-6 cache passed to the JsonApiClient constructor, using a cache key to look up the results next time.

This cache key contains a fast-to-compute sha256 hash of the authorization header. The downside is, your auth tokens are vulnerable to hash collision attacks, when two different string produce the same hash.

The auth token hopefully has a baked-in lifetime. Once this lifetime is reached, the auth token is worthless anyway. And, when an attacker has file access to your cache, he will have all results, regardless if he has your auth tokens or not.

Security tips:

  • Consider to pass an “Always-empty-cache” or one with very short lifetime, such as Stash's Ephemeral driver.
  • Store your cache securely. This is not responsibility of this library.
  • Clean your items cache often. This is not responsibility of this library.

Retrieve things

The JsonApiClient class is callable; invoking with a URL path and an optional filter values array returns an ArrayIterator with the documents provided by the API.

Caching: The results are cached in the given PSR-6 Cache Item Pool. The cache item TTL depends on the Cache-Control: max-age=SECONDS header that came along with the response to the Guzzle Client request. The default TTL is 3600 seconds.

$items = $downloads_client("some/url/path");

foreach( $items as $item):
	print_r( $item );
endforeach;

Example record

The print_r( $item ) could reveal something like this:

Array (
    [company] => ACME Corp.
    [brand] => ACME's Best
    [title] => ACME Super Thingy
    ...
)

Filtering results

To narrow down the results, both the all and latest methods accept an array with filter values. The fiter values may contain multiple values, separated with comma.

Think of the filter array items as WHERE … AND… clauses, and comma-separated values as 'a' OR 'b'

$filters = array(
  'company' => "ACME",
  'category' => "brochure",
  'language' => "en"
);

$items = $downloads_client("some/url/path", $filters);

Errors and Exceptions

Any error or exception during the ask-cache / request / response / results-building phases will first be logged to the PSR-3 Logger passed to the constrcutor. The error caught will be re-thrown as JsonApiClientExceptionInterface exception instances.

<?php
use Germania\JsonApiClient\JsonApiClientExceptionInterface;

use Germania\JsonApiClient\{
  JsonApiClientCacheException,
  JsonApiClientRequestException,
  JsonApiClientResponseException,
  JsonApiClientResultsException
};

Cache problems

Before the request is actually sent, the Cache ItemPool will be asked. In case of any error, a JsonApiClientCacheException will be thrown This class implements JsonApiClientExceptionInterface and extends \RuntimeException.

Request problems

When the JsonApiClient catches a Guzzle RequestException or TransferExceptions, i.e. something wrong with the request or on the server, a JsonApiClientRequestException will be thrown. This class implements JsonApiClientExceptionInterface and extends \RuntimeException.

Response problems

The response is expected to be a valid JsonAPI response. Whenever the response can't be decoded to a useful array, a JsonApiClientResponseException will be thrown. This class implements JsonApiClientExceptionInterface and extends \UnexpectedValueException.

Result building problems

When there's a problem building the result array, or writing to the cache, a JsonApiClientResultsException will be thrown. This class implements JsonApiClientExceptionInterface and extends \RuntimeException.

Development and Unit tests

$ git clone https://github.com/GermaniaKG/jsonapi-client-php.git
$ cd jsonapi-client-php
$ composer install

Unit tests

Copy phpunit.xml.dist to phpunit.xml and adapt the API_BASE_URL and AUTH_TOKEN environment variables. Then run PhpUnit like this:

$ composer test
# or
$ vendor/bin/phpunit