Skip to content

Commit dbff7b9

Browse files
committed
Implement HTTPlug
1 parent 1711b5e commit dbff7b9

File tree

7 files changed

+229
-67
lines changed

7 files changed

+229
-67
lines changed

README.UPGRADING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
## Upgrade Guide
44

5-
### Upgrading to Version 1.0.0
5+
### Upgrading to Version 1.5
66

7-
TBD
7+
You need to install `php-http/guzzle6-adapter` and ` php-http/message`, then use the libaray as normal.

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,17 @@ $provider = new \League\OAuth2\Client\Provider\GenericProvider([
249249
Via Composer
250250

251251
``` bash
252-
$ composer require league/oauth2-client
252+
$ composer require league/oauth2-client php-http/guzzle6-adapter php-http/message
253253
```
254254

255+
The two extra packages from `php-http` is part of the [HTTPlug](http://httplug.io/) organisation. It helps us not to
256+
be coupled to Guzzle. That is why you need to install the `php-http/guzzle6-adapter` or any other library providing the virtual
257+
[php-http/client-implementation](https://packagist.org/providers/php-http/client-implementation) package. The
258+
`php-http/message` package contains factory classes to create Guzzle and Diactoros PSR-7 requests.
259+
260+
You can read more about HTTPlug and how to use it in
261+
[their documentation](http://docs.php-http.org/en/latest/httplug/users.html).
262+
255263
## Contributing
256264

257265
Please see [CONTRIBUTING](https://github.com/thephpleague/oauth2-client/blob/master/CONTRIBUTING.md) for details.

composer.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,23 @@
44
"license": "MIT",
55
"require": {
66
"php": ">=5.5.0",
7+
"psr/http-message": "^1.0",
78
"ext-curl": "*",
89
"ircmaxell/random-lib": "~1.1",
9-
"guzzlehttp/guzzle": "~6.0"
10+
"php-http/httplug": "^1.0",
11+
"php-http/client-implementation": "^1.0",
12+
"php-http/message-factory": "^1.0.2",
13+
"php-http/discovery": "^1.0"
1014
},
1115
"require-dev": {
1216
"phpunit/phpunit": "~4.0",
1317
"mockery/mockery": "~0.9",
1418
"squizlabs/php_codesniffer": "~2.0",
1519
"satooshi/php-coveralls": "0.6.*",
16-
"jakub-onderka/php-parallel-lint": "0.8.*"
20+
"php-http/message": "^1.0",
21+
"php-http/guzzle6-adapter": "^1.0",
22+
"jakub-onderka/php-parallel-lint": "0.8.*",
23+
"symfony/phpunit-bridge": "^3.1"
1724
},
1825
"keywords": [
1926
"oauth",

src/Provider/AbstractProvider.php

Lines changed: 103 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
namespace League\OAuth2\Client\Provider;
1616

17-
use GuzzleHttp\Client as HttpClient;
18-
use GuzzleHttp\ClientInterface as HttpClientInterface;
19-
use GuzzleHttp\Exception\BadResponseException;
17+
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
18+
use GuzzleHttp\Client as GuzzleClient;
19+
use Http\Adapter\Guzzle6\Client as HttplugGuzzle6;
20+
use Http\Client\HttpClient;
21+
use Http\Discovery\HttpClientDiscovery;
2022
use League\OAuth2\Client\Grant\AbstractGrant;
2123
use League\OAuth2\Client\Grant\GrantFactory;
2224
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
@@ -85,7 +87,7 @@ abstract class AbstractProvider
8587
protected $requestFactory;
8688

8789
/**
88-
* @var HttpClientInterface
90+
* @var \Http\Client\HttpClient
8991
*/
9092
protected $httpClient;
9193

@@ -94,6 +96,19 @@ abstract class AbstractProvider
9496
*/
9597
protected $randomFactory;
9698

99+
/**
100+
* The options given to the Guzzle6 client
101+
* @var array
102+
* @deprecated These are to be removed in the next major release. These options are only used in getHttpClient to keep BC.
103+
*/
104+
private $guzzle6Options = [];
105+
106+
/**
107+
* @var GuzzleClientInterface
108+
* @deprecated This client is only used in getHttpClient to keep BC.
109+
*/
110+
private $guzzleClient;
111+
97112
/**
98113
* Constructs an OAuth 2.0 service provider.
99114
*
@@ -123,14 +138,7 @@ public function __construct(array $options = [], array $collaborators = [])
123138
}
124139
$this->setRequestFactory($collaborators['requestFactory']);
125140

126-
if (empty($collaborators['httpClient'])) {
127-
$client_options = $this->getAllowedClientOptions($options);
128-
129-
$collaborators['httpClient'] = new HttpClient(
130-
array_intersect_key($options, array_flip($client_options))
131-
);
132-
}
133-
$this->setHttpClient($collaborators['httpClient']);
141+
$this->setHttpClient($this->getHttpClientFromOptions($options, $collaborators));
134142

135143
if (empty($collaborators['randomFactory'])) {
136144
$collaborators['randomFactory'] = new RandomFactory();
@@ -207,11 +215,24 @@ public function getRequestFactory()
207215
/**
208216
* Sets the HTTP client instance.
209217
*
210-
* @param HttpClientInterface $client
218+
* @param HttpClient $client
211219
* @return self
212220
*/
213-
public function setHttpClient(HttpClientInterface $client)
221+
public function setHttpClient($client)
214222
{
223+
if ($client instanceof GuzzleClientInterface) {
224+
trigger_error(sprintf('Passing a "%s" to "%s::setHttpClient" is deprecated. Please use a "Http\Client\HttpClient" instead.', GuzzleClientInterface::class, static::class), E_USER_DEPRECATED);
225+
if (!class_exists(HttplugGuzzle6::class)) {
226+
throw new \RuntimeException(sprintf('You must install "php-http/guzzle6-adapter" to be able to pass a "%s" to "%s::setHttpClient".', GuzzleClientInterface::class, static::class));
227+
}
228+
$client = new HttplugGuzzle6($client);
229+
}
230+
231+
if (!$client instanceof HttpClient) {
232+
$type = is_object($client) ? get_class($client) : gettype($client);
233+
throw new \RuntimeException(sprintf('First parameter to "%s::setHttpClient" was expected to be a "Http\Client\HttpClient", you provided a "%s"', static::class, $type));
234+
}
235+
215236
$this->httpClient = $client;
216237

217238
return $this;
@@ -220,13 +241,33 @@ public function setHttpClient(HttpClientInterface $client)
220241
/**
221242
* Returns the HTTP client instance.
222243
*
223-
* @return HttpClientInterface
244+
* @return HttpClient
224245
*/
225-
public function getHttpClient()
246+
public function getHttplugClient()
226247
{
227248
return $this->httpClient;
228249
}
229250

251+
/**
252+
* Returns the HTTP client instance.
253+
*
254+
* @return GuzzleClientInterface
255+
*/
256+
public function getHttpClient()
257+
{
258+
trigger_error(sprintf('Using "%s::getHttpClient" is deprecated in favor for "%s::getHttplugClient".', static::class, static::class), E_USER_DEPRECATED);
259+
260+
if ($this->guzzleClient !== null) {
261+
return $this->guzzleClient;
262+
}
263+
264+
if (!class_exists(GuzzleClient::class)) {
265+
throw new \RuntimeException('You must install "php-http/guzzle6-adapter" to be able to use "%s::getHttplugClient".', static::class);
266+
}
267+
268+
return new GuzzleClient($this->guzzle6Options);
269+
}
270+
230271
/**
231272
* Sets the instance of the CSPRNG random generator factory.
232273
*
@@ -621,12 +662,7 @@ protected function createRequest($method, $url, $token, array $options)
621662
*/
622663
protected function sendRequest(RequestInterface $request)
623664
{
624-
try {
625-
$response = $this->getHttpClient()->send($request);
626-
} catch (BadResponseException $e) {
627-
$response = $e->getResponse();
628-
}
629-
return $response;
665+
return $this->getHttplugClient()->sendRequest($request);
630666
}
631667

632668
/**
@@ -840,4 +876,49 @@ public function getHeaders($token = null)
840876

841877
return $this->getDefaultHeaders();
842878
}
879+
880+
/**
881+
* Get a HttpClient from constructor options
882+
*
883+
* @param array $options
884+
* @param array $collaborators
885+
*
886+
* @return HttpClient
887+
*/
888+
private function getHttpClientFromOptions(array $options, array $collaborators)
889+
{
890+
if (!empty($collaborators['httplugClient'])) {
891+
// Use provided client
892+
return $collaborators['httplugClient'];
893+
}
894+
895+
if (empty($collaborators['httpClient'])) {
896+
$client_options = $this->getAllowedClientOptions($options);
897+
$guzzle6Options = array_intersect_key($options, array_flip($client_options));
898+
899+
if (empty($guzzle6Options)) {
900+
return HttpClientDiscovery::find();
901+
} else {
902+
trigger_error('Passing options to Guzzle6 client is deprecated. Use "httplugClient" instead', E_USER_DEPRECATED);
903+
if (!class_exists(HttplugGuzzle6::class)) {
904+
throw new \RuntimeException('You must install "php-http/guzzle6-adapter" to be able to pass options to the Guzzle6 client.');
905+
}
906+
$this->guzzle6Options = $guzzle6Options;
907+
return HttplugGuzzle6::createWithConfig($guzzle6Options);
908+
}
909+
}
910+
911+
trigger_error('The "httpClient" option is deprecated. Use "httplugClient" instead', E_USER_DEPRECATED);
912+
$client = $collaborators['httpClient'];
913+
if (!$client instanceof GuzzleClientInterface) {
914+
throw new \RuntimeException(sprintf('The value provided with option "HttpClient" must be instance of "%s".', GuzzleClientInterface::class));
915+
}
916+
917+
if (!class_exists(HttplugGuzzle6::class)) {
918+
throw new \RuntimeException('You must install "php-http/guzzle6-adapter" to be able to pass a Guzzle6 client with "httpClient" option.');
919+
}
920+
921+
$this->guzzleClient = $client;
922+
return new HttplugGuzzle6($client);
923+
}
843924
}

src/Tool/RequestFactory.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414

1515
namespace League\OAuth2\Client\Tool;
1616

17-
use GuzzleHttp\Psr7\Request;
17+
use Http\Discovery\MessageFactoryDiscovery;
18+
use Psr\Http\Message\RequestInterface;
19+
use Psr\Http\Message\StreamInterface;
20+
1821

1922
/**
2023
* Used to produce PSR-7 Request instances.
@@ -23,6 +26,11 @@
2326
*/
2427
class RequestFactory
2528
{
29+
/**
30+
* @var \Http\Message\RequestFactory
31+
*/
32+
private $factory;
33+
2634
/**
2735
* Creates a PSR-7 Request instance.
2836
*
@@ -32,7 +40,7 @@ class RequestFactory
3240
* @param string|resource|StreamInterface $body Message body.
3341
* @param string $version HTTP protocol version.
3442
*
35-
* @return Request
43+
* @return RequestInterface
3644
*/
3745
public function getRequest(
3846
$method,
@@ -41,7 +49,11 @@ public function getRequest(
4149
$body = null,
4250
$version = '1.1'
4351
) {
44-
return new Request($method, $uri, $headers, $body, $version);
52+
if (!$this->factory) {
53+
$this->factory = MessageFactoryDiscovery::find();
54+
}
55+
56+
return $this->factory->createRequest($method, $uri, $headers, $body, $version);
4557
}
4658

4759
/**
@@ -70,7 +82,7 @@ protected function parseOptions(array $options)
7082
* @param null|string $uri
7183
* @param array $options
7284
*
73-
* @return Request
85+
* @return RequestInterface
7486
*/
7587
public function getRequestWithOptions($method, $uri, array $options = [])
7688
{

test/src/Grant/GrantTestCase.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace League\OAuth2\Client\Test\Grant;
44

5-
use GuzzleHttp\ClientInterface;
5+
use Http\Client\HttpClient;
66
use Psr\Http\Message\ResponseInterface;
77
use Psr\Http\Message\StreamInterface;
88
use League\OAuth2\Client\Token\AccessToken;
@@ -44,7 +44,7 @@ abstract public function providerGetAccessToken();
4444
/**
4545
* Callback to test access token request parameters.
4646
*
47-
* @return Closure
47+
* @return \Closure
4848
*/
4949
abstract protected function getParamExpectation();
5050

@@ -64,8 +64,8 @@ public function testGetAccessToken($grant, array $params = [])
6464

6565
$paramCheck = $this->getParamExpectation();
6666

67-
$client = m::mock(ClientInterface::class);
68-
$client->shouldReceive('send')->with(
67+
$client = m::mock(HttpClient::class);
68+
$client->shouldReceive('sendRequest')->with(
6969
$request = m::on(function ($request) use ($paramCheck) {
7070
parse_str((string) $request->getBody(), $body);
7171
return $paramCheck($body);

0 commit comments

Comments
 (0)