Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add response id to request error. (bunq/sdk_php#88) #93

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c77832d
Added response id header constants. (bunq/sdk_php#88)
OGKevin Dec 26, 2017
1b3aaa5
Added new responseId field to base exception class. (bunq/sdk_php#88)
OGKevin Dec 26, 2017
1bd4279
Altered generateErrorMessage to also include the response id in the e…
OGKevin Dec 26, 2017
d1ff10b
Pass the response id to the exceptions in ExceptionFactory. (bunq/sdk…
OGKevin Dec 26, 2017
872c4a0
Added missing spaces for better method formatting. (bunq/sdk_php#88)
OGKevin Dec 26, 2017
e201559
Added error constant in case response header retrieval fails. (bunq/s…
OGKevin Dec 26, 2017
33b8e35
Added method to get the response id from the failed request response.…
OGKevin Dec 26, 2017
1a182a6
Added test to make sure that the response header can be retrieved fro…
OGKevin Dec 26, 2017
ad04c24
Optimised imports. (bunq/sdk_php#88)
OGKevin Dec 26, 2017
c3c5089
Removed plural variables. (bunq/sdk_php#88)
OGKevin Dec 27, 2017
f7178b7
Changed constant name of GLUE_ERROR_MESSAGES to SEPARATOR_ERROR_MESSA…
OGKevin Dec 27, 2017
041550b
Removed unneeded empty new line. (bunq/sdk_php#88)
OGKevin Dec 27, 2017
cd65652
Extracted magic value. (bunq/sdk_php#88)
OGKevin Dec 27, 2017
f96b6b6
Fixed typo in caughtExcretion to caughtException. (bunq/sdk_php#88)
OGKevin Dec 27, 2017
1f8fbf3
Removed plural from glueMessages. (bunq/sdk_php#88)
OGKevin Dec 27, 2017
c9a2379
Removed plural parameter from glueAllMessage. (bunq/sdk_php#88)
OGKevin Dec 27, 2017
3653cf3
Reanmed response header constants to the propper name. (bunq/sdk_php#88)
OGKevin Dec 30, 2017
f040d04
Merge branch 'develop' into feature/bunq/sdk_php#88-add_response_id_t…
andrederoos Jan 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/Exception/ApiException.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,32 @@ class ApiException extends Exception
*/
private $responseCode;

/**
* @var string
*/
private $responseId;

/**
* @param string $message
* @param int $responseCode
* @param string $responseId
*/
public function __construct(string $message, int $responseCode)
public function __construct(string $message, int $responseCode, string $responseId)
{
$this->responseCode = $responseCode;
$this->responseId = $responseId;

parent::__construct($message);
}

/**
* @return string
*/
public function getResponseId(): string
{
return $this->responseId;
}

/**
* @return int
*/
Expand Down
62 changes: 40 additions & 22 deletions src/Exception/ExceptionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,64 +20,82 @@ class ExceptionFactory
* Formatting constants
*/
const FORMAT_RESPONSE_CODE_LINE = 'HTTP Response Code: %s';
const GLUE_ERROR_MESSAGES = "\n";
const FORMAT_RESPONSE_ID = 'The response id to help bunq debug: %s';
const FORMAT_ERROR_MESSAGE_LINE = 'Error message: %s';

/**
* String separator constants
*/
const SEPARATOR_ERROR_MESSAGES = "\n";

/**
* The first item index in an array.
*/
const INDEX_FIRST = 0;

/**
* @param string[] $messages
* @param string[] $allMessage
* @param int $responseCode
* @param string $responseId
*
* @return ApiException
*/
public static function createExceptionForResponse(array $messages, int $responseCode): ApiException
{
$errorMessage = static::generateErrorMessage($responseCode, $messages);
public static function createExceptionForResponse(
array $allMessage,
int $responseCode,
string $responseId
): ApiException {
$errorMessage = static::generateErrorMessage($responseCode, $allMessage, $responseId);

switch ($responseCode)
{
switch ($responseCode) {
case self::HTTP_RESPONSE_CODE_BAD_REQUEST:
return new BadRequestException($errorMessage, $responseCode);
return new BadRequestException($errorMessage, $responseCode, $responseId);
case self::HTTP_RESPONSE_CODE_UNAUTHORIZED:
return new UnauthorizedException($errorMessage, $responseCode);
return new UnauthorizedException($errorMessage, $responseCode, $responseId);
case self::HTTP_RESPONSE_CODE_FORBIDDEN:
return new ForbiddenException($errorMessage, $responseCode);
return new ForbiddenException($errorMessage, $responseCode, $responseId);
case self::HTTP_RESPONSE_CODE_NOT_FOUND:
return new NotFoundException($errorMessage, $responseCode);
return new NotFoundException($errorMessage, $responseCode, $responseId);
case self::HTTP_RESPONSE_CODE_METHOD_NOT_ALLOWED:
return new MethodNotAllowedException($errorMessage, $responseCode);
return new MethodNotAllowedException($errorMessage, $responseCode, $responseId);
case self::HTTP_RESPONSE_CODE_TOO_MANY_REQUESTS:
return new TooManyRequestsException($errorMessage, $responseCode);
return new TooManyRequestsException($errorMessage, $responseCode, $responseId);
case self::HTTP_RESPONSE_CODE_INTERNAL_SERVER_ERROR:
return new PleaseContactBunqException($errorMessage, $responseCode);
return new PleaseContactBunqException($errorMessage, $responseCode, $responseId);
default:
return new UnknownApiErrorException($errorMessage, $responseCode);
return new UnknownApiErrorException($errorMessage, $responseCode, $responseId);
}
}

/**
* @param int $responseCode
* @param string[] $messages
* @param string[] $allMessage
* @param string $responseId
*
* @return string
*/
private static function generateErrorMessage(int $responseCode, array $messages): string
{
private static function generateErrorMessage(
int $responseCode,
array $allMessage,
string $responseId
): string {
$lineResponseCode = sprintf(self::FORMAT_RESPONSE_CODE_LINE, $responseCode);
$lineResponseId = sprintf(self::FORMAT_RESPONSE_ID, $responseId);
$lineErrorMessage = sprintf(
self::FORMAT_ERROR_MESSAGE_LINE,
implode($allMessage)
);

return static::glueMessages(array_merge([$lineResponseCode], $messages));
return static::glueAllMessage([$lineResponseCode, $lineResponseId, $lineErrorMessage]);
}

/**
* @param string[] $messages
* @param string[] $allMessage
*
* @return string
*/
private static function glueMessages(array $messages): string
private static function glueAllMessage(array $allMessage): string
{
return implode(self::GLUE_ERROR_MESSAGES, $messages);
return implode(self::SEPARATOR_ERROR_MESSAGES, $allMessage);
}
}
1 change: 0 additions & 1 deletion src/Http/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Uri;
use phpDocumentor\Reflection\Types\Self_;
use Psr\Http\Message\ResponseInterface;

/**
Expand Down
60 changes: 50 additions & 10 deletions src/Http/Handler/ResponseHandlerError.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,42 @@
namespace bunq\Http\Handler;

use bunq\Exception\ApiException;
use bunq\Exception\BunqException;
use bunq\Exception\ExceptionFactory;
use Psr\Http\Message\ResponseInterface;

/**
*/
class ResponseHandlerError extends ResponseHandlerBase
{
/**
* Error constants.
*/
const ERROR_COULD_NOT_DETERMINE_RESPONSE_ID_HEADER =
'The response header "X-Bunq-Client-Response-Id" or "x-bunq-client-response-id" could not be found.';

/**
* Field constants.
*/
const FIELD_ERROR = 'Error';
const FIELD_ERROR_DESCRIPTION = 'error_description';

/**
* Header constants.
*/
const HEADER_BUNQ_CLIENT_RESPONSE_ID_UPPER_CASED = 'X-Bunq-Client-Response-Id';
const HEADER_BUNQ_CLIENT_RESPONSE_ID_LOWER_CASED = 'x-bunq-client-response-id';

/**
* Http status code constants.
*/
const STATUS_CODE_OK = 200;

/**
* The index of the first item in an array.
*/
const INDEX_FIRST = 0;

/**
* @param ResponseInterface $response
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@return

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid, as you can see this particular line has not been changed in this pr and therefore only a snippet of the doc block is show. If you look at the original file you see that this doc block is correct 🙃 see:

* @return ResponseInterface

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, missed that one. Ignore then. 😄

Expand All @@ -29,10 +47,11 @@ class ResponseHandlerError extends ResponseHandlerBase
*/
public function execute(ResponseInterface $response): ResponseInterface
{
if ($response->getStatusCode() !== self::STATUS_CODE_OK){
if ($response->getStatusCode() !== self::STATUS_CODE_OK) {
throw ExceptionFactory::createExceptionForResponse(
$this->fetchErrorMessages($response),
$response->getStatusCode()
$response->getStatusCode(),
$this->getResponseId($response)
);
}

Expand All @@ -49,9 +68,9 @@ private function fetchErrorMessages(ResponseInterface $response): array
$responseBody = $response->getBody();
$responseBodyInJson = json_decode($responseBody, true);

if ($responseBodyInJson !== false){
return $this->fetchErrorDescriptions($responseBodyInJson);
}else{
if ($responseBodyInJson !== false) {
return $this->fetchAllErrorDescription($responseBodyInJson);
} else {
return [$responseBody];
}
}
Expand All @@ -61,15 +80,36 @@ private function fetchErrorMessages(ResponseInterface $response): array
*
* @return string[]
*/
private function fetchErrorDescriptions(array $errorArray): array
private function fetchAllErrorDescription(array $errorArray): array
{
$errorDescriptions = [];
$allErrorDescription = [];

foreach ($errorArray[self::FIELD_ERROR] as $error){
foreach ($errorArray[self::FIELD_ERROR] as $error) {
$description = $error[self::FIELD_ERROR_DESCRIPTION];
$errorDescriptions[] = $description;
$allErrorDescription[] = $description;
}

return $allErrorDescription;
}

/**
* @param ResponseInterface $response
*
* @return string
* @throws BunqException
*/
private function getResponseId(ResponseInterface $response): string
{
$header = $response->getHeader(self::HEADER_BUNQ_CLIENT_RESPONSE_ID_UPPER_CASED);

if (empty($header)) {
$header = $response->getHeader(self::HEADER_BUNQ_CLIENT_RESPONSE_ID_UPPER_CASED);
}

if (empty($header)) {
throw new BunqException(self::ERROR_COULD_NOT_DETERMINE_RESPONSE_ID_HEADER);
}

return $errorDescriptions;
return $header[self::INDEX_FIRST];
}
}
33 changes: 33 additions & 0 deletions tests/Http/ErrorResponseIdTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
namespace bunq\test\Http;

use bunq\Exception\BadRequestException;
use bunq\Model\Generated\Endpoint\UserPerson;
use bunq\test\BunqSdkTestBase;

/**
* Tests if the response id from a failed request can be retrieved successfully.
*/
class ErrorResponseIdTest extends BunqSdkTestBase
{
/**
* Invalid user id to trigger BadRequestException
*/
const INVALID_USER_PERSON_ID = 0;

/**
*/
public function testBadRequestWitResponseId()
{
$caughtException = null;

try {
UserPerson::get(static::$apiContext, self::INVALID_USER_PERSON_ID);
} catch (BadRequestException $exception) {
$caughtException = $exception;
}

static::assertNotNull($caughtException);
static::assertNotNull($caughtException->getResponseId());
}
}