Skip to content

Commit 4867539

Browse files
Hasanhhn
authored andcommitted
Introduce ResponseParsingException and throw this exception in AbstractProvider::parseResponse() if necessary
1 parent 4276bb0 commit 4867539

File tree

5 files changed

+175
-10
lines changed

5 files changed

+175
-10
lines changed

src/Provider/AbstractProvider.php

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use League\OAuth2\Client\OptionProvider\OptionProviderInterface;
2323
use League\OAuth2\Client\OptionProvider\PostAuthOptionProvider;
2424
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
25+
use League\OAuth2\Client\Provider\Exception\ResponseParsingException;
2526
use League\OAuth2\Client\Token\AccessToken;
2627
use League\OAuth2\Client\Token\AccessTokenInterface;
2728
use League\OAuth2\Client\Tool\ArrayAccessorTrait;
@@ -98,6 +99,15 @@ abstract class AbstractProvider
9899
*/
99100
protected $optionProvider;
100101

102+
/**
103+
* If a response body cannot be parsed, a value true of this flag will allow
104+
* the response parser to throw a ResponseParsingException containing
105+
* the response and the body.
106+
*
107+
* @var bool
108+
*/
109+
protected $mayThrowResponseParsingException = false;
110+
101111
/**
102112
* Constructs an OAuth 2.0 service provider.
103113
*
@@ -520,6 +530,8 @@ protected function getAccessTokenRequest(array $params)
520530
* @param mixed $grant
521531
* @param array $options
522532
* @throws IdentityProviderException
533+
* @throws ResponseParsingException if the flag $mayThrowResponseParsingException is true and
534+
* response body cannot be parsed.
523535
* @return AccessTokenInterface
524536
*/
525537
public function getAccessToken($grant, array $options = [])
@@ -613,6 +625,8 @@ public function getResponse(RequestInterface $request)
613625
*
614626
* @param RequestInterface $request
615627
* @throws IdentityProviderException
628+
* @throws ResponseParsingException if the flag $mayThrowResponseParsingException is true and
629+
* response body cannot be parsed.
616630
* @return mixed
617631
*/
618632
public function getParsedResponse(RequestInterface $request)
@@ -666,8 +680,10 @@ protected function getContentType(ResponseInterface $response)
666680
* Parses the response according to its content-type header.
667681
*
668682
* @throws UnexpectedValueException
683+
* @throws ResponseParsingException if the flag $mayThrowResponseParsingException is true and
684+
* response body cannot be parsed.
669685
* @param ResponseInterface $response
670-
* @return array
686+
* @return array|string
671687
*/
672688
protected function parseResponse(ResponseInterface $response)
673689
{
@@ -686,18 +702,26 @@ protected function parseResponse(ResponseInterface $response)
686702
return $this->parseJson($content);
687703
} catch (UnexpectedValueException $e) {
688704
if (strpos($type, 'json') !== false) {
689-
throw $e;
705+
throw $this->mayThrowResponseParsingException
706+
? new ResponseParsingException($response, $content, $e->getMessage(), $e->getCode())
707+
: $e;
690708
}
691709

692-
if ($response->getStatusCode() == 500) {
693-
throw new UnexpectedValueException(
694-
'An OAuth server error was encountered that did not contain a JSON body',
695-
0,
696-
$e
697-
);
710+
// for any other content types
711+
if ($this->mayThrowResponseParsingException) {
712+
// let the calling function decide what to do with the response and its body
713+
throw new ResponseParsingException($response, $content, '', 0);
714+
} else {
715+
if ($response->getStatusCode() == 500) {
716+
throw new UnexpectedValueException(
717+
'An OAuth server error was encountered that did not contain a JSON body',
718+
0,
719+
$e
720+
);
721+
}
722+
723+
return $content;
698724
}
699-
700-
return $content;
701725
}
702726
}
703727

@@ -774,6 +798,8 @@ public function getResourceOwner(AccessToken $token)
774798
*
775799
* @param AccessToken $token
776800
* @return mixed
801+
* @throws ResponseParsingException if the flag $mayThrowResponseParsingException is true and
802+
* response body cannot be parsed.
777803
*/
778804
protected function fetchResourceOwnerDetails(AccessToken $token)
779805
{
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
/**
3+
* This file is part of the league/oauth2-client library
4+
*
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*
8+
* @copyright Copyright (c) Alex Bilbie <[email protected]>
9+
* @license http://opensource.org/licenses/MIT MIT
10+
* @link http://thephpleague.com/oauth2-client/ Documentation
11+
* @link https://packagist.org/packages/league/oauth2-client Packagist
12+
* @link https://github.com/thephpleague/oauth2-client GitHub
13+
*/
14+
15+
namespace League\OAuth2\Client\Provider\Exception;
16+
17+
use Exception;
18+
use Psr\Http\Message\ResponseInterface;
19+
20+
/**
21+
* Exception thrown if the parser cannot parse the provider response.
22+
*/
23+
class ResponseParsingException extends Exception
24+
{
25+
/**
26+
* @var ResponseInterface
27+
*/
28+
protected $response;
29+
30+
/**
31+
* @var string
32+
*/
33+
protected $responseBody;
34+
35+
/**
36+
* @param ResponseInterface $response The response
37+
* @param string $responseBody The response body
38+
* @param null $message
39+
* @param int $code
40+
*/
41+
public function __construct(
42+
ResponseInterface $response,
43+
$responseBody,
44+
$message = null,
45+
$code = 0
46+
) {
47+
$this->response = $response;
48+
$this->responseBody = $responseBody;
49+
50+
if (null === $message) {
51+
$message = sprintf('Cannot parse response body: "%s"', $responseBody);
52+
}
53+
54+
parent::__construct($message, $code);
55+
}
56+
57+
/**
58+
* Returns the exception's response.
59+
*
60+
* @return ResponseInterface
61+
*/
62+
public function getResponse()
63+
{
64+
return $this->response;
65+
}
66+
67+
/**
68+
* Returns the exception's response body.
69+
*
70+
* @return string
71+
*/
72+
public function getResponseBody()
73+
{
74+
return $this->responseBody;
75+
}
76+
}

test/src/Provider/AbstractProviderTest.php

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

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

5+
use League\OAuth2\Client\Provider\Exception\ResponseParsingException;
56
use UnexpectedValueException;
67
use Eloquent\Liberator\Liberator;
78
use Eloquent\Phony\Phpunit\Phony;
@@ -624,6 +625,21 @@ public function testParseResponseNonJsonFailure()
624625
$this->testParseResponse('<xml></xml>', 'application/xml', null, 500);
625626
}
626627

628+
public function testResponseParsingException()
629+
{
630+
$this->provider->allowResponseParsingException();
631+
$exception = null;
632+
try {
633+
$this->testParseResponse('', '', null, 401);
634+
} catch (ResponseParsingException $exception) {
635+
}
636+
$this->assertInstanceOf(ResponseParsingException::class, $exception);
637+
$response = $exception->getResponse();
638+
$this->assertSame(401, $response->getStatusCode());
639+
$this->assertSame('', $exception->getResponseBody());
640+
$this->provider->disallowResponseParsingException();
641+
}
642+
627643
public function getAppendQueryProvider()
628644
{
629645
return [
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace League\OAuth2\Client\Test\Provider\Exception;
4+
5+
use GuzzleHttp\Psr7\Response;
6+
use League\OAuth2\Client\Provider\Exception\ResponseParsingException;
7+
use PHPUnit\Framework\TestCase;
8+
use Psr\Http\Message\ResponseInterface;
9+
10+
class ResponseParsingExceptionTest extends TestCase
11+
{
12+
protected $result;
13+
14+
/**
15+
* @var ResponseParsingException
16+
*/
17+
protected $exception;
18+
19+
protected function setUp()
20+
{
21+
$this->result = [
22+
'response' => new Response('401'),
23+
'body' => ''
24+
];
25+
$this->exception = new ResponseParsingException($this->result['response'], $this->result['body']);
26+
}
27+
28+
public function testGetResponse()
29+
{
30+
$this->assertInstanceOf(ResponseInterface::class, $this->exception->getResponse());
31+
}
32+
33+
public function testGetResponseBody()
34+
{
35+
$this->assertSame($this->result['body'], $this->exception->getResponseBody());
36+
}
37+
}

test/src/Provider/Fake.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ public function getAccessTokenMethod()
4444
return $this->accessTokenMethod;
4545
}
4646

47+
public function allowResponseParsingException()
48+
{
49+
$this->mayThrowResponseParsingException = true;
50+
}
51+
52+
public function disallowResponseParsingException()
53+
{
54+
$this->mayThrowResponseParsingException = false;
55+
}
56+
4757
protected function createResourceOwner(array $response, AccessToken $token)
4858
{
4959
return new Fake\User($response);

0 commit comments

Comments
 (0)