proklung/symfony-guzzle-bundle

Symfony 的 Guzzle 工作包。

1.0.6 2021-08-20 07:03 UTC

This package is auto-updated.

Last update: 2024-09-20 14:01:51 UTC


README

该包是基于CsaGuzzleBundle进行改进的,以满足个人需求(例如,添加了适用于Bitrix的缓存适配器等)。

安装

  1. composer require proklung/symfony-guzzle-bundle

使用

配置

您也可以启用内置的记录器,以记录输出请求

csa_guzzle:
    logger: true

自动装配

如果您依赖于 Symfony 的自动装配,可以选择将特定的服务别名指定为 GuzzleHttp\ClientInterface 接口和 GuzzlHttp\Client 类。

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

然后,github_api 客户端将自动注入到您的控制器或服务中

<?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']);
    }
}

创建客户端服务

创建客户端服务有两种方法

  • 使用语义配置(入门级)
  • 注册自己的服务(高级用户)

使用语义配置创建客户端

只需编写以下代码

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

前面的代码将创建一个新的服务,称为 csa_guzzle.client.github_api,您可以在控制器中使用它,或者将其注入到另一个服务中

<?php

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class MyController extends Controller
{
    public function indexAction()
    {
        $client = $this->get('csa_guzzle.client.github_api');
        // ...
    }
}

您可能希望将该服务标记为 延迟加载

csa_guzzle:
    clients:
        my_client:
            lazy: true
            # ...

如果您覆盖了客户端的类,您也可以设置客户端的类

csa_guzzle:
    clients:
        my_client:
            class: AppBundle\Client
            # ...

当然,您需要确保客户端类的构造函数与 Guzzle 的 Client 类的签名完全相同。

注册自己的服务

为了使客户端支持该包,只需将其标记为这样

YAML

acme.client:
    class: %acme.client.class%
    arguments: [{ base_uri: http://acme.com, timeout: 2.0} ]

创建新的中间件

创建一个新的 Guzzle 中间件就像创建一个 symfony 服务并使用 csa_guzzle.middleware 标签一样,给它一个别名,并(可选地)一个优先级

<service
        id="acme.middleware"
        class="Closure">
    <factory class="My\Middleware" method="my_middleware" />
    <tag name="csa_guzzle.middleware" alias="my_middleware" priority="100" />
</service>

您还可以定义具有 __invoke 方法的类作为中间件,如下所示

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);
        };
    }
}

此类服务的定义是

My\Middleware:
    tags:
        - { name: csa_guzzle.middleware, alias: my_middleware, priority: 100 }

如果使用语义配置,中间件将自动用于所有客户端。但是,如果您愿意,您可以限制客户端使用特定的中间件列表

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.

您还可以禁用特定的中间件,通过在中间件名称前加上一个 ! 字符

csa_guzzle:
    # ...
    clients:
        github_api:
            # ...
            middleware: ['!my_middleware']

您可以选择性地列出中间件,或者黑名单中间件。同时使用白名单和黑名单将触发异常。

当使用该包注册自己的客户端时,您可以明确列出所有启用的中间件。 middleware 属性接受以空格分隔的中件间名称列表。在这种情况下,只有指定的中间件将为该客户端注册

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

可用的中间件

目前,有五种中间件可用

  • the logger 中间件
  • the cache 中间件
  • the mock 中间件

The logger 中间件

The logger 中间件的目标是提供一个简单的工具来记录 Guzzle 请求。

启用请求记录,您只需在 Symfony 的配置中启用它

csa_guzzle:
    logger:
        enabled: true

类似于 debug 中间件,也存在简写语法来启用它

csa_guzzle:
    logger: true

使用高级配置,您还可以配置自己的记录器,只要它实现了 PSR-3 LoggerInterface

csa_guzzle:
    logger:
        enabled: true
        service: my_logger_service

您可以使用在guzzlehttp/guzzle的文档中描述的语法来配置日志格式。您还可以使用格式化程序中描述的三个级别:clf(Apache日志格式)、debugshort

csa_guzzle:
    logger:
        enabled: true
        format: debug

您还可以更改日志级别,对于dev,您可能想要debug,对于prod,您可能想要error。您可以在php-fig的LogLevel中找到更多日志级别。

csa_guzzle:
    logger:
        enabled: true
        level: debug

cache中间件

cache中间件的目标是提供一个非常简单的缓存,以便缓存Guzzle响应。

尽管只提供了一个doctrine/cache适配器(Prokl\GuzzleBundle\GuzzleHttp\Cache\DoctrineAdapter),但中间件是无状态的。如果您想在cache中间件中使用自己的缓存实现,您只需实现Prokl\GuzzleBundle\GuzzleHttp\Cache\StorageAdapterInterface即可!

此中间件可以使用以下配置进行配置

csa_guzzle:
    cache:
        enabled: true
        adapter: my_storage_adapter

要使用doctrine缓存适配器,您需要使用Prokl\GuzzleBundle\GuzzleHttp\Cache\DoctrineAdapter类,您应该在其中注入您的doctrine缓存服务。例如,使用doctrine/cache的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>

mock中间件

当运行测试时,您通常想禁用对您的(或外部的)API的真实HTTP请求。mock中间件可以记录这些请求以便在测试中回放。

mock中间件可以在两种模式下工作

  • record,它将您的HTTP请求保存到您的文件系统中的一个目录中
  • replay,它使用同一目录中保存的您的HTTP请求

当然,此中间件仅在test环境(或dev,如果您无法访问远程服务器)中使用

# config_test.yml
csa_guzzle:
    mock:
        storage_path: "%kernel.root_dir%/../features/fixtures/guzzle"
        mode: record

生成的文件可以随后提交到版本控制系统(VCS)。

要使用它们,只需将模式更改为replay

# config_test.yml
csa_guzzle:
    mock:
        storage_path: "%kernel.root_dir%/../features/fixtures/guzzle"
        mode: replay

可以使用mock中间件进行一些自定义设置。您确实可以添加黑名单

  • 请求头,因此它们不会用于生成mock的文件名。
  • 响应头,因此它们不会保存到mock文件中。

为此,您只需按如下方式配置您的客户端

# 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']

配置参考

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: []

要记录请求/响应体,您可以在format设置中使用分别代表请求和响应体的{req_body}{res_body}

日志变量的完整列表及其描述

参考 Guzzle日志插件文档

其他

  1. 替代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}']