diff --git a/src/Client/Adapter/Curl.php b/src/Client/Adapter/Curl.php index 9d830e4619..1dac31df3d 100644 --- a/src/Client/Adapter/Curl.php +++ b/src/Client/Adapter/Curl.php @@ -208,6 +208,18 @@ public function connect($host, $port = 80, $secure = false) } else { $connectTimeout = null; } + + if ($connectTimeout !== null && (! is_int($connectTimeout) || ! is_numeric($connectTimeout))) { + throw new AdapterException\InvalidArgumentException(sprintf( + 'integer or numeric string expected, got %s', + gettype($connectTimeout) + )); + } + + if ($connectTimeout !== null) { + $connectTimeout = (int) $connectTimeout; + } + if ($connectTimeout !== null) { if (defined('CURLOPT_CONNECTTIMEOUT_MS')) { curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT_MS, $connectTimeout * 1000); diff --git a/src/Client/Adapter/Socket.php b/src/Client/Adapter/Socket.php index 2319a4785f..26a17217a8 100644 --- a/src/Client/Adapter/Socket.php +++ b/src/Client/Adapter/Socket.php @@ -262,6 +262,14 @@ public function connect($host, $port = 80, $secure = false) } else { $connectTimeout = $this->config['timeout']; } + + if ($connectTimeout !== null && (! is_int($connectTimeout) || ! is_numeric($connectTimeout))) { + throw new AdapterException\InvalidArgumentException(sprintf( + 'integer or numeric string expected, got %s', + gettype($connectTimeout) + )); + } + ErrorHandler::start(); $this->socket = stream_socket_client( $host . ':' . $port, diff --git a/test/Client/CurlTest.php b/test/Client/CurlTest.php index 0e6c75fc92..6dc81a3fc2 100644 --- a/test/Client/CurlTest.php +++ b/test/Client/CurlTest.php @@ -96,6 +96,36 @@ public function testConfigSetAsZendConfig() $this->assertEquals($config->nested->item, $hasConfig['nested']['item']); } + public function provideValidTimeoutConfig() + { + return [ + 'integer' => [10], + 'numeric' => ['10'], + ]; + } + + /** + * @dataProvider provideValidTimeoutConfig + */ + public function testPassValidTimeout($timeout) + { + $adapter = new Adapter\Curl(); + $adapter->setOptions(['timeout' => $timeout]); + + $adapter->connect('http://framework.zend.com'); + } + + public function testThrowInvalidArgumentExceptionOnNonIntegerAndNonNumericStringTimeout() + { + $adapter = new Adapter\Curl(); + $adapter->setOptions(['timeout' => 'timeout']); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('integer or numeric string expected, got string'); + + $adapter->connect('http://framework.zend.com'); + } + /** * Check that an exception is thrown when trying to set invalid config * diff --git a/test/Client/SocketTest.php b/test/Client/SocketTest.php index 1610c571f2..e1504041c8 100644 --- a/test/Client/SocketTest.php +++ b/test/Client/SocketTest.php @@ -171,6 +171,36 @@ public function testSetConfigInvalidConfig($config) $this->_adapter->setOptions($config); } + public function provideValidTimeoutConfig() + { + return [ + 'integer' => [10], + 'numeric' => ['10'], + ]; + } + + /** + * @dataProvider provideValidTimeoutConfig + */ + public function testPassValidTimeout($timeout) + { + $adapter = new Adapter\Socket(); + $adapter->setOptions(['timeout' => $timeout]); + + $adapter->connect('http://framework.zend.com'); + } + + public function testThrowInvalidArgumentExceptionOnNonIntegerAndNonNumericStringTimeout() + { + $adapter = new Adapter\Socket(); + $adapter->setOptions(['timeout' => 'timeout']); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('integer or numeric string expected, got string'); + + $adapter->connect('http://framework.zend.com'); + } + /** * Stream context related tests */