proklung / symfony-guzzle-bundle
Symfony bundle for work with Guzzle.
Installs: 39
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: >=7.1 || ^8.0
- ext-dom: *
- ext-json: *
- doctrine/cache: ^1
- guzzlehttp/guzzle: ~6|~7
- psr/cache: ^1.0
- psr/simple-cache: ^1.0
- symfony/config: ^4.4 || ^5.0
- symfony/dependency-injection: ^4.4 || ^5.0
- symfony/filesystem: ^4.4 || ^5.0
- symfony/http-kernel: ^4.4 || ^5.0
- twig/twig: ~2 | ~3
Requires (Dev)
- icanhazstring/composer-unused: ^0.7.5
- proklung/phpunit-testing-tools: ^1.4.0
README
Форк пакета, доработано под личные нужды (добавлен адаптер для кэширования в Битриксе, и т.п).
Установка
composer require proklung/symfony-guzzle-bundle
Использование
Конфигурация
You may also enable the included logger, in order log outcoming requests:
csa_guzzle: logger: true
Autowiring
If you rely on Symfony autowiring, you can choose to alias a specific service to the GuzzleHttp\ClientInterface
interface and GuzzlHttp\Client
class.
csa_guzzle: profiler: '%kernel.debug%' logger: true clients: github_api: config: base_uri: 'https://api.github.com' headers: Accept: application/vnd.github.v3+json jsonplaceholder: config: base_uri: 'https://jsonplaceholder.typicode.com' headers: Accept: application/json default_client: github_api
Then, your github_api client will be automatically injected into your controller or service:
<?php namespace App\Controller; use Twig\Environment; use Symfony\Component\HttpFoundation\Response; use GuzzleHttp\Client; class DefaultController { private $twig; private $client; public function __construct(Environment $twig, Client $client) { $this->twig = $twig; $this->client = $client; } public function index() { $this->client->get('/users'); return new Response($this->twig->render("base.html.twig"), 200, ['Content-Type' => 'text/html']); } }
Creating a service for your client
There are two ways for creating a service for your client:
- Using the semantic configuration (Beginners)
- Registering your own service (Advanced users)
Creating a client using semantic configuration
Simply write the following code:
csa_guzzle: clients: github_api: config: # you can specify the options as in http://docs.guzzlephp.org/en/latest/quickstart.html#creating-a-client base_uri: https://api.github.com timeout: 2.0 headers: Accept: application/vnd.github.v3+json
The previous code will create a new service, called csa_guzzle.client.github_api
, that you can use in your controller, or that you can inject in another service:
<?php use Symfony\Bundle\FrameworkBundle\Controller\Controller; class MyController extends Controller { public function indexAction() { $client = $this->get('csa_guzzle.client.github_api'); // ... } }
You may want to mark the service as lazy.
csa_guzzle: clients: my_client: lazy: true # ...
If you override your client's class, you can also set the class for your client:
csa_guzzle: clients: my_client: class: AppBundle\Client # ...
Of course, you need to make sure that your client class' constructor has exactly the same signature as Guzzle's Client class.
Registering your own service
To have a client supported by the bundle, simply tag it as such:
YAML:
acme.client: class: %acme.client.class% arguments: [{ base_uri: http://acme.com, timeout: 2.0} ]
Creating new middleware
Creating a new Guzzle middleware
is as easy as creating a symfony service and using the csa_guzzle.middleware
tag, giving it an alias and
(optionally) a priority:
<service id="acme.middleware" class="Closure"> <factory class="My\Middleware" method="my_middleware" /> <tag name="csa_guzzle.middleware" alias="my_middleware" priority="100" /> </service>
You can also define middleware as a class with the __invoke
method like this:
class Middleware { public function __invoke(callable $handler): callable { return function (RequestInterface $request, array $options) use ($handler) { $request = $request->withHeader('X-Test', 'I was here'); return $handler($request, $options); }; } }
The service definition for such a class is then:
My\Middleware: tags: - { name: csa_guzzle.middleware, alias: my_middleware, priority: 100 }
Middleware are automatically used by all your clients, if you are using the semantic configuration. However, if you wish to, you can limit a client to a list of specific middleware:
csa_guzzle: # ... clients: # Prototype github_api: config: base_uri: https://api.github.com headers: Accept: application/vnd.github.v3+json middleware: ['debug', 'my_middleware'] # Note the use of the alias defined earlier in the service definition.
You can also disable specific middleware, by prefixing the middleware name with a !
character:
csa_guzzle: # ... clients: github_api: # ... middleware: ['!my_middleware']
You can either whitelist or blacklist middleware. Using both whitelisting and blacklisting will trigger an exception.
When registering your own clients with the bundle, you can explicitly list all
enabled middleware. The middleware
attribute takes a space-delimited list of
middleware names. In that case only the specified middleware will be registered
for that client:
YAML:
acme.client: class: %acme.client.class% tags: - { name: csa_guzzle.client, middleware: 'my_middleware another_middleware'}
BitrixCacheAdapter
Определяется сервис кэширования. Например, так:
bitrix.psr.cacher: class: WebArch\BitrixCache\AntiStampedeCacheAdapter arguments: ['/', 3600, 'cache/s1/psr-cache'] bitrix.psr.cacher.adapter: class: Local\Bundles\GuzzleBundle\Middlewares\Cache\Adapter\PsrAdapter arguments: ['@bitrix.psr.cacher', 3600]
И в конфигурации бандла указывается:
cache: enabled: true adapter: bitrix.psr.cacher.adapter
Available middleware
Currently, five middleware are available:
- the
logger
middleware - the
cache
middleware - the
mock
middleware
The logger
middleware
The logger
middleware's objective is to provide a simple tool for logging Guzzle requests.
Enabling request logging, you simply need to enable it in Symfony's configuration:
csa_guzzle: logger: enabled: true
Like the debug
middleware, there's also a shorthand syntax to enable it:
csa_guzzle: logger: true
Using the advanced configuration, you may also configure your own logger, as long as it implements
the PSR-3 LoggerInterface
:
csa_guzzle: logger: enabled: true service: my_logger_service
You can configure the log format using the syntax described in guzzlehttp/guzzle's documentation.
You may also use of the three levels described in the formatter: clf
(Apache log format), debug
, or short
:
csa_guzzle: logger: enabled: true format: debug
You could also change the level of logging, for dev
, you likely want debug
, for prod
, you likely want error
. You'll find more log levels in the LogLevel of php-fig.
csa_guzzle: logger: enabled: true level: debug
The cache
middleware
The cache
middleware's objective is to provide a very simple cache, in order to cache Guzzle responses.
Even though only a doctrine/cache adapter is provided
(Prokl\GuzzleBundle\GuzzleHttp\Cache\DoctrineAdapter
), the middleware is agnostic.
If you wish to use your own cache implementation with the cache
middleware, you simply need
to implement Prokl\GuzzleBundle\GuzzleHttp\Cache\StorageAdapterInterface
, and you're set!
This middleware can be configured with the following configuration:
csa_guzzle: cache: enabled: true adapter: my_storage_adapter
To use the doctrine cache adapter, you need to use the Prokl\GuzzleBundle\GuzzleHttp\Cache\DoctrineAdapter
class, in which you should inject your doctrine cache service. For example, using doctrine/cache's FilesystemCache
:
<services> <service id="my_storage_adapter" class="Prokl\GuzzleBundle\GuzzleHttp\Cache\DoctrineAdapter"> <argument type="service" id="my_cache_service" /> </service> <service id="my_cache_service" class="Doctrine\Common\Cache\FilesystemCache"> <argument>%kernel.cache_dir%/my_cache_folder</argument> </service> </services>
The mock
middleware
When running tests, you often want to disable real HTTP requests to your (or an external) API.
The mock
middleware can record those requests to replay them in tests.
The mock
middleware can work in two modes:
- record, which saves your HTTP requests inside a directory in your filesystem
- replay, which uses your saved HTTP requests from the same directory
Of course, this middleware should only be used in the test
environment (or dev
, if you don't have
access to the remote server):
# config_test.yml csa_guzzle: mock: storage_path: "%kernel.root_dir%/../features/fixtures/guzzle" mode: record
The generated files can then be committed in the VCS.
To use them, simply change the mode to replay
:
# config_test.yml csa_guzzle: mock: storage_path: "%kernel.root_dir%/../features/fixtures/guzzle" mode: replay
A few customizations can be done with the mock
middleware. You can indeed blacklist:
- Request headers, so they are not used for generating the mock's filename.
- Response headers, so they are not saved in the mock file.
For this, you can simply configure your client as follows:
# config_test.yml csa_guzzle: mock: # ... request_headers_blacklist: ['User-Agent', 'Host', 'X-Guzzle-Cache', 'X-Foo'] response_headers_blacklist: ['X-Guzzle-Cache', 'X-Bar']
Configuration reference
csa_guzzle: profiler: enabled: false # The maximum size of the body which should be stored in the profiler (in bytes) max_body_size: 65536 # Example: 65536 logger: enabled: false service: ~ format: '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}' level: debug default_client: ~ cache: enabled: false adapter: ~ clients: # Prototype name: class: GuzzleHttp\Client lazy: false config: ~ middleware: [] alias: null mock: enabled: false storage_path: ~ # Required mode: replay request_headers_blacklist: [] response_headers_blacklist: []
To log request/response body you can use {req_body}
and {res_body}
respectively in format
setting.
Full list of logs variables with description:
Reference Guzzle Log Plugin Docs
Прочее
- Альтернативный Guzzle Logger - для использования вне рамок бандла -
Prokl\GuzzleBundle\Middlewares\Raw\GuzzleLogger
Prokl\GuzzleBundle\Middlewares\Raw\GuzzleLogger: class: Prokl\GuzzleBundle\Middlewares\Raw\GuzzleLogger arguments: ['@logger', '@custom.guzzle.formatter'] custom.guzzle.formatter: class: GuzzleHttp\MessageFormatter arguments: ['[{date_common_log}] [{request}] "{method} {target} HTTP/{version}" {response}']