Skip to content

Commit

Permalink
UHF-9239: Make ApiClient non-abstract
Browse files Browse the repository at this point in the history
  • Loading branch information
hyrsky committed Jan 15, 2024
1 parent 67f190e commit 3d201cd
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 142 deletions.
63 changes: 24 additions & 39 deletions documentation/api-client.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# API client

Base service for HTTP JSON APIs.
Service for HTTP JSON APIs.

Features:
- Simple caching.
Expand All @@ -9,57 +9,42 @@ Features:

## Usage

Extend `\Drupal\helfi_api_base\ApiClient\ApiClient`. Requests are made in the callbacks of `cache()` method.

```php
namespace Drupal\my_module;

use Drupal\helfi_api_base\ApiClient\ApiClient;
use Drupal\helfi_api_base\ApiClient\CacheValue;

class MyApi extends ApiClient {

const TTL = 180;

public function getFoo(string $id) {
return $this->cache($id, fn () => new CacheValue(
$this->makeRequest('GET', 'https://example.com/api/v1/foo'),
$this->time->getRequestTime() + self::TTL,
['user:1']
))->response;
}

}
```

### Service

Extend your service from the abstract service `helfi_api_base.api_client_base`. You must provide your own logger. Optionally you can provide default request parameters and headers.
Create your own client service from abstract service `helfi_api_base.api_client_base`. You must provide your own logger. Optionally you can provide default request parameters.

```yaml
# my_module.services.yml
my_module.my_api:
parent: helfi_api_base.api_manager
class: Drupal\my_module\MyApi
arguments:
- '@logger.channel.my_module'
# Optional:
- { timeout: 30 }
```
### Mocking
*Warning*: The client fail any further requests instantly after one failed requests. This is to prevent blocking the rendering process and cause the site to time-out. You should not share the client for different purposes that need fault tolerance.
In local environment, the `makeRequestWithFixture` method returns response from JSON file if the response fails.
Actual requests are usually made in the callback of `cache()` method. The callback must return `CacheValue`.

```php
class MyApi extends ApiClientBase {
use Drupal\helfi_api_base\ApiClient\CacheValue;
/** @var Drupal\helfi_api_base\ApiClient\ApiClient $client */
$client = \Drupal::service('my_module.my_api');
$response = $client->cache($id, fn () => new CacheValue(
// Actual HTTP response.
$client->makeRequest('GET', 'https://example.com/api/v1/foo'),
// TTL.
$client->cacheMaxAge(ttl: 180),
// Custom cache tags.
['user:1']
));
```

public function getFoo(string $id) {
return $this->cache($id, fn () => new CacheValue(
$this->makeRequestWithFixture('path-to-fixture.json', 'GET', 'https://example.com/fail'),
$this->time->getRequestTime() + self::TTL,
['user:1']
))->response;
}
### Mocking

}
In local environment, the `makeRequestWithFixture` method returns response from JSON file if the response fails.

```php
$client->makeRequestWithFixture('path-to-fixture.json', 'GET', 'https://example.com/fails-in-local'),
```
2 changes: 1 addition & 1 deletion helfi_api_base.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ services:
- '@database'

helfi_api_base.api_client_base:
class: Drupal\helfi_api_base\ApiClient\ApiClientBase
class: Drupal\helfi_api_base\ApiClient\ApiClient
abstract: true
arguments:
- '@http_client'
Expand Down
75 changes: 42 additions & 33 deletions src/ApiClient/ApiClientBase.php → src/ApiClient/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\helfi_api_base\Cache\CacheKeyTrait;
use Drupal\helfi_api_base\Environment\EnvironmentResolverInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ClientException;
Expand All @@ -17,13 +16,11 @@
use Psr\Log\LoggerInterface;

/**
* Base class for services that fetch data from HTTP API.
* Fetch data from HTTP API.
*
* Provides caching and fixtures (for local environment).
* Provides simple caching and fixtures (for local environment).
*/
abstract class ApiClientBase {

use CacheKeyTrait;
class ApiClient {

/**
* Whether to bypass cache or not.
Expand Down Expand Up @@ -119,7 +116,7 @@ protected function getRequestOptions(string $environmentName, array $options = [
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function makeRequest(
public function makeRequest(
string $method,
string $url,
array $options = [],
Expand All @@ -130,7 +127,6 @@ protected function makeRequest(
/**
* Makes HTTP request with fixture.
*
*
* @param string $fixture
* File for mock data if requests fail in local environment.
* @param string $method
Expand All @@ -145,7 +141,7 @@ protected function makeRequest(
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function makeRequestWithFixture(
public function makeRequestWithFixture(
string $fixture,
string $method,
string $url,
Expand All @@ -154,29 +150,29 @@ protected function makeRequestWithFixture(
return $this->makeRequestInternal($fixture, $method, $url, $options);
}

/**
* Makes the HTTP request.
*
* @param string|NULL $fixture
* Fixture file or NULL if disabled.
* @param string $method
* Request method.
* @param string $url
* The endpoint in the instance.
* @param array $options
* Body for requests.
*
* @return \Drupal\helfi_api_base\ApiClient\ApiResponse
* The JSON object.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function makeRequestInternal(
string|NULL $fixture,
string $method,
string $url,
array $options,
): ApiResponse {
/**
* Makes the HTTP request.
*
* @param string|null $fixture
* Fixture file or NULL if disabled.
* @param string $method
* Request method.
* @param string $url
* The endpoint in the instance.
* @param array $options
* Body for requests.
*
* @return \Drupal\helfi_api_base\ApiClient\ApiResponse
* The JSON object.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function makeRequestInternal(
?string $fixture,
string $method,
string $url,
array $options,
): ApiResponse {

$activeEnvironmentName = $this->environmentResolver
->getActiveEnvironment()
Expand Down Expand Up @@ -232,7 +228,7 @@ private function makeRequestInternal(
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function cache(string $key, callable $callback) : ?CacheValue {
public function cache(string $key, callable $callback) : ?CacheValue {
$exception = new TransferException();
$value = ($cache = $this->cache->get($key)) ? $cache->data : NULL;

Expand Down Expand Up @@ -266,4 +262,17 @@ protected function cache(string $key, callable $callback) : ?CacheValue {
throw $exception;
}

/**
* Helper method for calculating cache max age.
*
* @param int $ttl
* Time to live in seconds.
*
* @return int
* Expires timestamp.
*/
public function cacheMaxAge(int $ttl): int {
return $this->time->getRequestTime() + $ttl;
}

}

This file was deleted.

43 changes: 0 additions & 43 deletions tests/modules/helfi_api_client_test/src/ApiClient.php

This file was deleted.

Loading

0 comments on commit 3d201cd

Please sign in to comment.