Last active
June 10, 2020 21:35
-
-
Save gnumoksha/b35d97613dd729315d3dc1ba0449544a to your computer and use it in GitHub Desktop.
Wrap some of Guzzle's behaviours using only PSR-7, PSR-17 and PSR-18 interfaces.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Libs\Tools\Http; | |
use Http\Client\Common\Plugin\CookiePlugin; | |
use Http\Client\Common\Plugin\RedirectPlugin; | |
use Http\Client\Common\PluginClient; | |
use Http\Message\CookieJar; | |
use InvalidArgumentException; | |
use Psr\Http\Client\ClientInterface; | |
use Psr\Http\Message\RequestFactoryInterface; | |
use Psr\Http\Message\RequestInterface; | |
use Psr\Http\Message\ResponseFactoryInterface; | |
use Psr\Http\Message\ResponseInterface; | |
use Psr\Http\Message\StreamFactoryInterface; | |
use Psr\Http\Message\UriFactoryInterface; | |
use Psr\Http\Message\UriInterface; | |
use Libs\Tools\Json\Json; | |
use function is_string; | |
/** | |
* Adapts some of Guzzle's behaviours using only PSR interfaces. | |
* Its give us the possibility to use any implementations for PSR interfaces while still using | |
* a simple Guzzle-like API. | |
* | |
* Note: 4xx and 5xx http codes will not throw an exception. | |
* | |
* @see https://github.com/guzzle/guzzle/issues/2186 Guzzle does not implements PSR 17 and PSR 18. | |
* @see https://github.com/guzzle/guzzle/pull/2122 | |
* @see https://github.com/guzzle/guzzle/pull/2525 | |
*/ | |
class Client implements ClientInterface | |
{ | |
/** @var \Psr\Http\Client\ClientInterface */ | |
protected $wrappedClient; | |
/** @var \Http\Client\Common\PluginClient */ | |
protected $pluginClient; | |
/** @var \Psr\Http\Message\RequestFactoryInterface */ | |
protected $requestFactory; | |
/** @var \Psr\Http\Message\ResponseFactoryInterface */ | |
protected $responseFactory; | |
/** @var \Psr\Http\Message\UriFactoryInterface */ | |
protected $uriFactory; | |
/** @var \Psr\Http\Message\StreamFactoryInterface */ | |
protected $streamFactory; | |
/** @var null|string */ | |
protected $baseUri; | |
/** @var \Http\Client\Common\Plugin[] */ | |
protected $plugins = []; | |
public function __construct( | |
ClientInterface $wrappedClient, | |
RequestFactoryInterface $requestFactory, | |
ResponseFactoryInterface $responseFactory, | |
UriFactoryInterface $uriFactory, | |
StreamFactoryInterface $streamFactory | |
) { | |
$this->wrappedClient = $wrappedClient; | |
$this->requestFactory = $requestFactory; | |
$this->responseFactory = $responseFactory; | |
$this->uriFactory = $uriFactory; | |
$this->streamFactory = $streamFactory; | |
$this->plugins[] = new RedirectPlugin(); | |
$this->pluginClient = new PluginClient($wrappedClient, $this->plugins); | |
} | |
/** | |
* @param mixed[] $config | |
* | |
* @return static | |
*/ | |
public function withConfig(array $config) : self | |
{ | |
$obj = clone $this; | |
if (isset($config['base_uri'])) { | |
$obj->baseUri = $config['base_uri']; | |
} | |
if (isset($config['cookies'])) { | |
$value = $config['cookies']; | |
if ($value === true) { | |
$cookieJar = new CookieJar(); | |
} else { | |
$cookieJar = $value; | |
} | |
$obj->plugins[] = new CookiePlugin($cookieJar); | |
} | |
$obj->pluginClient = new PluginClient($obj->wrappedClient, $obj->plugins); | |
return $obj; | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function sendRequest(RequestInterface $request) : ResponseInterface | |
{ | |
return $this->pluginClient->sendRequest($request); | |
} | |
/** | |
* Create and send an HTTP request. | |
* | |
* Use an absolute path to override the base path of the client, or a | |
* relative path to append to the base path of the client. The URL can | |
* contain the query string as well. | |
* | |
* @param string $method HTTP method. | |
* @param string|UriInterface $uri URI object or string. | |
* @param mixed[] $options Request options to apply. | |
* | |
* @see \GuzzleHttp\ClientInterface guzzle client interface | |
*/ | |
public function request(string $method, $uri = '', array $options = []) : ResponseInterface | |
{ | |
$request = $this->buildRequest($method, $uri, $options); | |
return $this->sendRequest($request); | |
} | |
/** | |
* @param string|UriInterface $uri | |
* @param mixed[] $options may contains the keys: headers, form_params, json, query. | |
* | |
* @return \Psr\Http\Message\ResponseInterface | |
* @throws \Psr\Http\Client\ClientExceptionInterface | |
*/ | |
public function get($uri, array $options = []) : ResponseInterface | |
{ | |
$request = $this->buildRequest('GET', $uri, $options); | |
return $this->sendRequest($request); | |
} | |
/** | |
* @param string|UriInterface $uri | |
* @param mixed[] $options may contains the keys: headers, form_params, json, query. | |
* | |
* @return \Psr\Http\Message\ResponseInterface | |
* @throws \Psr\Http\Client\ClientExceptionInterface | |
*/ | |
public function post($uri, array $options = []) : ResponseInterface | |
{ | |
$request = $this->buildRequest('POST', $uri, $options); | |
return $this->sendRequest($request); | |
} | |
/** | |
* @param string|UriInterface $uri | |
* @param mixed[] $options may contains the keys: headers, form_params, json, query. | |
* | |
* @see \GuzzleHttp\Client::applyOptions() | |
* @see \GuzzleHttp\Client::requestAsync() | |
*/ | |
protected function buildRequest(string $method, $uri, array $options = []) : RequestInterface | |
{ | |
$request = $this->requestFactory->createRequest($method, $this->buildUri($uri, $options)); | |
if (isset($options['headers'])) { | |
foreach ($options['headers'] as $key => $value) { | |
$request = $request->withHeader($key, $value); | |
} | |
} | |
if (isset($options['form_params'])) { | |
if (isset($options['multipart'])) { | |
throw new InvalidArgumentException('You cannot use form_params and multipart at the same time.'); | |
} | |
$request = $request->withBody( | |
$this->streamFactory->createStream( | |
http_build_query($options['form_params'], '', '&') | |
) | |
)->withHeader('Content-Type', 'application/x-www-form-urlencoded'); | |
} | |
if (isset($options['json'])) { | |
$request = $request->withBody($this->streamFactory->createStream(Json::encode($options['json']))) | |
->withHeader('Content-Type', 'application/json'); | |
} | |
return $request; | |
} | |
/** | |
* @param string|UriInterface $uri | |
* @param mixed[] $options may contains the keys: query. | |
* | |
* @see \GuzzleHttp\Client::applyOptions() | |
* @see \GuzzleHttp\Client::buildUri() | |
*/ | |
protected function buildUri($uri, array $options) : UriInterface | |
{ | |
if ($this->baseUri !== null) { | |
$uri = $this->baseUri . $uri; | |
} | |
if (is_string($uri)) { | |
$uri = $this->uriFactory->createUri($uri); | |
} | |
if (isset($options['query'])) { | |
$uri = $uri->withQuery( | |
http_build_query($options['query'], '', '&', PHP_QUERY_RFC3986) | |
); | |
} | |
return $uri; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment