Skip to content

Commit

Permalink
Merge pull request #2 from mops1k/1.0.0
Browse files Browse the repository at this point in the history
1.0.0
  • Loading branch information
mops1k authored Dec 3, 2023
2 parents 7504025 + d9884a0 commit db786a6
Show file tree
Hide file tree
Showing 91 changed files with 1,208 additions and 2,592 deletions.
8 changes: 8 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
./tests export-ignore
./ecs.php export-ignore
./phpunit.xml.dist export-ignore
./phpstan.neon export-ignore
./phpstan-baseline.neon export-ignore
./.gitignore export-ignore
./doc export-ignore
./Readme.md export-ignore
6 changes: 3 additions & 3 deletions .github/workflows/bundle-tests-higher-deps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ jobs:
# To automatically get bug fixes and new Php versions for shivammathur/setup-php,
# change this to (see https://github.com/shivammathur/setup-php#bookmark-versioning):
# uses: shivammathur/setup-php@v2
- uses: shivammathur/setup-php@2cb9b829437ee246e9b3cac53555a39208ca6d28
- uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
php-version: '8.1'
- uses: actions/checkout@v2
- name: Cache Composer packages
id: composer-cache
Expand All @@ -26,7 +26,7 @@ jobs:
restore-keys: |
${{ runner.os }}-php-
- name: Install Dependencies
run: composer update -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
run: composer update --no-progress --prefer-dist
- name: Execute phpstan checks
run: vendor/bin/phpstan --memory-limit=-1 --no-progress
- name: Execute ecs checks
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/bundle-tests-lower-deps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ jobs:
# To automatically get bug fixes and new Php versions for shivammathur/setup-php,
# change this to (see https://github.com/shivammathur/setup-php#bookmark-versioning):
# uses: shivammathur/setup-php@v2
- uses: shivammathur/setup-php@2cb9b829437ee246e9b3cac53555a39208ca6d28
- uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
php-version: '8.1'
- uses: actions/checkout@v2
- name: Cache Composer packages
id: composer-cache
Expand All @@ -26,7 +26,7 @@ jobs:
restore-keys: |
${{ runner.os }}-php-
- name: Install Dependencies
run: composer update -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-lowest
run: composer update --no-progress --prefer-lowest
- name: Execute phpstan checks
run: vendor/bin/phpstan --memory-limit=-1 --no-progress
- name: Execute ecs checks
Expand Down
139 changes: 8 additions & 131 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,131 +1,8 @@
# ApiClientBundle
Symfony библиотека, позволяющая выполнять запросы к сторонним REST-API ресурсам посредством создания конфигурации и
отдельно предварительных конфигураций для различных эндпоинтов. Позволяет выполнив запрос получить десериализованный в
объект ответ от апи.

## Установка
```bash
composer require mops1k/api-client-bundle
```

## Использование

### Команды make
Библиотека поддерживает генерацию базовых классов с помощью использования `symfony/maker-bundle`.

На данный момент в проекте 2 команды генерации:
1. `bin/console make:api:client` - эта команда создаст класс конфигурации клиента, во время выполнения команды
будут заданы вопросы, на которые необходимо ответить для генерации класса конфигурации клиента.
2. `bin/console make:api:query` - эту команду надо выполнять только после того, как у вас уже есть хотя бы 1
конфигурация клиента. Она выполняет генерацию Query, Response и ErrorResponse(если необходимо) классов, которые уже
отвечают за выполнение запроса к конкретному эндпоинту стороннего api. Во время выполнения команды, также будут заданы
уточняющие вопросы, необходимые для генерации необходимых классов.

### Ручная конфигурация клиента

Как пример возьмём вымышленный эндпоинт `https://example.com/api/status`, который присылает ответ:

```json
{
"status": true
}
```

1. Создадим класс-клиент:

```php
<?php

use ApiClientBundle\Model\AbstractClientConfiguration;

class ExampleClient extends AbstractClientConfiguration
{
public function domain(): string
{
return 'example.com';
}

public function scheme(): string
{
return self::SCHEME_SSL;
}

public function isAsync(): bool
{
return false;
}
}
```

2. Создадим класс конфигуратор запроса:

```php
<?php

use ApiClientBundle\Interfaces\ClientConfigurationInterface;
use ApiClientBundle\Model\AbstractQuery;
use ApiClientBundle\Model\GenericErrorResponse;use Symfony\Component\HttpFoundation\Request;

class StatusQuery extends AbstractQuery
{
public function method(): string
{
return Request::METHOD_GET;
}

public function path(): string
{
return '/api/status';
}

public function support(ClientConfigurationInterface $clientConfiguration): bool
{
return $clientConfiguration instanceof ExampleClient;
}

public function responseClassName(): string
{
return StatusResponse::class;
}

public function errorResponseClassName(): string
{
return GenericErrorResponse::class;
}
}
```

3. Создадим класс DTO ответа:
```php
<?php

use ApiClientBundle\Model\AbstractResponse;

class StatusResponse extends AbstractResponse
{
protected bool $status;

public function getStatus(): bool
{
return $this->status;
}
}
```

На этом конфигурация клиента и запроса завершена!

Чтобы выполнить запрос, достаточно вызвать такой код:

```php
<?php

use ApiClientBundle\Service\ApiClientFactory;

// получаем ApiClientFactory через DI

/** @var ApiClientFactory $apiClientFactory */
$client = $apiClientFactory->use(ExampleClient::class);
$response = $client->request(new StatusQuery());

$response->getStatus();
```
# Api-Client-Bundle
This bundle provides abstraction layer for http clients through [php-http](https://docs.php-http.org/en/latest/index.html).
You can use this bundle for making your services request easier and flexible.

## Instructions
1. [Installation](./doc/Installation.md)
2. [Usage](./doc/Usage.md)
3. [Plugins](./doc/Plugins.md)
55 changes: 35 additions & 20 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,42 @@
"description": "Client for making work with any api more easy",
"type": "symfony-bundle",
"require": {
"php": "~8.0.0",
"php": ">=8.1.0",
"composer-runtime-api": "^2.1.0",
"ocramius/proxy-manager": "^2.13",
"php-http/client-implementation": "*",
"php-http/discovery": "^1.0",
"php-http/httplug": "^2.0",
"php-http/multipart-stream-builder": "^1.3",
"phpdocumentor/reflection-docblock": "^5.3",
"symfony/framework-bundle": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/mime": "^5.4|^6.0",
"symfony/serializer": "^5.4|^6.0",
"symfony/yaml": "^5.4|^6.0"
"psr/http-client-implementation": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0",
"symfony/event-dispatcher": "*",
"symfony/framework-bundle": "^6.3",
"symfony/mime": "^6.3",
"symfony/serializer": "^6.3"
},
"require-dev": {
"doctrine/annotations": "^1.13",
"phpdocumentor/type-resolver": "^1.6",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"phpunit/phpunit": "^9.5",
"doctrine/annotations": "^2.0",
"guzzlehttp/psr7": "^2.6",
"php-http/guzzle7-adapter": "^1.0",
"php-http/message": "^1.0",
"php-http/mock-client": "^1.0",
"phpdocumentor/type-resolver": "^1.7",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan": "^1.10",
"phpstan/phpstan-beberlei-assert": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.3",
"phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "^10.4",
"psr/cache-implementation": "2.0|3.0",
"roave/security-advisories": "dev-latest",
"symfony/config": "^5.4|^6.0",
"symfony/maker-bundle": "^1.37",
"symfony/property-access": "^5.4|^6.0",
"symfony/property-info": "^5.4|^6.0",
"symfony/var-exporter": "^5.4|^6.0",
"symplify/easy-coding-standard": "^11.1"
"symfony/config": "^6.3",
"symfony/property-access": "^6.3",
"symfony/property-info": "^6.3",
"symfony/var-exporter": "^6.3",
"symplify/easy-coding-standard": "^12.0"
},
"autoload": {
"psr-4": {
Expand All @@ -47,6 +58,10 @@
}
],
"config": {
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"php-http/discovery": true,
"phpstan/extension-installer": true
}
}
}
24 changes: 24 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use ApiClientBundle\HTTP\HttpClient;
use Http\Client\Common\Plugin\ErrorPlugin;
use Symfony\Component\Serializer\SerializerInterface;

return static function (ContainerConfigurator $container): void {
$services = $container->services();

$services->set(ErrorPlugin::class)
->arg('$config', [
'only_server_exception' => false,
])
->tag('api.http_client.plugin')
;

$services->set(HttpClient::class)
->arg('$serializer', service(SerializerInterface::class))
->arg('$plugins', tagged_iterator('api.http_client.plugin'))
->public()
;
};
7 changes: 7 additions & 0 deletions doc/Installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Installation

1. Install bundle through composer:
```bash
composer require mops1k/request-object-resolver-bundle
```
2. Install client or adapter. Follow [php-http documentation](https://docs.php-http.org/en/latest/httplug/users.html)
35 changes: 35 additions & 0 deletions doc/Plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Plugins

## Library has 3 ways to register plugins:

1. Global plugins:
To add global plugins you have to register service with tag `api.http_client.plugin`

2. Service and Query plugins:
To add service and query plugins you have to implement `getPlugins` method from interfaces and return array of Plugins.
Example:
```php
<?php
namespace App\Remote\Api;

use ApiClientBundle\Client\AbstractQuery;use Http\Client\Common\Plugin\AuthenticationPlugin;use Http\Client\Common\Plugin\RetryPlugin;

class MyQuery extends AbstractQuery
{
protected ?string $path = '/some-path'
protected string $format = 'json'; // Any format supported by symfony/serializer
protected string $service = MyService::class;
protected string $response = MyResponse::class;
protected array $plugins = [new RetryPlugin(['retries' => 3])];
}
```

## Plugin priority
Plugins from several places will overwrite in this ordering:
`Global plugins -> Service plugins -> Query plugins`
Scopes:
| Plugin | Scope | Note |
| :----- | :-----: | :---- |
| Global plugins | Global | Uses in all services and queries |
| Service plugins | Service | Uses in concrete service and his queries |
| Query plugins | Query | Uses in concrete query |
Loading

0 comments on commit db786a6

Please sign in to comment.