Skip to content

Commit

Permalink
Fix handling errors with empty body (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
sashabeton authored and Horat1us committed Jun 22, 2018
1 parent 282cafb commit b717029
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 108 deletions.
22 changes: 12 additions & 10 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,20 @@ public function verify(string $response, string $remoteIp = null): Response
/**
* @param array $jsonResponse
* @return Response
* @throws Exception
*/
protected function createResponse(array $jsonResponse): Response
{
$dateTime = \DateTime::createFromFormat(\DateTime::ATOM, $jsonResponse['challenge_ts']);
$dateTime = array_key_exists('challenge_ts', $jsonResponse)
? \DateTime::createFromFormat(\DateTime::ATOM, $jsonResponse['challenge_ts'])
: null;

$response = new Response(
$jsonResponse['success'],
$jsonResponse['score'],
$jsonResponse['action'],
$dateTime,
$jsonResponse['hostname'],
$jsonResponse['error_codes'] ?? []
$jsonResponse['hostname']
);

if (!$response->isSuccess()) {
throw new Exception($response);
}

return $response;
}

Expand All @@ -87,8 +82,15 @@ protected function parseJson(string $responseBody): array
);
}

if (!array_key_exists('success', $jsonResponse)) {
throw new \Exception('Missing required response attribute: success');
}

if ($jsonResponse['success'] === false) {
throw new Exception($jsonResponse['error-codes'] ?? []);
}

$requiredAttributes = [
'success',
'score',
'action',
'challenge_ts',
Expand Down
32 changes: 16 additions & 16 deletions src/Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,25 @@
* Class Exception
* @package Wearesho\ReCaptcha\V3
*/
class Exception extends \Exception implements ExceptionInterface
class Exception extends \Exception
{
const MISSING_INPUT_SECRET = 'missing-input-secret';
const INVALID_INPUT_SECRET = 'invalid-input-secret';
const MISSING_INPUT_RESPONSE = 'missing-input-response';
const INVALID_INPUT_RESPONSE = 'invalid-input-response';
const BAD_REQUEST = 'bad-request';
public const MISSING_INPUT_SECRET = 'missing-input-secret';
public const INVALID_INPUT_SECRET = 'invalid-input-secret';
public const MISSING_INPUT_RESPONSE = 'missing-input-response';
public const INVALID_INPUT_RESPONSE = 'invalid-input-response';
public const BAD_REQUEST = 'bad-request';

/** @var Response */
protected $response;
/** @var array */
protected $errors;

public function __construct(Response $response, int $code = 0, Throwable $previous = null)
public function __construct(array $errors, int $code = 0, Throwable $previous = null)
{
$message = implode(
', ',
array_map([$this, 'getMessageByCode',], $response->getErrors())
array_map([$this, 'getMessageByCode',], $errors)
);
parent::__construct($message, $code, $previous);
$this->response = $response;
}

public function getResponse(): Response
{
return $this->response;
$this->errors = $errors;
}

public function getMessageByCode(string $code): string
Expand All @@ -50,4 +45,9 @@ public function getMessageByCode(string $code): string
}
return $code;
}

public function getErrors(): array
{
return $this->errors;
}
}
12 changes: 0 additions & 12 deletions src/ExceptionInterface.php

This file was deleted.

19 changes: 1 addition & 18 deletions src/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
*/
class Response
{
/** @var bool */
protected $success;

/** @var float */
protected $score;

Expand All @@ -27,24 +24,15 @@ class Response
protected $errors = [];

public function __construct(
bool $success,
float $score,
string $action,
\DateTime $dateTime,
string $hostname,
array $errors
string $hostname
) {
$this->success = $success;
$this->score = $score;
$this->action = $action;
$this->dateTime = $dateTime;
$this->hostname = $hostname;
$this->errors = $errors;
}

public function isSuccess(): bool
{
return $this->success;
}

public function getScore(): float
Expand All @@ -66,9 +54,4 @@ public function getHostname(): string
{
return $this->hostname;
}

public function getErrors(): array
{
return $this->errors;
}
}
52 changes: 46 additions & 6 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ public function testParsing(): void
);

$response = $this->client->verify('response', '127.0.0.1');
$this->assertEquals(
$success,
$response->isSuccess()
);
$this->assertEquals(
$score,
$response->getScore()
Expand Down Expand Up @@ -117,7 +113,7 @@ public function testInvalidJson(): void
* @expectedException \Exception
* @expectedExceptionMessage Missing required response attribute: score
*/
public function testMissingJsonFields()
public function testMissingJsonFields(): void
{
$this->mock->append(new GuzzleHttp\Psr7\Response(200, [], json_encode([
'success' => true,
Expand All @@ -126,6 +122,17 @@ public function testMissingJsonFields()
$this->client->verify('response', '127.0.0.1');
}

/**
* @expectedException \Exception
* @expectedExceptionMessage Missing required response attribute: success
*/
public function testMissingSuccess(): void
{
$this->mock->append(new GuzzleHttp\Psr7\Response(200, [], '{}'));

$this->client->verify('response', '127.0.0.1');
}

/**
* @expectedException \Wearesho\ReCaptcha\V3\Exception
* @expectedExceptionMessage The request is invalid or malformed
Expand All @@ -139,12 +146,45 @@ public function testGeneratingException(): void
'action' => $action = 'test',
'challenge_ts' => $date = date('c'),
'hostname' => $hostname = 'wearesho.com',
'error_codes' => [
'error-codes' => [
ReCaptcha\V3\Exception::BAD_REQUEST,
],
]))
);

$this->client->verify('response', '127.0.0.1');
}

/**
* @expectedException \Wearesho\ReCaptcha\V3\Exception
* @expectedExceptionMessage timeout-or-duplicate
*/
public function testErrorWithEmptyParams(): void
{
$this->mock->append(
new GuzzleHttp\Psr7\Response(200, [], json_encode([
'success' => false,
'error-codes' => [
'timeout-or-duplicate'
],
]))
);

$this->client->verify('response', '127.0.0.1');
}

/**
* @expectedException \Wearesho\ReCaptcha\V3\Exception
* @expectedExceptionMessageRegExp /^$/
*/
public function testErrorWithoutErrorCodes(): void
{
$this->mock->append(
new GuzzleHttp\Psr7\Response(200, [], json_encode([
'success' => false,
]))
);

$this->client->verify('response', '127.0.0.1');
}
}
47 changes: 22 additions & 25 deletions tests/ExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,21 @@
*/
class ExceptionTest extends TestCase
{
/** @var ReCaptcha\V3\Exception */
/** @var ReCaptcha\V3\Exception
*/
protected $exception;

/** @var ReCaptcha\V3\Response */
protected $response;

protected function setUp(): void
public function setUp(): void
{
parent::setUp();
$this->response = new ReCaptcha\V3\Response(
false,
0.5,
'test',
new \DateTime,
'wearesho.com',
[
ReCaptcha\V3\Exception::INVALID_INPUT_RESPONSE,
ReCaptcha\V3\Exception::MISSING_INPUT_RESPONSE,
ReCaptcha\V3\Exception::INVALID_INPUT_SECRET,
ReCaptcha\V3\Exception::MISSING_INPUT_SECRET,
ReCaptcha\V3\Exception::BAD_REQUEST,
'some-not-documented',
]
);
$this->exception = new ReCaptcha\V3\Exception($this->response);
$this->exception = new ReCaptcha\V3\Exception([
ReCaptcha\V3\Exception::INVALID_INPUT_RESPONSE,
ReCaptcha\V3\Exception::MISSING_INPUT_RESPONSE,
ReCaptcha\V3\Exception::INVALID_INPUT_SECRET,
ReCaptcha\V3\Exception::MISSING_INPUT_SECRET,
ReCaptcha\V3\Exception::BAD_REQUEST,
'some-not-documented',
]);
}

public function testGetMessage(): void
Expand All @@ -46,11 +36,18 @@ public function testGetMessage(): void
);
}

public function testGetResponse(): void
public function testGetErrors(): void
{
$this->assertEquals(
$this->response,
$this->exception->getResponse()
$this->assertArraySubset(
[
ReCaptcha\V3\Exception::INVALID_INPUT_RESPONSE,
ReCaptcha\V3\Exception::MISSING_INPUT_RESPONSE,
ReCaptcha\V3\Exception::INVALID_INPUT_SECRET,
ReCaptcha\V3\Exception::MISSING_INPUT_SECRET,
ReCaptcha\V3\Exception::BAD_REQUEST,
'some-not-documented',
],
$this->exception->getErrors()
);
}
}
22 changes: 1 addition & 21 deletions tests/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
*/
class ResponseTest extends TestCase
{
const SUCCESS = true;
const SCORE = 0.6;
const ACTION = 'login';
const TIMESTAMP = 190000;
Expand All @@ -25,22 +24,10 @@ protected function setUp(): void
{
parent::setUp();
$this->response = new ReCaptcha\V3\Response(
static::SUCCESS,
static::SCORE,
static::ACTION,
(new \DateTime())->setTimestamp(static::TIMESTAMP),
static::HOSTNAME,
[
static::ERROR_CODE,
]
);
}

public function testIsSuccess(): void
{
$this->assertEquals(
static::SUCCESS,
$this->response->isSuccess()
static::HOSTNAME
);
}

Expand Down Expand Up @@ -75,11 +62,4 @@ public function testGetHostName(): void
$this->response->getHostname()
);
}

public function testGetErrors(): void
{
$this->assertEquals([
static::ERROR_CODE,
], $this->response->getErrors());
}
}

0 comments on commit b717029

Please sign in to comment.