Skip to content

Commit

Permalink
Replace GuzzleHttp with PSR-18 HTTP Clients (#1032)
Browse files Browse the repository at this point in the history
* Replace GuzzleHttp with psr/http-client and psr/http-factory
* Improve AbstractProvider code coverage
  • Loading branch information
flavioheleno authored Dec 11, 2024
1 parent c8cc03e commit 94dd102
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 236 deletions.
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
"require": {
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
"ext-json": "*",
"guzzlehttp/guzzle": "^7.4.5"
"psr/http-client": "^1.0",
"psr/http-factory": "^1.1",
"psr/http-message": "^2.0"
},
"require-dev": {
"guzzlehttp/guzzle": "^7.4.5",
"mockery/mockery": "^1.6",
"php-parallel-lint/php-parallel-lint": "^1.4",
"phpunit/phpunit": "^10.5 || ^11.5",
Expand Down
82 changes: 63 additions & 19 deletions src/Provider/AbstractProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
namespace League\OAuth2\Client\Provider;

use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\ClientInterface as HttpClientInterface;
use GuzzleHttp\Exception\BadResponseException;
use InvalidArgumentException;
use League\OAuth2\Client\Grant\AbstractGrant;
Expand All @@ -28,9 +27,11 @@
use League\OAuth2\Client\Tool\ArrayAccessorTrait;
use League\OAuth2\Client\Tool\GuardedPropertyTrait;
use League\OAuth2\Client\Tool\QueryBuilderTrait;
use League\OAuth2\Client\Tool\RequestFactory;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;
use UnexpectedValueException;

/**
Expand Down Expand Up @@ -103,12 +104,17 @@ abstract class AbstractProvider
protected $grantFactory;

/**
* @var RequestFactory
* @var RequestFactoryInterface
*/
protected $requestFactory;

/**
* @var HttpClientInterface
* @var StreamFactoryInterface
*/
protected $streamFactory;

/**
* @var ClientInterface
*/
protected $httpClient;

Expand Down Expand Up @@ -140,16 +146,17 @@ public function __construct(array $options = [], array $collaborators = [])
$this->setGrantFactory($collaborators['grantFactory']);

if (empty($collaborators['requestFactory'])) {
$collaborators['requestFactory'] = new RequestFactory();
throw new InvalidArgumentException('No request factory set');
}
$this->setRequestFactory($collaborators['requestFactory']);

if (empty($collaborators['httpClient'])) {
$client_options = $this->getAllowedClientOptions($options);
if (empty($collaborators['streamFactory'])) {
throw new InvalidArgumentException('No stream factory set');
}
$this->setStreamFactory($collaborators['streamFactory']);

$collaborators['httpClient'] = new HttpClient(
array_intersect_key($options, array_flip($client_options))
);
if (empty($collaborators['httpClient'])) {
throw new InvalidArgumentException('No http client set');
}
$this->setHttpClient($collaborators['httpClient']);

Expand Down Expand Up @@ -205,10 +212,10 @@ public function getGrantFactory()
/**
* Sets the request factory instance.
*
* @param RequestFactory $factory
* @param RequestFactoryInterface $factory
* @return self
*/
public function setRequestFactory(RequestFactory $factory)
public function setRequestFactory(RequestFactoryInterface $factory)
{
$this->requestFactory = $factory;

Expand All @@ -218,20 +225,43 @@ public function setRequestFactory(RequestFactory $factory)
/**
* Returns the request factory instance.
*
* @return RequestFactory
* @return RequestFactoryInterface
*/
public function getRequestFactory()
{
return $this->requestFactory;
}

/**
* Sets the stream factory instance.
*
* @param StreamFactoryInterface $factory
* @return self
*/
public function setStreamFactory(StreamFactoryInterface $factory)
{
$this->streamFactory = $factory;

return $this;
}

/**
* Returns the stream factory instance.
*
* @return StreamFactoryInterface
*/
public function getStreamFactory()
{
return $this->streamFactory;
}

/**
* Sets the HTTP client instance.
*
* @param HttpClientInterface $client
* @param ClientInterface $client
* @return self
*/
public function setHttpClient(HttpClientInterface $client)
public function setHttpClient(ClientInterface $client)
{
$this->httpClient = $client;

Expand All @@ -241,7 +271,7 @@ public function setHttpClient(HttpClientInterface $client)
/**
* Returns the HTTP client instance.
*
* @return HttpClientInterface
* @return ClientInterface
*/
public function getHttpClient()
{
Expand Down Expand Up @@ -696,9 +726,23 @@ protected function createRequest($method, $url, $token, array $options)
];

$options = array_merge_recursive($defaults, $options);
$factory = $this->getRequestFactory();
$requestFactory = $this->getRequestFactory();
$streamFactory = $this->getStreamFactory();

$request = $requestFactory->createRequest($method, $url);
foreach ($options['headers'] as $name => $value) {
$request = $request->withAddedHeader($name, $value);
}

$request = $request->withProtocolVersion($options['version'] ?? '1.1');

if (!empty($options['body'])) {
$request = $request->withBody(
$streamFactory->createStream($options['body'] ?? null)
);
}

return $factory->getRequestWithOptions($method, $url, $options);
return $request;
}

/**
Expand All @@ -712,7 +756,7 @@ protected function createRequest($method, $url, $token, array $options)
*/
public function getResponse(RequestInterface $request)
{
return $this->getHttpClient()->send($request);
return $this->getHttpClient()->sendRequest($request);
}

/**
Expand Down
87 changes: 0 additions & 87 deletions src/Tool/RequestFactory.php

This file was deleted.

10 changes: 8 additions & 2 deletions test/src/Grant/GrantTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

namespace League\OAuth2\Client\Test\Grant;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use Mockery;
use Mockery\MockInterface;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use League\OAuth2\Client\Token\AccessTokenInterface;
Expand All @@ -20,6 +22,10 @@ protected function getMockProvider()
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
],[
'httpClient' => new Client(),
'requestFactory' => new HttpFactory(),
'streamFactory' => new HttpFactory()
]);
}

Expand Down Expand Up @@ -72,7 +78,7 @@ public function testGetAccessToken($grant, array $params = [])
/** @var ClientInterface & MockInterface $client */
$client = Mockery::spy(ClientInterface::class)->makePartial();
$client
->shouldReceive('send')
->shouldReceive('sendRequest')
->once()
->withArgs(function ($request) {
parse_str((string) $request->getBody(), $body);
Expand Down
Loading

0 comments on commit 94dd102

Please sign in to comment.