Skip to content

Commit 1e9e7c8

Browse files
feat: add support for Guzzle 8
Signed-off-by: Graham Campbell <hello@gjcampbell.co.uk>
1 parent f745b31 commit 1e9e7c8

8 files changed

Lines changed: 59 additions & 48 deletions

File tree

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
"google/apiclient-services": "~0.350",
1414
"firebase/php-jwt": "^6.0||^7.0",
1515
"monolog/monolog": "^2.9||^3.0",
16-
"guzzlehttp/guzzle": "^7.4.5",
17-
"guzzlehttp/psr7": "^2.6"
16+
"guzzlehttp/guzzle": "^7.8.2||^8.0",
17+
"guzzlehttp/psr7": "^2.6.3||^3.0"
1818
},
1919
"require-dev": {
2020
"squizlabs/php_codesniffer": "^3.8",

phpstan.neon.dist

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,11 @@ parameters:
33
level: 5
44
paths:
55
- src
6+
ignoreErrors:
7+
# On Guzzle 7 the base RequestException has getResponse(), so the
8+
# method_exists() guard is statically true; it stays for the Guzzle 8
9+
# code path, where the response lives only on the ResponseException
10+
# subclass.
11+
-
12+
message: '#^Call to function method_exists\(\) with GuzzleHttp\\Exception\\RequestException and ''getResponse'' will always evaluate to true\.$#'
13+
path: src/Http/REST.php

src/AuthHandler/AuthHandlerFactory.php

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,9 @@ class AuthHandlerFactory
3030
*/
3131
public static function build($cache = null, array $cacheConfig = [])
3232
{
33-
$guzzleVersion = null;
34-
if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
35-
$guzzleVersion = ClientInterface::MAJOR_VERSION;
36-
} elseif (defined('\GuzzleHttp\ClientInterface::VERSION')) {
37-
$guzzleVersion = (int) substr(ClientInterface::VERSION, 0, 1);
38-
}
39-
40-
switch ($guzzleVersion) {
41-
case 6:
42-
return new Guzzle6AuthHandler($cache, $cacheConfig);
33+
switch (ClientInterface::MAJOR_VERSION) {
4334
case 7:
35+
case 8:
4436
return new Guzzle7AuthHandler($cache, $cacheConfig);
4537
default:
4638
throw new Exception('Version not supported');

src/AuthHandler/Guzzle6AuthHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use Psr\Cache\CacheItemPoolInterface;
1414

1515
/**
16-
* This supports Guzzle 6
16+
* @deprecated Guzzle 6 is no longer supported; use Guzzle7AuthHandler.
1717
*/
1818
class Guzzle6AuthHandler
1919
{

src/Client.php

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
use Google\Http\REST;
3636
use GuzzleHttp\Client as GuzzleClient;
3737
use GuzzleHttp\ClientInterface;
38-
use GuzzleHttp\Ring\Client\StreamHandler;
3938
use InvalidArgumentException;
4039
use LogicException;
4140
use Monolog\Handler\StreamHandler as MonologStreamHandler;
@@ -1239,34 +1238,10 @@ public function setApiFormatV2($value)
12391238

12401239
protected function createDefaultHttpClient()
12411240
{
1242-
$guzzleVersion = null;
1243-
if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
1244-
$guzzleVersion = ClientInterface::MAJOR_VERSION;
1245-
} elseif (defined('\GuzzleHttp\ClientInterface::VERSION')) {
1246-
$guzzleVersion = (int)substr(ClientInterface::VERSION, 0, 1);
1247-
}
1248-
1249-
if (5 === $guzzleVersion) {
1250-
$options = [
1251-
'base_url' => $this->config['base_path'],
1252-
'defaults' => ['exceptions' => false],
1253-
];
1254-
if ($this->isAppEngine()) {
1255-
if (class_exists(StreamHandler::class)) {
1256-
// set StreamHandler on AppEngine by default
1257-
$options['handler'] = new StreamHandler();
1258-
$options['defaults']['verify'] = '/etc/ca-certificates.crt';
1259-
}
1260-
}
1261-
} elseif (6 === $guzzleVersion || 7 === $guzzleVersion) {
1262-
// guzzle 6 or 7
1263-
$options = [
1264-
'base_uri' => $this->config['base_path'],
1265-
'http_errors' => false,
1266-
];
1267-
} else {
1268-
throw new LogicException('Could not find supported version of Guzzle.');
1269-
}
1241+
$options = [
1242+
'base_uri' => $this->config['base_path'],
1243+
'http_errors' => false,
1244+
];
12701245

12711246
return new GuzzleClient($options);
12721247
}

src/Http/REST.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,12 @@ public static function doExecute(ClientInterface $client, RequestInterface $requ
8484
$response = $httpHandler($request);
8585
} catch (RequestException $e) {
8686
// if Guzzle throws an exception, catch it and handle the response
87-
if (!$e->hasResponse()) {
87+
// (on Guzzle 7 the response is on RequestException, but on Guzzle 8
88+
// it is only on its ResponseException subclass)
89+
$response = method_exists($e, 'getResponse') ? $e->getResponse() : null;
90+
if (null === $response) {
8891
throw $e;
8992
}
90-
91-
$response = $e->getResponse();
9293
}
9394

9495
return self::decodeHttpResponse($response, $request, $expectedClass);

tests/Google/ClientTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,13 @@ private function checkAuthHandler($http, $className)
6868
$property = $class->getProperty('stack');
6969
$property->setAccessible(true);
7070
$middlewares = $property->getValue($stack);
71-
$middleware = array_pop($middlewares);
7271

7372
if (null === $className) {
7473
// only the default middlewares have been added
75-
$this->assertCount(3, $middlewares);
74+
$defaultStack = (new GuzzleClient())->getConfig('handler');
75+
$this->assertCount(count($property->getValue($defaultStack)), $middlewares);
7676
} else {
77+
$middleware = array_pop($middlewares);
7778
$authClass = sprintf('Google\Auth\Middleware\%sMiddleware', $className);
7879
$this->assertInstanceOf($authClass, $middleware[0]);
7980
}
@@ -904,7 +905,7 @@ public function testCredentialsOptionWithFetchAuthTokenInterface()
904905
$callable(new Request('GET', '/fake-uri'), ['auth' => 'google_auth']);
905906
});
906907

907-
$httpClient = $this->prophesize('GuzzleHttp\ClientInterface');
908+
$httpClient = $this->prophesize('GuzzleHttp\Client');
908909
$httpClient->getConfig()
909910
->shouldBeCalled()
910911
->willReturn(['handler' => $handler->reveal()]);

tests/Google/Http/RESTTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@
2121
use Google\Service\Exception as ServiceException;
2222
use Google\Tests\BaseTest;
2323
use GuzzleHttp\Client as GuzzleClient;
24+
use GuzzleHttp\Exception\ClientException;
25+
use GuzzleHttp\Exception\RequestException;
2426
use GuzzleHttp\Psr7;
2527
use GuzzleHttp\Psr7\Request;
2628
use GuzzleHttp\Psr7\Response;
29+
use Prophecy\Argument;
2730

2831
class RESTTest extends BaseTest
2932
{
@@ -86,6 +89,37 @@ public function testExceptionResponse()
8689
$response = $this->rest->doExecute($http, $request);
8790
}
8891

92+
public function testRequestExceptionWithResponseIsHandled()
93+
{
94+
$this->expectException(ServiceException::class);
95+
$this->expectExceptionCode(400);
96+
97+
$request = new Request('GET', 'http://www.example.com');
98+
$response = new Response(400, [], Psr7\Utils::streamFor('{"error": "bad request"}'));
99+
100+
$http = $this->prophesize('GuzzleHttp\ClientInterface');
101+
$http->send(Argument::type('Psr\Http\Message\RequestInterface'), [])
102+
->shouldBeCalledTimes(1)
103+
->willThrow(new ClientException('Bad Request', $request, $response));
104+
105+
$this->rest->doExecute($http->reveal(), $request);
106+
}
107+
108+
public function testRequestExceptionWithoutResponseIsRethrown()
109+
{
110+
$this->expectException(RequestException::class);
111+
$this->expectExceptionMessage('Request failed');
112+
113+
$request = new Request('GET', 'http://www.example.com');
114+
115+
$http = $this->prophesize('GuzzleHttp\ClientInterface');
116+
$http->send(Argument::type('Psr\Http\Message\RequestInterface'), [])
117+
->shouldBeCalledTimes(1)
118+
->willThrow(new RequestException('Request failed', $request));
119+
120+
$this->rest->doExecute($http->reveal(), $request);
121+
}
122+
89123
public function testDecodeEmptyResponse()
90124
{
91125
$stream = Psr7\Utils::streamFor('{}');

0 commit comments

Comments
 (0)