Skip to content

Commit 498052a

Browse files
authored
Merge pull request google#244 from google/show-connection-error
Show an explicit error when the connection fails
2 parents 5de9f3e + fe5f17c commit 498052a

File tree

8 files changed

+71
-16
lines changed

8 files changed

+71
-16
lines changed

ARCHITECTURE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,11 @@ unit tested by passing in a mock. Take a look at
5454
[`RequestMethod\Curl`](./src/ReCaptcha/RequestMethod/Curl.php) with the matching
5555
[`RequestMethod/CurlPostTest`](./tests/ReCaptcha/RequestMethod/CurlPostTest.php)
5656
to see this pattern in action.
57+
58+
### Error conventions
59+
60+
The client returns the response as provided by the reCAPTCHA services augmented
61+
with additional error codes based on the client's checks. When adding a new
62+
[`RequestMethod`](./src/ReCaptcha/RequestMethod.php) ensure that it returns the
63+
`ReCaptcha::E_CONNECTION_FAILED` and `ReCaptcha::E_BAD_RESPONSE` where
64+
appropriate.

src/ReCaptcha/ReCaptcha.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class ReCaptcha
5353
* Could not connect to service
5454
* @const string
5555
*/
56-
const E_BAD_CONNECTION = 'bad-connection';
56+
const E_CONNECTION_FAILED = 'connection-failed';
5757

5858
/**
5959
* Did not receive a 200 from the service

src/ReCaptcha/RequestMethod/CurlPost.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ public function submit(RequestParameters $params)
8787
$response = $this->curl->exec($handle);
8888
$this->curl->close($handle);
8989

90-
return $response;
90+
if ($response !== false) {
91+
return $response;
92+
}
93+
94+
return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
9195
}
9296
}

src/ReCaptcha/RequestMethod/Post.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ public function submit(RequestParameters $params)
6969
),
7070
);
7171
$context = stream_context_create($options);
72-
return file_get_contents($this->siteVerifyUrl, false, $context);
72+
$response = file_get_contents($this->siteVerifyUrl, false, $context);
73+
74+
if ($response !== false) {
75+
return $response;
76+
}
77+
78+
return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
7379
}
7480
}

src/ReCaptcha/RequestMethod/SocketPost.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function submit(RequestParameters $params)
6868
$urlParsed = parse_url($this->siteVerifyUrl);
6969

7070
if (false === $this->socket->fsockopen('ssl://' . $urlParsed['host'], 443, $errno, $errstr, 30)) {
71-
return '{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_CONNECTION.'"]}';
71+
return '{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}';
7272
}
7373

7474
$content = $params->toQueryString();

tests/ReCaptcha/RequestMethod/CurlPostTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
namespace ReCaptcha\RequestMethod;
2828

29+
use \ReCaptcha\ReCaptcha;
2930
use \ReCaptcha\RequestParameters;
3031
use PHPUnit\Framework\TestCase;
3132

@@ -88,4 +89,27 @@ public function testOverrideSiteVerifyUrl()
8889
$response = $pc->submit(new RequestParameters("secret", "response"));
8990
$this->assertEquals('RESPONSEBODY', $response);
9091
}
92+
93+
public function testConnectionFailureReturnsError()
94+
{
95+
$curl = $this->getMockBuilder(\ReCaptcha\RequestMethod\Curl::class)
96+
->disableOriginalConstructor()
97+
->setMethods(array('init', 'setoptArray', 'exec', 'close'))
98+
->getMock();
99+
$curl->expects($this->once())
100+
->method('init')
101+
->willReturn(new \stdClass);
102+
$curl->expects($this->once())
103+
->method('setoptArray')
104+
->willReturn(true);
105+
$curl->expects($this->once())
106+
->method('exec')
107+
->willReturn(false);
108+
$curl->expects($this->once())
109+
->method('close');
110+
111+
$pc = new CurlPost($curl);
112+
$response = $pc->submit(new RequestParameters("secret", "response"));
113+
$this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}', $response);
114+
}
91115
}

tests/ReCaptcha/RequestMethod/PostTest.php

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
namespace ReCaptcha\RequestMethod;
2828

29+
use \ReCaptcha\ReCaptcha;
2930
use ReCaptcha\RequestParameters;
3031
use PHPUnit\Framework\TestCase;
3132

@@ -37,7 +38,7 @@ class PostTest extends TestCase
3738

3839
public function setUp()
3940
{
40-
$this->parameters = new RequestParameters("secret", "response", "remoteip", "version");
41+
$this->parameters = new RequestParameters('secret', 'response', 'remoteip', 'version');
4142
}
4243

4344
public function tearDown()
@@ -48,27 +49,39 @@ public function tearDown()
4849
public function testHTTPContextOptions()
4950
{
5051
$req = new Post();
51-
self::$assert = array($this, "httpContextOptionsCallback");
52+
self::$assert = array($this, 'httpContextOptionsCallback');
5253
$req->submit($this->parameters);
53-
$this->assertEquals(1, $this->runcount, "The assertion was ran");
54+
$this->assertEquals(1, $this->runcount, 'The assertion was ran');
5455
}
5556

5657
public function testSSLContextOptions()
5758
{
5859
$req = new Post();
59-
self::$assert = array($this, "sslContextOptionsCallback");
60+
self::$assert = array($this, 'sslContextOptionsCallback');
6061
$req->submit($this->parameters);
61-
$this->assertEquals(1, $this->runcount, "The assertion was ran");
62+
$this->assertEquals(1, $this->runcount, 'The assertion was ran');
6263
}
6364

6465
public function testOverrideVerifyUrl()
6566
{
6667
$req = new Post('https://over.ride/some/path');
6768
self::$assert = array($this, 'overrideUrlOptions');
6869
$req->submit($this->parameters);
69-
$this->assertEquals(1, $this->runcount, "The assertion was ran");
70+
$this->assertEquals(1, $this->runcount, 'The assertion was ran');
7071
}
7172

73+
public function testConnectionFailureReturnsError()
74+
{
75+
$req = new Post('https://bad.connection/');
76+
self::$assert = array($this, 'connectionFailureResponse');
77+
$response = $req->submit($this->parameters);
78+
$this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}', $response);
79+
}
80+
81+
public function connectionFailureResponse()
82+
{
83+
return false;
84+
}
7285
public function overrideUrlOptions(array $args)
7386
{
7487
$this->runcount++;
@@ -84,14 +97,14 @@ public function httpContextOptionsCallback(array $args)
8497
$this->assertArrayHasKey('http', $options);
8598

8699
$this->assertArrayHasKey('method', $options['http']);
87-
$this->assertEquals("POST", $options['http']['method']);
100+
$this->assertEquals('POST', $options['http']['method']);
88101

89102
$this->assertArrayHasKey('content', $options['http']);
90103
$this->assertEquals($this->parameters->toQueryString(), $options['http']['content']);
91104

92105
$this->assertArrayHasKey('header', $options['http']);
93106
$headers = array(
94-
"Content-type: application/x-www-form-urlencoded",
107+
'Content-type: application/x-www-form-urlencoded',
95108
);
96109
foreach ($headers as $header) {
97110
$this->assertContains($header, $options['http']['header']);
@@ -112,9 +125,9 @@ public function sslContextOptionsCallback(array $args)
112125
protected function assertCommonOptions(array $args)
113126
{
114127
$this->assertCount(3, $args);
115-
$this->assertStringStartsWith("https://www.google.com/", $args[0]);
128+
$this->assertStringStartsWith('https://www.google.com/', $args[0]);
116129
$this->assertFalse($args[1]);
117-
$this->assertTrue(is_resource($args[2]), "The context options should be a resource");
130+
$this->assertTrue(is_resource($args[2]), 'The context options should be a resource');
118131
}
119132
}
120133

tests/ReCaptcha/RequestMethod/SocketPostTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public function testSubmitBadResponse()
112112
$this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}', $response);
113113
}
114114

115-
public function testSubmitBadRequest()
115+
public function testConnectionFailureReturnsError()
116116
{
117117
$socket = $this->getMockBuilder(\ReCaptcha\RequestMethod\Socket::class)
118118
->disableOriginalConstructor()
@@ -123,6 +123,6 @@ public function testSubmitBadRequest()
123123
->willReturn(false);
124124
$ps = new SocketPost($socket);
125125
$response = $ps->submit(new RequestParameters("secret", "response", "remoteip", "version"));
126-
$this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_CONNECTION.'"]}', $response);
126+
$this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_CONNECTION_FAILED.'"]}', $response);
127127
}
128128
}

0 commit comments

Comments
 (0)