From c14ed57f344dbacb28513fdc58f187a2a01a6b8c Mon Sep 17 00:00:00 2001 From: Mahmoud Ashraf <182176867+SNO7E-G@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:59:55 +0500 Subject: [PATCH 1/3] fix: accept HTTP/1.1 responses in SocketPost to support proxies Proxies and certain hosting environments may convert outbound HTTP/1.0 requests and respond with HTTP/1.1 200 OK. The previous strict check (strpos for 'HTTP/1.0 200 OK') caused false E_BAD_RESPONSE errors for these users. Replace the strpos check with a regex that accepts both HTTP/1.0 and HTTP/1.1 200 OK response headers. Add a dedicated test to verify HTTP/1.1 responses are handled correctly. --- src/ReCaptcha/RequestMethod/SocketPost.php | 2 +- tests/ReCaptcha/RequestMethod/SocketPostTest.php | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ReCaptcha/RequestMethod/SocketPost.php b/src/ReCaptcha/RequestMethod/SocketPost.php index c45d744..955a49d 100644 --- a/src/ReCaptcha/RequestMethod/SocketPost.php +++ b/src/ReCaptcha/RequestMethod/SocketPost.php @@ -107,7 +107,7 @@ public function submit(RequestParameters $params): string $response = ''; } - if (0 !== strpos($response, 'HTTP/1.0 200 OK')) { + if (1 !== preg_match('#^HTTP/1\.[01] 200 OK#', $response)) { return '{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}'; } diff --git a/tests/ReCaptcha/RequestMethod/SocketPostTest.php b/tests/ReCaptcha/RequestMethod/SocketPostTest.php index ef45a78..04961cb 100644 --- a/tests/ReCaptcha/RequestMethod/SocketPostTest.php +++ b/tests/ReCaptcha/RequestMethod/SocketPostTest.php @@ -182,6 +182,21 @@ public function testOverrideSiteVerifyUrl(): void $this->assertTrue(SocketPostGlobalState::$fcloseCalled); } + public function testSubmitReturnsResponseWhenHttp11(): void + { + SocketPostGlobalState::$fgetsResponses = [ + "HTTP/1.1 200 OK\r\n", + "Content-Type: application/json\r\n", + "\r\n", + 'RESPONSEBODY', + ]; + + $sp = new SocketPost(); + $response = $sp->submit(new RequestParameters('secret', 'response')); + $this->assertEquals('RESPONSEBODY', $response); + $this->assertTrue(SocketPostGlobalState::$fcloseCalled); + } + public function testStreamTimeoutFailureReturnsError(): void { SocketPostGlobalState::$streamSetTimeoutSuccess = false; From 9b1acb920a63f75d795b39f87fe50fdeb70cfbe4 Mon Sep 17 00:00:00 2001 From: Mahmoud Ashraf <182176867+SNO7E-G@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:05:20 +0500 Subject: [PATCH 2/3] test: verify SocketPost correctly rejects HTTP/1.1 errors --- tests/ReCaptcha/RequestMethod/SocketPostTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/ReCaptcha/RequestMethod/SocketPostTest.php b/tests/ReCaptcha/RequestMethod/SocketPostTest.php index 04961cb..1a86a8c 100644 --- a/tests/ReCaptcha/RequestMethod/SocketPostTest.php +++ b/tests/ReCaptcha/RequestMethod/SocketPostTest.php @@ -287,4 +287,18 @@ public function testStreamGetContentsReturnsFalse(): void $this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}', $response); } + + public function testBadResponseReturnsErrorWhenHttp11(): void + { + SocketPostGlobalState::$fgetsResponses = [ + "HTTP/1.1 500 Internal Server Error\r\n", + "\r\n", + 'FAIL', + ]; + + $sp = new SocketPost(); + $response = $sp->submit(new RequestParameters('secret', 'response')); + + $this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}', $response); + } } From df61d9dc21e199eeecba12838803cb35eda21159 Mon Sep 17 00:00:00 2001 From: Mahmoud Ashraf <182176867+SNO7E-G@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:24:57 +0500 Subject: [PATCH 3/3] test: verify SocketPost correctly rejects unsupported HTTP protocols --- tests/ReCaptcha/RequestMethod/SocketPostTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/ReCaptcha/RequestMethod/SocketPostTest.php b/tests/ReCaptcha/RequestMethod/SocketPostTest.php index 1a86a8c..ec6193e 100644 --- a/tests/ReCaptcha/RequestMethod/SocketPostTest.php +++ b/tests/ReCaptcha/RequestMethod/SocketPostTest.php @@ -193,6 +193,7 @@ public function testSubmitReturnsResponseWhenHttp11(): void $sp = new SocketPost(); $response = $sp->submit(new RequestParameters('secret', 'response')); + $this->assertEquals('RESPONSEBODY', $response); $this->assertTrue(SocketPostGlobalState::$fcloseCalled); } @@ -301,4 +302,19 @@ public function testBadResponseReturnsErrorWhenHttp11(): void $this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}', $response); } + + public function testBadResponseReturnsErrorWhenHttp2(): void + { + SocketPostGlobalState::$fgetsResponses = [ + "HTTP/2.0 200 OK\r\n", + "Content-Type: application/json\r\n", + "\r\n", + 'RESPONSEBODY', + ]; + + $sp = new SocketPost(); + $response = $sp->submit(new RequestParameters('secret', 'response')); + + $this->assertEquals('{"success": false, "error-codes": ["'.ReCaptcha::E_BAD_RESPONSE.'"]}', $response); + } }