pluggit / http-client
一个通过配置执行HTTP请求的库
Requires
- php: ^8.0
- guzzlehttp/psr7: ^1.0
- psr/log: ^2.0
Requires (Dev)
- behat/behat: ^3.1
- guzzlehttp/guzzle: ^6.0
- php-mock/php-mock: ^1.0
- phpspec/phpspec: ^7
- phpunit/php-code-coverage: ^2.2
- pimple/pimple: ^3.0
- pluggit/monitoring: ^4.0
- symfony/console: ^5.4
- symfony/var-dumper: ^5.4
- symfony/yaml: ^4.0
Suggests
- guzzlehttp/guzzle: Allows the library to send requests
- pimple/pimple: Allows to use the included service provider to register the client builder
- symfony/console: Allows to enable debug request executions in the console
- symfony/yaml: Allows to use yaml configuration files for the requests
- dev-master
- 3.0.0
- 2.1.1
- 2.1.0
- 2.0.0
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- dev-PHP8-compatibility
- dev-PHP8-compatibility-2
- dev-upgrade/php8_v2
- dev-upgrade/php8
- dev-rebrand
- dev-array-replace
- dev-fix-log-1.2.4
- dev-docs_update
- dev-feature/WHD-825
- dev-json
- dev-dev_json
This package is not auto-updated.
Last update: 2024-09-18 12:25:59 UTC
README
一个小型的PSR7兼容库,用于根据预配置的请求集执行http请求
TL;DR
# requests.yml my_cool_api: endpoint: http://my_cool_api.com/v2 requests: get_user: path: /user/${USER_ID} create_user: path: /user/${USER_ID} method: POST headers: Content-Type: application/json body: name: ${NAME} email: ${EMAIL}
$coolApi = ClientBuilder::create() ->withYamlConfig('requests.yml') ->build('my_cool_api'); $user = $client->json('get_user', ['user_id' => $userId]); echo "Hello ".$user->name;
目录
安装
像往常一样要求包
composer require pluggit/http-client
要使用Guzzle作为发送者(默认选项),您必须手动要求
composer require guzzlehttp/guzzle "^6.0"
需求
php >=5.5
guzzlehttp/psr7 ^1.0
psr/log ^1.0
注意: 此包依赖于guzzle实现PSR-7: HTTP消息接口
附加需求
Guzzle
此库允许使用不同的发送者来执行请求;并且包括了对guzzlehttp/guzzle
的适配器,它包含在库中,但您必须手动要求依赖项
composer require guzzlehttp/guzzle "^6.0"
可选需求
Yaml解析
如果您想使用Yaml文件作为配置源,您可以:a) 使用您自己的解析器并将配置作为数组传递;b) 将symfony/yaml
作为依赖项要求,并将yaml文件路径传递给构建器
composer require symfony/yaml "^3.1"
日志记录
您想知道为什么您的请求失败吗?没问题,该库接受任何Psr-3 logger logger实现(如Monolog)以写入调试和错误消息。
为了快速入门,您可以使用Symfony的控制台包在控制台中查看调试消息
composer require symfony/console "^3.1"
现在您将能够激活控制台调试模式
$builder->withConsoleDebug();
Pimple
如果您使用pimple构建依赖项,则可以使用提供者Cmp\Http\Provider\HttpClientServiceProvider
来注册构建器和多客户端。
composer require pimple/pimple "^3.0"
注意: 请参阅附录了解如何注册提供者
兼容性
此库已在以下PHP版本和配置下进行了测试
使用方法
此库允许从一组配置值构建请求,通过客户端执行它们,并获取响应
定义配置
配置是告诉客户端如何构建请求的内容,让我们看看一些配置示例
my_users_api: endpoint: https://api.mysite.com headers: api_version: 1.2 options: timeout: 2 requests: list_users: path: /users options: timeout: 15 get_user: path: /users/${USER_ID} create_user: path: /users/${USER_ID} headers: - Content-Type: application/json method: POST # Another service the_comments_api: endpoint: http://messaging_service.com/v2/ ...
第一行定义了一个服务名称,在本例中为my_users_api
注意: 您可以在config-sample/requests.yaml
中看到一个完整的示例配置文件,用于处理REST API
服务配置值
endpoint
(必需):这是此服务的所有请求的端点headers
:一个键值数组,包含要添加到所有此服务的请求的标头query
:一个键值数组,包含要附加到此服务的所有请求URI的查询参数body
:一个键值数组,包含要发送到此服务的所有请求的正文中的POST参数version
:HTTP协议版本,默认为1.1
options
:一个键值数组,包含传递给HTTP客户端发送者以修改其行为的选项requests
:一个键值数组,包含此服务的允许请求
请求配置值
请求配置允许设置几乎与服务配置相同选项,覆盖服务提供的值,这允许为服务定义一般行为,但可以调整一些特定请求的选项,例如,允许更长的超时
path
(必需):定义跟随端点的路径method
:定义请求的HTTP方法。默认为GET
headers
:一个键值数组,包含要添加到此请求的头部query
:一个键值数组,包含要附加到此请求URI的查询参数body
:一个键值数组,包含要发送到请求主体的post参数version
:HTTP协议版本,默认为1.1
options
:一个键值数组,包含传递给HTTP客户端发送者以修改其行为的选项
底层客户端选项
请求选项允许自定义客户端行为,而无需库知道如何处理它们的特定细节。
以与Guzzle提供的集成为例,我们可以有
- 基本认证:
auth: ['myUser', 'myPass']
- 超时:
timeout: 2
- 连接超时:
timeout: 15
- 添加证书:
['cert' => ['/path/server.pem', 'password']]
配置占位符
库允许指示配置参数中存在动态值,作为占位符
占位符规则
- 仅在path、query、headers和body中允许占位符
- 使用此格式添加占位符:
${PLACEHOLDER_NAME}
- 占位符标签名称必须为大写(尽管在替换时可以使用小写键)
- 可以在所有选项中多次使用相同的占位符,它将在所有选项中替换。
在请求中替换占位符
要替换占位符,请在创建请求时作为参数传递值
secure_api: endpoint: https://topsecret.com headers: api_key: MyPersonalApiKey token: ${TOKEN} requests: get_user: path: /users/${USER_ID}
$request = $client->create('secure_api', 'get_user', [ 'token' => $oath->sign($secret), 'user_id' => $userId ]);
配置构建器
构建器(Cmp\Http\ClientBuilder
)是一个将帮助您创建客户端的对象,简化了自定义过程。以下是可用的选项
$builder = ClientBuilder::create() ->withConfig($requests) ->withGuzzleSender($myCustomGuzzleClient) ->withConsoleDebug();
配置构建器后,您就准备好为您的HTTP服务创建客户端了
构建客户端
有两种不同的客户端允许创建和执行请求
Cmp\Http\Client\MultiClientInterface
:此客户端可以访问所有服务Cmp\Http\Client\ServiceClientInterface
:此客户端只能从单个服务执行请求
注意:您应该始终尝试在服务中注入ServiceClientInterface
,这将防止意外触发其他服务的请求
客户端中可用的方法是
create
:创建请求(Cmp\Http\Message\Request
)send
:发送请求,返回一个Cmp\Http\Message\Response
它们还提供了一些快捷方式以简化使用
execute
:在单个调用中创建并发送请求json
:创建并发送请求,解析JSON响应jsonAsArray
:创建并发送请求,从JSON响应解析为数组
构建多客户端
构建客户端最简单的方法是使用构建器上的build
方法
$client = $builder->build();
构建服务客户端
要构建服务客户端,请在构建器的最后一步指定服务名称
$myServiceApi = $builder->build('my_service');
自定义构建
客户端需要3个依赖项才能工作,构建器有方法可以覆盖所有这些依赖项,使用自定义实现
发送者
这是一个发送请求的类,它必须实现Cmp\Http\Sender\SenderInterface
并返回一个Psr-7兼容的响应
构建器将默认尝试使用提供的 Cmp\Http\Sender\GuzzleSender
,要指定不同的一个,请使用
$builder->withSender($sender);
即使你想使用guzzle,也可以自定义内部客户端
// tweak the client $customGuzzleClient = new Guzzlehttp\Guzzle(); // Pass it to the builder $builder->withGuzzleSender($customGuzzleClient);
配置
这是唯一的必需依赖项,一个定义可用请求的配置
$builder->withConfig($config);
如果已安装 symfony/yaml
,你可以传递一个包含yaml配置的文件路径
$builder->withYamlConfig($yamlFile);
日志记录器
你可以传递一个 Psr\Log\LoggerInterface
来接收调试和错误消息
$builder->withLogger($logger);
如果你想在控制台调试原始http请求/响应,你可以在构建器中激活调试输出(你需要安装 symfony/console
)
$builder->withConsoleDebug();
创建请求
要创建一个请求,你需要识别你想要的服务和请求。此外,你可以传递动态值以替换占位符
$request = $client->request('weather', 'forecast', ['city' => $city]); // Service specific clients do not need the service name $request = $weather->request('forecast', ['city' => $city]);
创建的请求是 Cmp\Http\Message\Request
实例,实现了 Psr\Http\Message\RequestInterface
,这使得它们适合在库和框架之间共享
库请求对象提供了一些帮助器,以便更容易地使用它们
withQueryParameter($key, $value)
:允许你添加或修改一个查询参数withPost(array $params)
:允许传递一个键值数组作为正文发送withJsonPost(array $params)
:允许传递一个键值数组;它将被编码为json,并将添加头Content-Type: application/json
__toString()
:这使得请求可以嵌入到字符串中
自定义请求创建
如果你提供给构建器的请求工厂符合 Cmp\Http\RequestFactoryInterface
,你将能够扩展请求类并更改行为。
你可能想知道"我为什么要这样做呢?"
例如,为了
- 将所有出站端点更改为模拟服务器,以防止在测试环境中执行某些请求
- 将配置应用于所有服务的所有请求
$factory = new TestEnvironmentsRequestFactory($config); $builder->withRequestFactory($factory);
发送请求
发送请求后,你会收到一个兼容 Psr\Http\Message\ResponseInterface
的 Cmp\Http\Message\Response
实例
此响应对象还提供了一些帮助器方法
json($asArray = true)
:将正文解析为json并返回一个stdClass
对象或一个array
jsonAsArray()
:与之前相同,但强制返回类型为数组__toString()
:这使得响应可以嵌入到字符串中
异常处理
并非所有事情都按预期工作;为了使你的生活更轻松地处理这些问题,库提供了一组小的异常
Cmp\Http\Exception\RuntimeException
:这是库中使用的基异常,所有在库代码中抛出的异常都使用或扩展了此异常Cmp\Http\Exception\RequestBuildException
:当无法完成请求构建过程时抛出此异常Cmp\Http\Exception\RequestExecutionException
:当发送请求时发生某些错误时抛出此异常
REST API集成示例
我将向你展示如何执行REST API中最常见的操作。
让我们假设我们想要与API端点交互来管理我们的应用程序用户。用户实体如下所示
{ "id": "1", "first_name": "John", "last_name": "Doe" }
现在让我们在我们的配置文件中定义典型的请求
# Service definition my_app: # The endpoint is required endpoint: https://api.myapp.com/v1 options: auth: ['apikey', 'secret'] # At least one request is required too requests: list_users: path: /users get_user: path: /users/${USER_ID} delete_user: path: /users/${USER_ID} method: DELETE put_user: path: /users/${USER_ID} method: PUT headers: Content-Type: application/json body: first_name: ${FIRST_NAME} last_name: ${LAST_NAME} create_user: path: /users method: POST headers: Content-Type: application/json body: first_name: ${FIRST_NAME} last_name: ${LAST_NAME} update_user: path: /users/${USER_ID} method: PATCH headers: Content-Type: application/json # body: No need to define all the body params here, we can do it at request time
构建API客户端
让我们根据配置为我们的api构建一个服务客户端,所有请求都将包含基本身份验证
$api = $builder->build('my_app');
###列出用户此调用将返回一个用户数组
// We are going to modify the request to pass a limit on the number of users to retrieve $users = $api->send($api->request('list_users')->withQueryParameter('limit', 25))->json();
获取用户
此调用将向uri路径中注入用户id,以请求用户
// The json shortcut creates, executes and parses the body response all in a single call $users = $api->json('get_user', ['user_id => 1]);
创建用户
在这里我们将替换正文数组中的占位符,如果api只接受json正文,我们必须添加正确的content type头,如示例所示,以便正确创建请求
$user = $api->json('create_user', ['name' => 'Jane', 'last_name' => 'Roe']);
替换用户
我们可以在路径或正文参数同时替换占位符
$user = $api->json('put_user', ['user_id' => 1, 'name' => 'Jane', 'last_name' => 'Roe']);
更新用户
当我们只更新某些字段时,我们事先不知道将要发送哪些字段,因此最好稍后决定
$request = $api->create('update_user', ['user_id' => 1]); // Remember to assign the result, as the request return always a new instance when modifying it $request = $request->withPost(['name' => 'Jane']); $updatedUser = $api->send($request)->json();
删除用户
删除用户更加简单
$api->execute('delete_user', ['user_id' => 1]);
附录
Pimple服务提供者
库中包含了一个服务提供者,用于以简单的方式注册客户端:Cmp\Http\Provider\HttpClientServiceProvider
。该提供者将在键http_client.builder
处注册构建器对象Cmp\Http\ClientBuilder
,并在http_client.client
中注册一个通用多客户端Cmp\Http\Client\MultiClient
,但它也接受这两个服务的别名。
$container->register(new HttpClientServiceProvider('requester', 'client'), [ 'http_client.yaml' => 'config/requests.yml', ]); $builder = $container['requester']; // or http_client.builder $client = $container['client']; // or http_client.client
提供者接受的选项有
http_client.yaml
:一个包含yaml配置文件的文件路径http_client.config
:包含请求的配置数组http_client.logger
:传递一个Psr\Logger\LoggerInterface对象以向客户端添加日志记录http_client.sender
:实现Cmp\Http\Sender\SenderInterface
接口的自定义实现http_client.guzzle
:自定义的GuzzleHttp\ClientInterface
对象(用于保留引用)http_client.factory
:自定义的Cmp\Http\RequestFactoryInterface
实现http_client.debug
:传递true,这将激活控制台输出以进行调试
开发环境
要构建测试环境,您需要安装docker和docker-compose
make dev
运行测试
make unit make integration
您只能以这种方式运行针对特定PHP版本的测试
make unit PHP_VERSION=5.6 make integration PHP_VERSION=5.6
代码覆盖率
您可以为代码覆盖率构建HTML格式的报告。它将在bin/code-coverage
中可用
make code-coverage
停止环境
make nodev
删除环境
您可以通过删除docker镜像来实现完全清理
make nodev IMAGES=true