stoyantodorov/laravel-api-client

Laravel 的 API 客户端

2.0.0 2024-05-15 10:01 UTC

This package is auto-updated.

Last update: 2024-09-15 14:37:46 UTC


README

此包提供了一种使用 Laravel HTTP 门面进行错误处理、日志记录和事件触发的方法。还有一个令牌服务,可以根据存储的配置或接收到的参数请求访问令牌。

Latest Version on Packagist Total Downloads

安装

composer require stoyantodorov/laravel-api-client

使用

HttpClient 服务

以符合您需求的方式解析 HttpClient 实例,例如

use Stoyantodorov\ApiClient\Interfaces\HttpClientInterface;

$apiClient = resolve(HttpClientInterface::class);

发送请求

$response = $apiClient->get('https://exmple-host', ['queryParam' => 'value']);

您可以在事先配置 PendingRequest

use Illuminate\Support\Facades\Http;

$apiClient->get('https://exmple-host', ['queryParam' => 'value'], Http::withToken($token));

您还可以使用 baseConfig 方法添加基础配置

$apiClien->baseConfig(retries: 3, retryInterval: 3000, timout: 60, connectTimeout: 5, userAgent: 'Test');

此方法可以接收已配置的 PendingRequest

use Illuminate\Support\Facades\Http;

$apiClient->baseConfig(retries: 3, pendingRequest: Http::withToken($token));

使用 send 方法发送特定 HTTP 方法和格式

use Stoyantodorov\ApiClient\Enums\HttpMethod;
use Stoyantodorov\ApiClient\Enums\HttpRequestFormat;

$apiClient->send(HttpMethod::CONNECT, 'https://exmple-host', HttpRequestFormat::QUERY, []);

可选地,您也可以添加已配置的 PendingRequest

use Illuminate\Support\Facades\Http;
use Stoyantodorov\ApiClient\Enums\HttpMethod;
use Stoyantodorov\ApiClient\Enums\HttpRequestFormat;

$apiClient->send(HttpMethod::CONNECT, 'https://exmple-host', HttpRequestFormat::QUERY, [], Http::withToken($token));

当您需要发送请求而不进行错误处理、日志记录和事件触发时,请使用 sendRequest

use Stoyantodorov\ApiClient\Enums\HttpClientRequestMethod;

$apiClient->->sendRequest(HttpClientRequestMethod::GET, 'https://exmple-host');

日志记录和事件触发可以通过 config 值进行配置

    'events' => [
        'onSuccess' => true,
        'onRequestException' => true,
        'onConnectionException' => true,
    ],
    'logs' => [
        'onRequestException' => true,
        'onConnectionException' => true,
    ],

这些配置可以通过 HttpClient 设置器进行覆盖

$apiClient->fireEventOnSuccess(false);

令牌服务

工厂

有两个工厂实例化 TokenService。第一个从 config 文件设置配置

use Stoyantodorov\ApiClient\Factories\TokenFromConfigFactory;

TokenFromConfigFactory::create();

当您使用此工厂时,应在 api-client.php 中设置相关配置

'tokenConfigurationsBase' => [
        'accessTokenRequest' => [
            'url' => '',
            'body' => [],
            'headers' => [],
            'responseNestedKeys' => ['access_token'],
            'method' => 'post',
            'dispatchEvent' => true,
        ],
        'refreshTokenRequest' => [
            'url' => '',
            'body' => [],
            'headers' => [],
            'responseNestedKeys' => ['access_token'],
            'method' => 'post',
            'dispatchEvent' => true,
        ],
        'tokenRequestsRetries' => 3,
    ],

第二个工厂从数据对象设置配置

use Stoyantodorov\ApiClient\Factories\TokenFromDataFactory;
use Stoyantodorov\ApiClient\Data\TokenData;

$tokenData new TokenData(
            url: 'https://example-host/access-token',
            body: ['username' => 'testValue', 'password' => 'testValue'],
        );

TokenFromDataFactory::create($tokenData);

当您使用端点刷新令牌时,应指示工厂发送此类配置

TokenFromConfigFactory::create(hasRefreshTokenRequest: true);

use Stoyantodorov\ApiClient\Data\RefreshTokenData;
$refreshTokenData = new RefreshTokenData(
            url: 'https://example-host/refresh-token',
            body: ['refreshToken' => 'testValue'],
        );
TokenFromDataFactory::create(tokenData: $tokenData, refreshTokenData: $refreshTokenData);

您可以指示 TokenFromConfigFactory 从其他配置键加载配置

TokenFromConfigFactory::create(configKey: 'anotherApiConfigurations');

如果您已经有了已接收的令牌,可以将其作为可选参数发送给两个工厂

TokenFromConfigFactory::>create(token: 'someValueOrNull');
TokenFromDataFactory::create(token: 'someValueOrNull');

获取令牌

get 方法发送令牌请求

$service->get();

如果服务实例化时已获得令牌,则该方法将返回该令牌而不是发送新的请求。

相同的方法还可以发送请求以刷新令牌

$service->get(refresh: true);

响应中令牌的 JSON 路径应在 config 文件中设置

'responseNestedKeys' => ['data', 'access_token'],

或在 TokenDataRefreshTokenData

new TokenData(
            url: 'https://example-host/access-token',
            body: ['username' => 'testValue', 'password' => 'testValue'],
            responseNestedKeys: ['data', 'access_token'],
        );
new RefreshTokenData(
            url: 'https://example-host/refresh-token',
            body: ['refreshToken' => 'testValue'],
            responseNestedKeys: ['data', 'access_token'],
        );

当您需要访问响应时,可以订阅默认触发的事件

use Stoyantodorov\ApiClient\Events\AccessTokenObtained;

public function handle(AccessTokenObtained $event): void
{
    $response = $vent->response;
}
use Stoyantodorov\ApiClient\Events\AccessTokenRefreshed;

public function handle(AccessTokenRefreshed $event): void
{
    $response = $vent->response;
}

如果您不使用这些事件,可以从 config 文件中禁用它们

'dispatchEvent' => false,

TokenDataRefreshTokenData

new TokenData(
            url: 'https://example-host/access-token',
            body: ['username' => 'testValue', 'password' => 'testValue'],
            dispatchEvent: false,
        );
new RefreshTokenData(
            url: 'https://example-host/refresh-token',
            body: ['refreshToken' => 'testValue'],
            dispatchEvent: false,
        );

API 参考

HttpClientInterface

    /**
     * Base configuration for PendingRequest
     * When PendingRequest instance isn't received, new one is created
     *
     * @param array               $headers
     * @param int                 $retries
     * @param int                 $retryInterval
     * @param int                 $timeout
     * @param int                 $connectTimeout
     * @param string|null         $userAgent
     * @param PendingRequest|null $pendingRequest
     * @return self
     */
    public function baseConfig(
        array               $headers = [],
        int                 $retries = 1,
        int                 $retryInterval = 1000,
        int                 $timeout = 30,
        int                 $connectTimeout = 3,
        string|null         $userAgent = null,
        PendingRequest|null $pendingRequest = null,
    ): self;

    /**
     * Send a request with given HTTP method, url, options HTTP request format
     * When PendingRequest instance isn't received, new one is created
     *
     * @param HttpMethod          $httpMethod
     * @param string              $url
     * @param HttpRequestFormat   $format
     * @param array               $options
     * @param PendingRequest|null $pendingRequest
     * @return Response|null
     */
    public function send(
        HttpMethod          $httpMethod,
        string              $url,
        HttpRequestFormat   $format,
        array               $options = [],
        PendingRequest|null $pendingRequest = null
    ): Response|null;

    /**
     * Send HEAD request
     * When PendingRequest instance isn't received, new one is created
     *
     * @param string              $url
     * @param array               $parameters
     * @param PendingRequest|null $pendingRequest
     * @return Response|null
     */
    public function head(string $url, array $parameters = [], PendingRequest|null $pendingRequest = null): Response|null;

    /**
     * Send GET request
     * When PendingRequest instance isn't received, new one is created
     *
     * @param string              $url
     * @param array               $parameters
     * @param PendingRequest|null $pendingRequest
     * @return Response|null
     */
    public function get(string $url, array $parameters = [], PendingRequest|null $pendingRequest = null): Response|null;

    /**
     * Send POST request
     * When PendingRequest instance isn't received, new one is created
     *
     * @param string              $url
     * @param array               $body
     * @param PendingRequest|null $pendingRequest
     * @return Response|null
     */
    public function post(string $url, array $body = [], PendingRequest|null $pendingRequest = null): Response|null;

    /**
     * Send PUT request
     * When PendingRequest instance isn't received, new one is created
     *
     * @param string              $url
     * @param array               $body
     * @param PendingRequest|null $pendingRequest
     * @return Response|null
     */
    public function put(string $url, array $body = [], PendingRequest|null $pendingRequest = null): Response|null;

    /**
     * Send PATCH request
     * When PendingRequest instance isn't received, new one is created
     *
     * @param string              $url
     * @param array               $body
     * @param PendingRequest|null $pendingRequest
     * @return Response|null
     */
    public function patch(string $url, array $body = [], PendingRequest|null $pendingRequest = null): Response|null;

    /**
     * Send DELETE request
     * When PendingRequest instance isn't received, new one is created
     *
     * @param string              $url
     * @param array               $body
     * @param PendingRequest|null $pendingRequest
     * @return Response|null
     */
    public function delete(string $url, array $body = [], PendingRequest|null $pendingRequest = null): Response|null;

    /**
     * Send a request by given HttpClient request method, url, options
     * Catches RequestException and ConnectionException
     * Logs messages
     * Fires events depending on the configurations
     * $httpMethod parameter should be provided when $apiClientRequestMethod is HttpClientRequestMethod::SEND
     * When PendingRequest instance isn't received, new one is created
     *
     * @param HttpClientRequestMethod $apiClientRequestMethod
     * @param string                 $url
     * @param array                  $options
     * @param PendingRequest|null    $pendingRequest
     * @param HttpMethod|null        $httpMethod
     * @return Response|null
     */
    public function sendRequest(
        HttpClientRequestMethod $apiClientRequestMethod,
        string                 $url,
        array                  $options = [],
        PendingRequest|null    $pendingRequest = null,
        HttpMethod|null        $httpMethod = null,
    ): Response|null;

    /**
     * Send request without error handling and event triggering
     * Throw RequestException when throw is true
     *
     * @param HttpClientRequestMethod $apiClientMethod
     * @param string                 $url
     * @param array                  $options
     * @param HttpMethod|null        $httpMethod
     * @param bool                   $throw
     * @return Response
     */
    public function request(
        HttpClientRequestMethod $apiClientMethod,
        string                 $url,
        array                  $options = [],
        HttpMethod|null        $httpMethod = null,
        bool                   $throw = false,

    ): Response;

    /**
     * Set PendingRequest when not null value is received
     *
     * @param PendingRequest|null $pendingRequest
     * @return self
     */
    public function setPendingRequest(PendingRequest|null $pendingRequest): self;

    /**
     * Get pendingRequest
     *
     * @return PendingRequest|null
     */
    public function getPendingRequest(): PendingRequest|null;

    /**
     * Determine if HttpResponseSucceeded event is fired
     *
     * @param bool $value
     * @return self
     */
    public function fireEventOnSuccess(bool $value): self;

    /**
     * Determine if HttpRequestFailed event is fired
     *
     * @param bool $value
     * @return self
     */
    public function fireEventOnRequestException(bool $value): self;

    /**
     * Determine if HttpConnectionFailed event is fired
     *
     * @param bool $value
     * @return self
     */
    public function fireEventOnConnectionException(bool $value): self;

    /**
     * Determine if RequestException occurring is logged
     *
     * @param bool $value
     * @return self
     */
    public function logOnRequestException(bool $value): self;

    /**
     * Determine if ConnectionException occurring is logged
     *
     * @param bool $value
     * @return self
     */
    public function logOnConnectionException(bool $value): self;

枚举

enum HttpMethod: string
{
    case HEAD = 'HEAD';
    case GET = 'GET';
    case POST = 'POST';
    case PUT = 'PUT';
    case PATCH = 'PATCH';
    case DELETE = 'DELETE';
    case CONNECT = 'CONNECT';
    case OPTIONS = 'OPTIONS';
    case TRACE = 'TRACE';
}
enum HttpRequestFormat: string
{
    case QUERY = 'query';
    case BODY = 'body';
    case JSON = 'json';
    case FORM_PARAMS = 'form_params';
    case MULTIPART = 'multipart';
}
enum HttpClientRequestMethod: string
{
    case GET = 'get';
    case HEAD = 'head';
    case POST = 'post';
    case PATCH = 'patch';
    case PUT = 'put';
    case DELETE = 'delete';
    case SEND = 'send';
}

TokenFromConfigFactoryInterface

    /**
     * Instantiate TokenInterface
     * When receives $token it is set in TokenInterface instance
     * $hasRefreshTokenRequest determines instantiating RefreshTokenData
     * $configKey refers to token configurations in the config file
     *
     * @param bool        $hasRefreshTokenRequest
     * @param string      $configKey
     * @param string|null $token = null
     * @return TokenInterface
     */
    public static function create(
                              bool $hasRefreshTokenRequest = true,
                              string $configKey = 'tokenConfigurationsBase',
                              #[SensitiveParameter] string|null $token = null,
    ): TokenInterface;

TokenFromDataFactoryInterface

    /**
     * Instantiate TokenInterface
     * When receives $token it is set in TokenInterface instance
     *
     * @param TokenData             $tokenData
     * @param RefreshTokenData|null $refreshTokenData = null
     * @param int                   $retries = 3
     * @param string|null           $token = null
     * @return TokenInterface
     */
    public static function create(
        #[SensitiveParameter] TokenData             $tokenData,
        #[SensitiveParameter] RefreshTokenData|null $refreshTokenData = null,
                              int                   $retries = 3,
        string|null                                  $token = null,
    ): TokenInterface;

TokenInterface

    /**
     * Get Access Token
     * When it's missing request it
     * When $refresh is true make a request to refresh the token
     *
     * @param bool $refresh = false
     * @return string
     */
    public function get(bool $refresh = false): string;

测试

composer test

变更日志

请参阅 CHANGELOG 了解最近的变化。

安全漏洞

请参阅 我们的安全策略 了解如何报告安全漏洞。

致谢

许可

MIT 许可证 (MIT)。请参阅 许可文件 了解更多信息。