From 65c2afd5f2e04fe3a1392d4dab492fff7c38bd92 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 15:26:47 +0100 Subject: [PATCH 01/16] Fix cs --- .gitignore | 4 ++ .php_cs | 27 +++++++---- .travis.yml | 2 + composer.json | 3 ++ src/Client.php | 1 - src/RequestWriter.php | 11 ++--- src/ResponseReader.php | 4 +- tests/BaseTestCase.php | 6 +-- tests/Semaphore.php | 4 +- tests/SocketClientFeatureTest.php | 1 - tests/SocketHttpAdapterTest.php | 1 - tests/SocketHttpClientTest.php | 64 +++++++++++++------------- tests/StreamTest.php | 55 +++++++++++----------- tests/server/ssl/file.srl | 2 +- tests/server/ssl/generate.sh | 4 +- tests/server/tcp-bugous-server.php | 4 +- tests/server/tcp-server.php | 2 +- tests/server/tcp-ssl-server-client.php | 20 ++++---- tests/server/tcp-ssl-server.php | 13 +++--- tests/server/unix-domain-server.php | 4 +- 20 files changed, 120 insertions(+), 112 deletions(-) diff --git a/.gitignore b/.gitignore index da734f1..33793eb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ vendor/ composer.lock phpspec.yml phpunit.xml +/.php_cs.cache +/tests/server/ssl/*.pem +/tests/server/ssl/*.key +/tests/server/ssl/*.req diff --git a/.php_cs b/.php_cs index 23ba165..55d9b0b 100644 --- a/.php_cs +++ b/.php_cs @@ -1,13 +1,22 @@ setRules([ + '@PSR2' => true, + '@Symfony' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'no_empty_phpdoc' => true, + 'no_superfluous_phpdoc_tags' => true, +]); -use SLLH\StyleCIBridge\ConfigBridge; +$finder = PhpCsFixer\Finder::create(); +$finder->in([ + 'src', + 'tests' +]); -return ConfigBridge::create(); +$config->setFinder($finder); + +return $config; diff --git a/.travis.yml b/.travis.yml index 0922767..cbde20e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ php: - 5.6 - 7.0 - 7.1 + - 7.2 + - 7.3 env: global: diff --git a/composer.json b/composer.json index ab43a37..afcf404 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "php-http/discovery": "^1.0" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^2.2", "guzzlehttp/psr7": "^1.2", "php-http/client-integration-tests": "^0.6", "php-http/message": "^1.0", @@ -35,6 +36,8 @@ } }, "scripts": { + "cs-check": "vendor/bin/php-cs-fixer fix --dry-run", + "cs-fix": "vendor/bin/php-cs-fixer fix", "test": "vendor/bin/phpunit", "test-ci": "vendor/bin/phpunit --coverage-clover build/coverage.xml" }, diff --git a/src/Client.php b/src/Client.php index cb84123..7333fbb 100644 --- a/src/Client.php +++ b/src/Client.php @@ -161,7 +161,6 @@ protected function configure(array $config = []) /** * Return remote socket from the request. * - * @param RequestInterface $request * * @throws InvalidRequestException When no remote can be determined from the request * diff --git a/src/RequestWriter.php b/src/RequestWriter.php index 3e8ac88..405649f 100644 --- a/src/RequestWriter.php +++ b/src/RequestWriter.php @@ -17,9 +17,8 @@ trait RequestWriter /** * Write a request to a socket. * - * @param resource $socket - * @param RequestInterface $request - * @param int $bufferSize + * @param resource $socket + * @param int $bufferSize * * @throws BrokenPipeException */ @@ -37,9 +36,8 @@ protected function writeRequest($socket, RequestInterface $request, $bufferSize /** * Write Body of the request. * - * @param resource $socket - * @param RequestInterface $request - * @param int $bufferSize + * @param resource $socket + * @param int $bufferSize * * @throws BrokenPipeException */ @@ -63,7 +61,6 @@ protected function writeBody($socket, RequestInterface $request, $bufferSize = 8 /** * Produce the header of request as a string based on a PSR Request. * - * @param RequestInterface $request * * @return string */ diff --git a/src/ResponseReader.php b/src/ResponseReader.php index f5fd083..df4ba50 100644 --- a/src/ResponseReader.php +++ b/src/ResponseReader.php @@ -25,8 +25,7 @@ trait ResponseReader /** * Read a response from a socket. * - * @param RequestInterface $request - * @param resource $socket + * @param resource $socket * * @throws TimeoutException When the socket timed out * @throws BrokenPipeException When the response cannot be read @@ -89,7 +88,6 @@ protected function readResponse(RequestInterface $request, $socket) * Create the stream. * * @param $socket - * @param ResponseInterface $response * * @return Stream */ diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php index 3bc67d2..a6ffda7 100644 --- a/tests/BaseTestCase.php +++ b/tests/BaseTestCase.php @@ -10,14 +10,14 @@ class BaseTestCase extends TestCase public function startServer($name) { - $filename = __DIR__ . '/server/' . $name . '.php'; - $pipes = []; + $filename = __DIR__.'/server/'.$name.'.php'; + $pipes = []; if (!Semaphore::acquire()) { $this->fail('Could not connect to server'); } - $this->servers[$name] = proc_open('php '. $filename, [], $pipes); + $this->servers[$name] = proc_open('php '.$filename, [], $pipes); sleep(1); } diff --git a/tests/Semaphore.php b/tests/Semaphore.php index ea83010..9ff92a7 100644 --- a/tests/Semaphore.php +++ b/tests/Semaphore.php @@ -23,7 +23,7 @@ public static function acquire() return false; } } - self::$openConnections++; + ++self::$openConnections; return true; } @@ -35,6 +35,6 @@ public static function release() { // Do no be too quick usleep(500000); - self::$openConnections--; + --self::$openConnections; } } diff --git a/tests/SocketClientFeatureTest.php b/tests/SocketClientFeatureTest.php index 487944b..d02dea8 100644 --- a/tests/SocketClientFeatureTest.php +++ b/tests/SocketClientFeatureTest.php @@ -3,7 +3,6 @@ namespace Http\Client\Socket\Tests; use Http\Client\Tests\HttpFeatureTest; -use Http\Message\MessageFactory\GuzzleMessageFactory; use Http\Client\Socket\Client as SocketHttpClient; class SocketClientFeatureTest extends HttpFeatureTest diff --git a/tests/SocketHttpAdapterTest.php b/tests/SocketHttpAdapterTest.php index 3d90e70..143d4b4 100644 --- a/tests/SocketHttpAdapterTest.php +++ b/tests/SocketHttpAdapterTest.php @@ -3,7 +3,6 @@ namespace Http\Client\Socket\Tests; use Http\Client\Tests\HttpClientTest; -use Http\Message\MessageFactory\GuzzleMessageFactory; use Http\Client\Socket\Client as SocketHttpClient; class SocketHttpAdapterTest extends HttpClientTest diff --git a/tests/SocketHttpClientTest.php b/tests/SocketHttpClientTest.php index c3660ec..e8981e6 100644 --- a/tests/SocketHttpClientTest.php +++ b/tests/SocketHttpClientTest.php @@ -8,7 +8,7 @@ class SocketHttpClientTest extends BaseTestCase { - public function createClient($options = array()) + public function createClient($options = []) { $messageFactory = new GuzzleMessageFactory(); @@ -18,7 +18,7 @@ public function createClient($options = array()) public function testTcpSocketDomain() { $this->startServer('tcp-server'); - $client = $this->createClient(['remote_socket' => '127.0.0.1:19999']); + $client = $this->createClient(['remote_socket' => '127.0.0.1:19999']); $response = $client->get('/', []); $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response); @@ -30,14 +30,14 @@ public function testTcpSocketDomain() */ public function testNoRemote() { - $client = $this->createClient(); + $client = $this->createClient(); $client->get('/', []); } public function testRemoteInUri() { $this->startServer('tcp-server'); - $client = $this->createClient(); + $client = $this->createClient(); $response = $client->get('http://127.0.0.1:19999/', []); $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response); @@ -47,7 +47,7 @@ public function testRemoteInUri() public function testRemoteInHostHeader() { $this->startServer('tcp-server'); - $client = $this->createClient(); + $client = $this->createClient(); $response = $client->get('/', ['Host' => '127.0.0.1:19999']); $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response); @@ -67,13 +67,13 @@ public function testBrokenSocket() public function testSslRemoteInUri() { $this->startServer('tcp-ssl-server'); - $client = $this->createClient([ + $client = $this->createClient([ 'stream_context_options' => [ 'ssl' => [ 'peer_name' => 'socket-adapter', - 'cafile' => __DIR__ . '/server/ssl/ca.pem' - ] - ] + 'cafile' => __DIR__.'/server/ssl/ca.pem', + ], + ], ]); $response = $client->get('https://127.0.0.1:19999/', []); @@ -85,8 +85,8 @@ public function testUnixSocketDomain() { $this->startServer('unix-domain-server'); - $client = $this->createClient([ - 'remote_socket' => 'unix://'.__DIR__.'/server/server.sock' + $client = $this->createClient([ + 'remote_socket' => 'unix://'.__DIR__.'/server/server.sock', ]); $response = $client->get('/', []); @@ -99,7 +99,7 @@ public function testUnixSocketDomain() */ public function testNetworkExceptionOnConnectError() { - $client = $this->createClient(['remote_socket' => '127.0.0.1:19999']); + $client = $this->createClient(['remote_socket' => '127.0.0.1:19999']); $client->get('/', []); } @@ -107,15 +107,15 @@ public function testSslConnection() { $this->startServer('tcp-ssl-server'); - $client = $this->createClient([ + $client = $this->createClient([ 'remote_socket' => '127.0.0.1:19999', - 'ssl' => true, + 'ssl' => true, 'stream_context_options' => [ 'ssl' => [ 'peer_name' => 'socket-adapter', - 'cafile' => __DIR__ . '/server/ssl/ca.pem' - ] - ] + 'cafile' => __DIR__.'/server/ssl/ca.pem', + ], + ], ]); $response = $client->get('/', []); @@ -131,16 +131,16 @@ public function testSslConnectionWithClientCertificate() $this->startServer('tcp-ssl-server-client'); - $client = $this->createClient([ + $client = $this->createClient([ 'remote_socket' => '127.0.0.1:19999', - 'ssl' => true, + 'ssl' => true, 'stream_context_options' => [ 'ssl' => [ - 'peer_name' => 'socket-adapter', - 'cafile' => __DIR__ . '/server/ssl/ca.pem', - 'local_cert' => __DIR__ . '/server/ssl/client-and-key.pem' - ] - ] + 'peer_name' => 'socket-adapter', + 'cafile' => __DIR__.'/server/ssl/ca.pem', + 'local_cert' => __DIR__.'/server/ssl/client-and-key.pem', + ], + ], ]); $response = $client->get('/', []); @@ -156,15 +156,15 @@ public function testInvalidSslConnectionWithClientCertificate() $this->startServer('tcp-ssl-server-client'); - $client = $this->createClient([ + $client = $this->createClient([ 'remote_socket' => '127.0.0.1:19999', - 'ssl' => true, + 'ssl' => true, 'stream_context_options' => [ 'ssl' => [ - 'peer_name' => 'socket-adapter', - 'cafile' => __DIR__ . '/server/ssl/ca.pem' - ] - ] + 'peer_name' => 'socket-adapter', + 'cafile' => __DIR__.'/server/ssl/ca.pem', + ], + ], ]); $response = $client->get('/', []); @@ -179,7 +179,7 @@ public function testNetworkExceptionOnSslError() { $this->startServer('tcp-server'); - $client = $this->createClient(['remote_socket' => '127.0.0.1:19999', 'ssl' => true]); + $client = $this->createClient(['remote_socket' => '127.0.0.1:19999', 'ssl' => true]); $client->get('/', []); } @@ -188,7 +188,7 @@ public function testNetworkExceptionOnSslError() */ public function testNetworkExceptionOnTimeout() { - $client = $this->createClient(['timeout' => 10]); + $client = $this->createClient(['timeout' => 10]); $client->get('http://php.net', []); } } diff --git a/tests/StreamTest.php b/tests/StreamTest.php index 2421fb1..0bd21e6 100644 --- a/tests/StreamTest.php +++ b/tests/StreamTest.php @@ -2,7 +2,6 @@ namespace Http\Client\Socket\Tests; -use Http\Client\Socket\Exception\TimeoutException; use Http\Client\Socket\Stream; use PHPUnit\Framework\TestCase; @@ -19,24 +18,24 @@ public function createSocket($body, $useSize = true) public function testToString() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); - $this->assertEquals("Body", $stream->__toString()); + $this->assertEquals('Body', $stream->__toString()); $stream->close(); } public function testSubsequentCallIsEmpty() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); - $this->assertEquals("Body", $stream->getContents()); + $this->assertEquals('Body', $stream->getContents()); $this->assertEmpty($stream->getContents()); $stream->close(); } public function testDetach() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); $socket = $stream->detach(); $this->assertTrue(is_resource($socket)); @@ -45,21 +44,21 @@ public function testDetach() public function testTell() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); $this->assertEquals(0, $stream->tell()); - $this->assertEquals("Body", $stream->getContents()); + $this->assertEquals('Body', $stream->getContents()); $this->assertEquals(4, $stream->tell()); } public function testEof() { $socket = fopen('php://memory', 'rw+'); - fwrite($socket, "Body"); + fwrite($socket, 'Body'); fseek($socket, 0); $stream = new Stream($socket); - $this->assertEquals("Body", $stream->getContents()); + $this->assertEquals('Body', $stream->getContents()); fwrite($socket, "\0"); $this->assertTrue($stream->eof()); $stream->close(); @@ -67,7 +66,7 @@ public function testEof() public function testNotSeekable() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); $this->assertFalse($stream->isSeekable()); @@ -80,7 +79,7 @@ public function testNotSeekable() public function testNoRewing() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); try { $stream->rewind(); @@ -91,12 +90,12 @@ public function testNoRewing() public function testNotWritable() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); $this->assertFalse($stream->isWritable()); try { - $stream->write("Test"); + $stream->write('Test'); } catch (\Exception $e) { $this->assertInstanceOf('Http\Client\Socket\Exception\StreamException', $e); } @@ -104,7 +103,7 @@ public function testNotWritable() public function testIsReadable() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); $this->assertTrue($stream->isReadable()); } @@ -114,7 +113,7 @@ public function testIsReadable() */ public function testTimeout() { - $socket = fsockopen("php.net", 80); + $socket = fsockopen('php.net', 80); socket_set_timeout($socket, 0, 100); $stream = new Stream($socket, 50); @@ -123,20 +122,20 @@ public function testTimeout() public function testMetadatas() { - $stream = $this->createSocket("Body", false); - - $this->assertEquals("PHP", $stream->getMetadata("wrapper_type")); - $this->assertEquals("MEMORY", $stream->getMetadata("stream_type")); - $this->assertEquals("php://memory", $stream->getMetadata("uri")); - $this->assertFalse($stream->getMetadata("timed_out")); - $this->assertFalse($stream->getMetadata("eof")); - $this->assertTrue($stream->getMetadata("blocked")); + $stream = $this->createSocket('Body', false); + + $this->assertEquals('PHP', $stream->getMetadata('wrapper_type')); + $this->assertEquals('MEMORY', $stream->getMetadata('stream_type')); + $this->assertEquals('php://memory', $stream->getMetadata('uri')); + $this->assertFalse($stream->getMetadata('timed_out')); + $this->assertFalse($stream->getMetadata('eof')); + $this->assertTrue($stream->getMetadata('blocked')); } public function testClose() { $socket = fopen('php://memory', 'rw+'); - fwrite($socket, "Body"); + fwrite($socket, 'Body'); fseek($socket, 0); $stream = new Stream($socket); @@ -147,10 +146,10 @@ public function testClose() public function testRead() { - $stream = $this->createSocket("Body"); + $stream = $this->createSocket('Body'); - $this->assertEquals("Bod", $stream->read(3)); - $this->assertEquals("y", $stream->read(3)); + $this->assertEquals('Bod', $stream->read(3)); + $this->assertEquals('y', $stream->read(3)); $stream->close(); } diff --git a/tests/server/ssl/file.srl b/tests/server/ssl/file.srl index da51c42..f5c8955 100644 --- a/tests/server/ssl/file.srl +++ b/tests/server/ssl/file.srl @@ -1 +1 @@ -2F +32 diff --git a/tests/server/ssl/generate.sh b/tests/server/ssl/generate.sh index 696b340..eb83bc2 100755 --- a/tests/server/ssl/generate.sh +++ b/tests/server/ssl/generate.sh @@ -7,11 +7,11 @@ O="PHP-HTTP" CN="socket-adapter" openssl req -out ca.pem -new -x509 -subj "/C=$C/ST=$ST/L=$L/O=$O/CN=socket-server" -passout pass:password -openssl genrsa -out server.key 1024 -subj "/C=$C/ST=$ST/L=$L/O=$O/CN=socket-adapter" +openssl genrsa -out server.key openssl req -key server.key -new -out server.req -subj "/C=$C/ST=$ST/L=$L/O=$O/CN=socket-adapter" -passout pass:password openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.pem -passin pass:password -openssl genrsa -out client.key 1024 -subj "/C=$C/ST=$ST/L=$L/O=$O/CN=socket-adapter-client" +openssl genrsa -out client.key openssl req -key client.key -new -out client.req -subj "/C=$C/ST=$ST/L=$L/O=$O/CN=socket-adapter-client" -passout pass:password openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.pem -passin pass:password diff --git a/tests/server/tcp-bugous-server.php b/tests/server/tcp-bugous-server.php index 7f0d91f..d1a55ae 100644 --- a/tests/server/tcp-bugous-server.php +++ b/tests/server/tcp-bugous-server.php @@ -1,9 +1,9 @@ [ - 'local_cert' => __DIR__ . '/ssl/server-and-key.pem', - 'cafile' => __DIR__ . '/ssl/ca.pem', - 'capture_peer_cert' => true - ] + 'local_cert' => __DIR__.'/ssl/server-and-key.pem', + 'cafile' => __DIR__.'/ssl/ca.pem', + 'capture_peer_cert' => true, + ], ]); -$socketServer = stream_socket_server('tcp://127.0.0.1:19999', $errNo, $errStr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context); +$socketServer = stream_socket_server('tcp://127.0.0.1:19999', $errNo, $errStr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context); stream_socket_enable_crypto($socketServer, false); -$client = stream_socket_accept($socketServer); +$client = stream_socket_accept($socketServer); stream_set_blocking($client, true); stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER); @@ -22,10 +22,10 @@ if (isset(stream_context_get_options($context)['ssl']['peer_certificate'])) { $client_cert = stream_context_get_options($context)['ssl']['peer_certificate']; - $name = openssl_x509_parse($client_cert)["subject"]["CN"]; + $name = openssl_x509_parse($client_cert)['subject']['CN']; } -if ($name == "socket-adapter-client") { +if ('socket-adapter-client' == $name) { fwrite($client, str_replace("\n", "\r\n", << [ - 'local_cert' => __DIR__ . '/ssl/server-and-key.pem' - ] + 'local_cert' => __DIR__.'/ssl/server-and-key.pem', + ], ]); -$socketServer = stream_socket_server('tcp://127.0.0.1:19999', $errNo, $errStr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context); +$socketServer = stream_socket_server('tcp://127.0.0.1:19999', $errNo, $errStr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context); stream_socket_enable_crypto($socketServer, false); -$client = stream_socket_accept($socketServer); +$client = stream_socket_accept($socketServer); stream_set_blocking($client, true); if (@stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER)) { fwrite($client, str_replace("\n", "\r\n", << Date: Mon, 21 Jan 2019 15:29:47 +0100 Subject: [PATCH 02/16] Remove support for old version of php --- .travis.yml | 10 +--------- composer.json | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index cbde20e..ad51702 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,6 @@ cache: - $HOME/.composer/cache php: - - 5.5 - - 5.6 - - 7.0 - 7.1 - 7.2 - 7.3 @@ -23,15 +20,10 @@ branches: - /^analysis-.*$/ matrix: - allow_failures: - - php: hhvm - dist: trusty fast_finish: true include: - - php: 5.5 + - php: 7.1 env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci" - - php: hhvm - dist: trusty before_install: - travis_retry composer self-update diff --git a/composer.json b/composer.json index afcf404..1ef4262 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ } ], "require": { - "php": "^5.5 || ^7.0", + "php": "^7.1", "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0", "php-http/httplug": "^1.0", "php-http/message-factory": "^1.0.2", From e8135a2f3a8fc39b83fa559ceae455db75f2483e Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 15:46:44 +0100 Subject: [PATCH 03/16] Make it work with psr18 and httplug 2.0 --- composer.json | 10 +++++----- src/Client.php | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 1ef4262..8eb246e 100644 --- a/composer.json +++ b/composer.json @@ -11,16 +11,16 @@ "require": { "php": "^7.1", "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0", - "php-http/httplug": "^1.0", - "php-http/message-factory": "^1.0.2", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0.2 || ^2.0", "php-http/discovery": "^1.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.2", "guzzlehttp/psr7": "^1.2", - "php-http/client-integration-tests": "^0.6", + "php-http/client-integration-tests": "^1.0 || ^2.0", "php-http/message": "^1.0", - "php-http/client-common": "^1.0" + "php-http/client-common": "^1.0 || ^2.0" }, "provide": { "php-http/client-implementation": "1.0" @@ -43,7 +43,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "prefer-stable": true, diff --git a/src/Client.php b/src/Client.php index 7333fbb..d085043 100644 --- a/src/Client.php +++ b/src/Client.php @@ -9,6 +9,7 @@ use Http\Discovery\MessageFactoryDiscovery; use Http\Message\ResponseFactory; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -62,7 +63,7 @@ public function __construct(ResponseFactory $responseFactory = null, array $conf /** * {@inheritdoc} */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { $remote = $this->config['remote_socket']; $useSsl = $this->config['ssl']; From 4a1b34a21a7c325b0c121d2ce8dc0f2313803ab0 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 15:49:13 +0100 Subject: [PATCH 04/16] Add changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aaef69..0d64672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 2.0.0 (unreleased) + + * PSR18 and HTTPlug 2 support + * Remove support for php 5.5, 5.6 and 7.0 + ## 1.4.0 * Support for Symfony 4 From 6636c00bb5542bd0f609e5d66fe1a460e7bb14c7 Mon Sep 17 00:00:00 2001 From: Bastien Jaillot Date: Tue, 29 May 2018 15:01:15 +0200 Subject: [PATCH 05/16] TLS v1 is not accepted anymore I got errors like that all the time since the servers I contact updated their lib. > OpenSSL Error messages: error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version --- src/Client.php | 4 ++-- tests/server/tcp-ssl-server-client.php | 2 +- tests/server/tcp-ssl-server.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Client.php b/src/Client.php index d085043..0d2a6c8 100644 --- a/src/Client.php +++ b/src/Client.php @@ -32,7 +32,7 @@ class Client implements HttpClient 'stream_context_param' => [], 'ssl' => null, 'write_buffer_size' => 8192, - 'ssl_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT, + 'ssl_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, ]; /** @@ -47,7 +47,7 @@ class Client implements HttpClient * @var array $stream_context_param Context params as defined in the PHP documentation * @var bool $ssl Use ssl, default to scheme from request, false if not present * @var int $write_buffer_size Buffer when writing the request body, defaults to 8192 - * @var int $ssl_method Crypto method for ssl/tls, see PHP doc, defaults to STREAM_CRYPTO_METHOD_TLS_CLIENT + * @var int $ssl_method Crypto method for ssl/tls, see PHP doc, defaults to STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT * } */ public function __construct(ResponseFactory $responseFactory = null, array $config = []) diff --git a/tests/server/tcp-ssl-server-client.php b/tests/server/tcp-ssl-server-client.php index 29ee43c..1e06cd3 100644 --- a/tests/server/tcp-ssl-server-client.php +++ b/tests/server/tcp-ssl-server-client.php @@ -15,7 +15,7 @@ $client = stream_socket_accept($socketServer); stream_set_blocking($client, true); -stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER); +stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLSv1_2_SERVER); // Verify client certificate $name = null; diff --git a/tests/server/tcp-ssl-server.php b/tests/server/tcp-ssl-server.php index 808717e..fb15359 100644 --- a/tests/server/tcp-ssl-server.php +++ b/tests/server/tcp-ssl-server.php @@ -13,7 +13,7 @@ $client = stream_socket_accept($socketServer); stream_set_blocking($client, true); -if (@stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER)) { +if (@stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLSv1_2_SERVER)) { fwrite($client, str_replace("\n", "\r\n", << Date: Mon, 21 Jan 2019 15:54:31 +0100 Subject: [PATCH 06/16] Add changelog for new ssl default --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d64672..5da849c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * PSR18 and HTTPlug 2 support * Remove support for php 5.5, 5.6 and 7.0 + * SSL Method now defaults to `STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT` ## 1.4.0 From d5f46a1e4abc8079456b73f203de019b1170d2f4 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 16:07:27 +0100 Subject: [PATCH 07/16] Remove styleci integration --- .styleci.yml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .styleci.yml diff --git a/.styleci.yml b/.styleci.yml deleted file mode 100644 index 296cab4..0000000 --- a/.styleci.yml +++ /dev/null @@ -1,10 +0,0 @@ -preset: symfony - -finder: - exclude: - - "spec" - path: - - "src" - -enabled: - - short_array_syntax From 3298ae57d2f168c1109b75e8699f9bbd877d8527 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 17:24:54 +0100 Subject: [PATCH 08/16] Add 7.2 with prefer lowest to ensure httplug 1.0 compatiblity --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index ad51702..28a8944 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,8 @@ matrix: include: - php: 7.1 env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci" + - php: 7.2 + env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" before_install: - travis_retry composer self-update From ed215638578a925c9e1bbaeea0587c2f48e2bcfc Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 17:28:55 +0100 Subject: [PATCH 09/16] Add type hinting --- src/Client.php | 2 +- src/RequestWriter.php | 14 ++++---------- src/ResponseReader.php | 10 +++------- src/Stream.php | 2 +- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/Client.php b/src/Client.php index 0d2a6c8..22125c3 100644 --- a/src/Client.php +++ b/src/Client.php @@ -105,7 +105,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface * * @return resource Socket resource */ - protected function createSocket(RequestInterface $request, $remote, $useSsl) + protected function createSocket(RequestInterface $request, string $remote, bool $useSsl) { $errNo = null; $errMsg = null; diff --git a/src/RequestWriter.php b/src/RequestWriter.php index 405649f..7f7bbca 100644 --- a/src/RequestWriter.php +++ b/src/RequestWriter.php @@ -18,11 +18,10 @@ trait RequestWriter * Write a request to a socket. * * @param resource $socket - * @param int $bufferSize * * @throws BrokenPipeException */ - protected function writeRequest($socket, RequestInterface $request, $bufferSize = 8192) + protected function writeRequest($socket, RequestInterface $request, int $bufferSize = 8192) { if (false === $this->fwrite($socket, $this->transformRequestHeadersToString($request))) { throw new BrokenPipeException('Failed to send request, underlying socket not accessible, (BROKEN EPIPE)', $request); @@ -37,11 +36,10 @@ protected function writeRequest($socket, RequestInterface $request, $bufferSize * Write Body of the request. * * @param resource $socket - * @param int $bufferSize * * @throws BrokenPipeException */ - protected function writeBody($socket, RequestInterface $request, $bufferSize = 8192) + protected function writeBody($socket, RequestInterface $request, int $bufferSize = 8192) { $body = $request->getBody(); @@ -60,11 +58,8 @@ protected function writeBody($socket, RequestInterface $request, $bufferSize = 8 /** * Produce the header of request as a string based on a PSR Request. - * - * - * @return string */ - protected function transformRequestHeadersToString(RequestInterface $request) + protected function transformRequestHeadersToString(RequestInterface $request): string { $message = vsprintf('%s %s HTTP/%s', [ strtoupper($request->getMethod()), @@ -87,11 +82,10 @@ protected function transformRequestHeadersToString(RequestInterface $request) * @see https://secure.phabricator.com/rPHU69490c53c9c2ef2002bc2dd4cecfe9a4b080b497 * * @param resource $stream The stream resource - * @param string $bytes Bytes written in the stream * * @return bool|int false if pipe is broken, number of bytes written otherwise */ - private function fwrite($stream, $bytes) + private function fwrite($stream, string $bytes) { if (!strlen($bytes)) { return 0; diff --git a/src/ResponseReader.php b/src/ResponseReader.php index df4ba50..e631426 100644 --- a/src/ResponseReader.php +++ b/src/ResponseReader.php @@ -29,10 +29,8 @@ trait ResponseReader * * @throws TimeoutException When the socket timed out * @throws BrokenPipeException When the response cannot be read - * - * @return ResponseInterface */ - protected function readResponse(RequestInterface $request, $socket) + protected function readResponse(RequestInterface $request, $socket): ResponseInterface { $headers = []; $reason = null; @@ -87,11 +85,9 @@ protected function readResponse(RequestInterface $request, $socket) /** * Create the stream. * - * @param $socket - * - * @return Stream + * @param resource $socket */ - protected function createStream($socket, ResponseInterface $response) + protected function createStream($socket, ResponseInterface $response): Stream { $size = null; diff --git a/src/Stream.php b/src/Stream.php index 507f135..00f2503 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -48,7 +48,7 @@ class Stream implements StreamInterface * @param resource $socket * @param int $size */ - public function __construct($socket, $size = null) + public function __construct($socket, ?int $size = null) { $this->socket = $socket; $this->size = $size; From 0243e0c63b41a038e88ed511bb13e05cf956b7d2 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 18:16:40 +0100 Subject: [PATCH 10/16] Use only psr18 and not httplug anymore, fix psr7 implementation --- composer.json | 12 ++++----- src/Client.php | 12 ++------- src/Exception/BrokenPipeException.php | 2 -- src/Exception/ConnectionException.php | 2 -- src/Exception/InvalidRequestException.php | 2 -- src/Exception/NetworkException.php | 23 ++++++++++++++++ src/Exception/SSLConnectionException.php | 2 -- src/Exception/StreamException.php | 33 ++--------------------- src/Exception/TimeoutException.php | 2 +- src/ResponseReader.php | 9 ++++--- src/Stream.php | 12 ++++++--- tests/SocketHttpClientTest.php | 12 ++++----- tests/StreamTest.php | 9 ++++--- 13 files changed, 58 insertions(+), 74 deletions(-) create mode 100644 src/Exception/NetworkException.php diff --git a/composer.json b/composer.json index 8eb246e..f3e0bb1 100644 --- a/composer.json +++ b/composer.json @@ -10,17 +10,15 @@ ], "require": { "php": "^7.1", - "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0", - "php-http/httplug": "^1.0 || ^2.0", - "php-http/message-factory": "^1.0.2 || ^2.0", - "php-http/discovery": "^1.0" + "nyholm/psr7": "^1.0", + "psr/http-client": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.2", - "guzzlehttp/psr7": "^1.2", - "php-http/client-integration-tests": "^1.0 || ^2.0", + "php-http/client-integration-tests": "^2.0", "php-http/message": "^1.0", - "php-http/client-common": "^1.0 || ^2.0" + "php-http/client-common": "^2.0" }, "provide": { "php-http/client-implementation": "1.0" diff --git a/src/Client.php b/src/Client.php index 22125c3..435ac18 100644 --- a/src/Client.php +++ b/src/Client.php @@ -6,8 +6,6 @@ use Http\Client\Socket\Exception\ConnectionException; use Http\Client\Socket\Exception\InvalidRequestException; use Http\Client\Socket\Exception\SSLConnectionException; -use Http\Discovery\MessageFactoryDiscovery; -use Http\Message\ResponseFactory; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Component\OptionsResolver\Options; @@ -38,8 +36,7 @@ class Client implements HttpClient /** * Constructor. * - * @param ResponseFactory $responseFactory Response factory for creating response - * @param array $config { + * @param array $config { * * @var string $remote_socket Remote entrypoint (can be a tcp or unix domain address) * @var int $timeout Timeout before canceling request @@ -50,13 +47,8 @@ class Client implements HttpClient * @var int $ssl_method Crypto method for ssl/tls, see PHP doc, defaults to STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT * } */ - public function __construct(ResponseFactory $responseFactory = null, array $config = []) + public function __construct(array $config = []) { - if (null === $responseFactory) { - $responseFactory = MessageFactoryDiscovery::find(); - } - - $this->responseFactory = $responseFactory; $this->config = $this->configure($config); } diff --git a/src/Exception/BrokenPipeException.php b/src/Exception/BrokenPipeException.php index 58eb1bb..4cf4b62 100644 --- a/src/Exception/BrokenPipeException.php +++ b/src/Exception/BrokenPipeException.php @@ -2,8 +2,6 @@ namespace Http\Client\Socket\Exception; -use Http\Client\Exception\NetworkException; - class BrokenPipeException extends NetworkException { } diff --git a/src/Exception/ConnectionException.php b/src/Exception/ConnectionException.php index 88dc252..67b628d 100644 --- a/src/Exception/ConnectionException.php +++ b/src/Exception/ConnectionException.php @@ -2,8 +2,6 @@ namespace Http\Client\Socket\Exception; -use Http\Client\Exception\NetworkException; - class ConnectionException extends NetworkException { } diff --git a/src/Exception/InvalidRequestException.php b/src/Exception/InvalidRequestException.php index fe77314..227375b 100644 --- a/src/Exception/InvalidRequestException.php +++ b/src/Exception/InvalidRequestException.php @@ -2,8 +2,6 @@ namespace Http\Client\Socket\Exception; -use Http\Client\Exception\NetworkException; - class InvalidRequestException extends NetworkException { } diff --git a/src/Exception/NetworkException.php b/src/Exception/NetworkException.php new file mode 100644 index 0000000..f3a6b3c --- /dev/null +++ b/src/Exception/NetworkException.php @@ -0,0 +1,23 @@ +request = $request; + + parent::__construct($message, 0, $previous); + } + + public function getRequest(): RequestInterface + { + return $this->request; + } +} diff --git a/src/Exception/SSLConnectionException.php b/src/Exception/SSLConnectionException.php index 534a487..b1f85ef 100644 --- a/src/Exception/SSLConnectionException.php +++ b/src/Exception/SSLConnectionException.php @@ -2,8 +2,6 @@ namespace Http\Client\Socket\Exception; -use Http\Client\Exception\NetworkException; - class SSLConnectionException extends NetworkException { } diff --git a/src/Exception/StreamException.php b/src/Exception/StreamException.php index 6437cec..472472d 100644 --- a/src/Exception/StreamException.php +++ b/src/Exception/StreamException.php @@ -2,37 +2,8 @@ namespace Http\Client\Socket\Exception; -use Http\Client\Exception; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Client\ClientExceptionInterface; -class StreamException extends \RuntimeException implements Exception +class StreamException extends \RuntimeException implements ClientExceptionInterface { - /** - * The request object. - * - * @var RequestInterface - */ - private $request; - - /** - * Accepts an optional request object as 4th param. - * - * @param string $message - * @param int $code - * @param Exception $previous - * @param RequestInterface $request - */ - public function __construct($message = null, $code = null, $previous = null, RequestInterface $request = null) - { - $this->request = $request; - parent::__construct($message, $code, $previous); - } - - /** - * @return \Psr\Http\Message\RequestInterface|null - */ - final public function getRequest() - { - return $this->request; - } } diff --git a/src/Exception/TimeoutException.php b/src/Exception/TimeoutException.php index 9d05407..a821ab5 100644 --- a/src/Exception/TimeoutException.php +++ b/src/Exception/TimeoutException.php @@ -2,6 +2,6 @@ namespace Http\Client\Socket\Exception; -class TimeoutException extends StreamException +class TimeoutException extends NetworkException { } diff --git a/src/ResponseReader.php b/src/ResponseReader.php index e631426..f8f94c5 100644 --- a/src/ResponseReader.php +++ b/src/ResponseReader.php @@ -5,6 +5,7 @@ use Http\Client\Socket\Exception\BrokenPipeException; use Http\Client\Socket\Exception\TimeoutException; use Http\Message\ResponseFactory; +use Nyholm\Psr7\Response; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -76,8 +77,8 @@ protected function readResponse(RequestInterface $request, $socket): ResponseInt : ''; } - $response = $this->responseFactory->createResponse($status, $reason, $responseHeaders, null, $protocol); - $stream = $this->createStream($socket, $response); + $response = new Response($status, $responseHeaders, null, $protocol, $reason); + $stream = $this->createStream($socket, $request, $response); return $response->withBody($stream); } @@ -87,7 +88,7 @@ protected function readResponse(RequestInterface $request, $socket): ResponseInt * * @param resource $socket */ - protected function createStream($socket, ResponseInterface $response): Stream + protected function createStream($socket, RequestInterface $request, ResponseInterface $response): Stream { $size = null; @@ -95,6 +96,6 @@ protected function createStream($socket, ResponseInterface $response): Stream $size = (int) $response->getHeaderLine('Content-Length'); } - return new Stream($socket, $size); + return new Stream($request, $socket, $size); } } diff --git a/src/Stream.php b/src/Stream.php index 00f2503..f98533a 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -4,6 +4,7 @@ use Http\Client\Socket\Exception\StreamException; use Http\Client\Socket\Exception\TimeoutException; +use Psr\Http\Message\RequestInterface; use Psr\Http\Message\StreamInterface; /** @@ -42,16 +43,21 @@ class Stream implements StreamInterface */ private $readed = 0; + /** + * @var RequestInterface request associated to this stream + */ + private $request; + /** * Create the stream. * * @param resource $socket - * @param int $size */ - public function __construct($socket, ?int $size = null) + public function __construct(RequestInterface $request, $socket, ?int $size = null) { $this->socket = $socket; $this->size = $size; + $this->request = $request; } /** @@ -175,7 +181,7 @@ public function read($length) $read = fread($this->socket, $length); if ($this->getMetadata('timed_out')) { - throw new TimeoutException('Stream timed out while reading data'); + throw new TimeoutException('Stream timed out while reading data', $this->request); } $this->readed += strlen($read); diff --git a/tests/SocketHttpClientTest.php b/tests/SocketHttpClientTest.php index e8981e6..3a957b3 100644 --- a/tests/SocketHttpClientTest.php +++ b/tests/SocketHttpClientTest.php @@ -12,7 +12,7 @@ public function createClient($options = []) { $messageFactory = new GuzzleMessageFactory(); - return new HttpMethodsClient(new SocketHttpClient($messageFactory, $options), $messageFactory); + return new HttpMethodsClient(new SocketHttpClient($options), $messageFactory); } public function testTcpSocketDomain() @@ -26,7 +26,7 @@ public function testTcpSocketDomain() } /** - * @expectedException \Http\Client\Exception\NetworkException + * @expectedException \Http\Client\Socket\Exception\NetworkException */ public function testNoRemote() { @@ -55,7 +55,7 @@ public function testRemoteInHostHeader() } /** - * @expectedException \Http\Client\Exception\NetworkException + * @expectedException \Http\Client\Socket\Exception\NetworkException */ public function testBrokenSocket() { @@ -95,7 +95,7 @@ public function testUnixSocketDomain() } /** - * @expectedException \Http\Client\Exception\NetworkException + * @expectedException \Http\Client\Socket\Exception\NetworkException */ public function testNetworkExceptionOnConnectError() { @@ -173,7 +173,7 @@ public function testInvalidSslConnectionWithClientCertificate() } /** - * @expectedException \Http\Client\Exception\NetworkException + * @expectedException \Http\Client\Socket\Exception\NetworkException */ public function testNetworkExceptionOnSslError() { @@ -184,7 +184,7 @@ public function testNetworkExceptionOnSslError() } /** - * @expectedException \Http\Client\Exception\NetworkException + * @expectedException \Http\Client\Socket\Exception\NetworkException */ public function testNetworkExceptionOnTimeout() { diff --git a/tests/StreamTest.php b/tests/StreamTest.php index 0bd21e6..11ad293 100644 --- a/tests/StreamTest.php +++ b/tests/StreamTest.php @@ -3,6 +3,7 @@ namespace Http\Client\Socket\Tests; use Http\Client\Socket\Stream; +use Nyholm\Psr7\Request; use PHPUnit\Framework\TestCase; class StreamTest extends TestCase @@ -13,7 +14,7 @@ public function createSocket($body, $useSize = true) fwrite($socket, $body); fseek($socket, 0); - return new Stream($socket, $useSize ? strlen($body) : null); + return new Stream(new Request('GET', '/'), $socket, $useSize ? strlen($body) : null); } public function testToString() @@ -56,7 +57,7 @@ public function testEof() $socket = fopen('php://memory', 'rw+'); fwrite($socket, 'Body'); fseek($socket, 0); - $stream = new Stream($socket); + $stream = new Stream(new Request('GET', '/'), $socket); $this->assertEquals('Body', $stream->getContents()); fwrite($socket, "\0"); @@ -116,7 +117,7 @@ public function testTimeout() $socket = fsockopen('php.net', 80); socket_set_timeout($socket, 0, 100); - $stream = new Stream($socket, 50); + $stream = new Stream(new Request('GET', '/'), $socket, 50); $stream->getContents(); } @@ -138,7 +139,7 @@ public function testClose() fwrite($socket, 'Body'); fseek($socket, 0); - $stream = new Stream($socket); + $stream = new Stream(new Request('GET', '/'), $socket); $stream->close(); $this->assertFalse(is_resource($socket)); From 9a182a9d66345d8571c1623c183ce49fd69e38ec Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Sat, 16 Feb 2019 22:59:47 +0100 Subject: [PATCH 11/16] Fix tests --- composer.json | 2 +- tests/SocketClientFeatureTest.php | 3 ++- tests/SocketHttpAdapterTest.php | 3 ++- tests/server/ssl/file.srl | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index f3e0bb1..19b3ff7 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.2", - "php-http/client-integration-tests": "^2.0", + "php-http/client-integration-tests": "dev-master", "php-http/message": "^1.0", "php-http/client-common": "^2.0" }, diff --git a/tests/SocketClientFeatureTest.php b/tests/SocketClientFeatureTest.php index d02dea8..aa614c4 100644 --- a/tests/SocketClientFeatureTest.php +++ b/tests/SocketClientFeatureTest.php @@ -4,10 +4,11 @@ use Http\Client\Tests\HttpFeatureTest; use Http\Client\Socket\Client as SocketHttpClient; +use Psr\Http\Client\ClientInterface; class SocketClientFeatureTest extends HttpFeatureTest { - protected function createClient() + protected function createClient(): ClientInterface { return new SocketHttpClient(); } diff --git a/tests/SocketHttpAdapterTest.php b/tests/SocketHttpAdapterTest.php index 143d4b4..7aa785b 100644 --- a/tests/SocketHttpAdapterTest.php +++ b/tests/SocketHttpAdapterTest.php @@ -4,13 +4,14 @@ use Http\Client\Tests\HttpClientTest; use Http\Client\Socket\Client as SocketHttpClient; +use Psr\Http\Client\ClientInterface; class SocketHttpAdapterTest extends HttpClientTest { /** * {@inheritdoc} */ - protected function createHttpAdapter() + protected function createHttpAdapter(): ClientInterface { return new SocketHttpClient(); } diff --git a/tests/server/ssl/file.srl b/tests/server/ssl/file.srl index f5c8955..a787364 100644 --- a/tests/server/ssl/file.srl +++ b/tests/server/ssl/file.srl @@ -1 +1 @@ -32 +34 From 927aabb3b51e3ddc0be68da7129bccdf98355bd5 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Sat, 16 Feb 2019 23:09:57 +0100 Subject: [PATCH 12/16] Readd httplug deps as we use interface in Client --- composer.json | 1 + src/Client.php | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 19b3ff7..59d5098 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "require": { "php": "^7.1", "nyholm/psr7": "^1.0", + "php-http/httplug": "^2.0", "psr/http-client": "^1.0", "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0" }, diff --git a/src/Client.php b/src/Client.php index 435ac18..37df5b9 100644 --- a/src/Client.php +++ b/src/Client.php @@ -47,8 +47,16 @@ class Client implements HttpClient * @var int $ssl_method Crypto method for ssl/tls, see PHP doc, defaults to STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT * } */ - public function __construct(array $config = []) + public function __construct($config1 = [], $config2 = null, array $config = []) { + if (\is_array($config1)) { + $this->config = $this->configure($config1); + + return; + } + + @trigger_error(E_USER_DEPRECATED, 'Passing a Psr\Http\Message\ResponseFactoryInterface and a Psr\Http\Message\StreamFactoryInterface to SocketClient is deprecated, and will be removed in 3.0, you should only pass config options.'); + $this->config = $this->configure($config); } From fddb55d32b035783948bf934fec4ef1ff1022bd7 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 21 Jan 2019 16:37:32 +0100 Subject: [PATCH 13/16] Add async support --- .travis.yml | 7 ++++++- composer.json | 1 + src/Client.php | 8 ++++++++ src/ResponseReader.php | 2 +- tests/AsyncTest.php | 37 ++++++++++++++++++++++++++++++++++ tests/SocketHttpClientTest.php | 11 ++++++---- 6 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 tests/AsyncTest.php diff --git a/.travis.yml b/.travis.yml index 28a8944..1344f3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,12 +26,17 @@ matrix: env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci" - php: 7.2 env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + - php: 7.3 + env: USE_ASYNC=true before_install: - travis_retry composer self-update + - if [[ "$USE_ASYNC" = true ]]; then git clone https://github.com/concurrent-php/ext-async.git /tmp/async; fi + - if [[ "$USE_ASYNC" = true ]]; then cd /tmp/async && phpize && ./configure && sudo make install; fi + - if [[ "$USE_ASYNC" = true ]]; then echo "extension = async.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini && php -m && cd $TRAVIS_BUILD_DIR; fi install: - - travis_retry composer update ${COMPOSER_FLAGS} --prefer-source --no-interaction + - travis_retry composer update ${COMPOSER_FLAGS} --prefer-source --no-interaction --ignore-platform-reqs before_script: - vendor/bin/http_test_server > /dev/null 2>&1 & diff --git a/composer.json b/composer.json index 59d5098..db2eccf 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0" }, "require-dev": { + "concurrent-php/async-api": "dev-master", "friendsofphp/php-cs-fixer": "^2.2", "php-http/client-integration-tests": "dev-master", "php-http/message": "^1.0", diff --git a/src/Client.php b/src/Client.php index 37df5b9..60b6f4e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -33,6 +33,8 @@ class Client implements HttpClient 'ssl_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, ]; + private $hasAsync; + /** * Constructor. * @@ -49,6 +51,8 @@ class Client implements HttpClient */ public function __construct($config1 = [], $config2 = null, array $config = []) { + $this->hasAsync = PHP_VERSION_ID >= 70300 && \extension_loaded('async'); + if (\is_array($config1)) { $this->config = $this->configure($config1); @@ -182,6 +186,10 @@ private function determineRemoteFromRequest(RequestInterface $request) $endpoint = $request->getHeaderLine('Host'); } + if ($this->hasAsync) { + return sprintf('async-tcp://%s', $endpoint); + } + return sprintf('tcp://%s', $endpoint); } } diff --git a/src/ResponseReader.php b/src/ResponseReader.php index f8f94c5..97bd314 100644 --- a/src/ResponseReader.php +++ b/src/ResponseReader.php @@ -46,7 +46,7 @@ protected function readResponse(RequestInterface $request, $socket): ResponseInt $metadatas = stream_get_meta_data($socket); if (array_key_exists('timed_out', $metadatas) && true === $metadatas['timed_out']) { - throw new TimeoutException('Error while reading response, stream timed out', null, null, $request); + throw new TimeoutException('Error while reading response, stream timed out', $request, null); } $parts = explode(' ', array_shift($headers), 3); diff --git a/tests/AsyncTest.php b/tests/AsyncTest.php new file mode 100644 index 0000000..58f62d8 --- /dev/null +++ b/tests/AsyncTest.php @@ -0,0 +1,37 @@ +markTestSkipped('Test need async extension'); + } + + $client = new Client(); + $request = new Request('GET', 'https://httpbin.org/delay/1'); + + $timeStart = microtime(true); + $task1 = Task::async(function () use ($request, $client) { + return $client->sendRequest($request); + }); + $task2 = Task::async(function () use ($request, $client) { + return $client->sendRequest($request); + }); + + [$response1, $response2] = Task::await(all([$task1, $task2])); + $timeTaken = microtime(true) - $timeStart; + + self::assertLessThan(2, $timeTaken); + self::assertEquals(200, $response1->getStatusCode()); + self::assertEquals(200, $response2->getStatusCode()); + } +} diff --git a/tests/SocketHttpClientTest.php b/tests/SocketHttpClientTest.php index 3a957b3..cfec8ce 100644 --- a/tests/SocketHttpClientTest.php +++ b/tests/SocketHttpClientTest.php @@ -68,6 +68,8 @@ public function testSslRemoteInUri() { $this->startServer('tcp-ssl-server'); $client = $this->createClient([ + 'remote_socket' => 'tcp://127.0.0.1:19999', + 'ssl' => true, 'stream_context_options' => [ 'ssl' => [ 'peer_name' => 'socket-adapter', @@ -75,7 +77,7 @@ public function testSslRemoteInUri() ], ], ]); - $response = $client->get('https://127.0.0.1:19999/', []); + $response = $client->get('/', []); $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response); $this->assertEquals(200, $response->getStatusCode()); @@ -184,11 +186,12 @@ public function testNetworkExceptionOnSslError() } /** - * @expectedException \Http\Client\Socket\Exception\NetworkException + * @expectedException \Http\Client\Socket\Exception\TimeoutException */ public function testNetworkExceptionOnTimeout() { - $client = $this->createClient(['timeout' => 10]); - $client->get('http://php.net', []); + $client = $this->createClient(['timeout' => 1]); + $response = $client->get('https://php.net', []); + $response->getBody()->getContents(); } } From ccb26020087dabff7d4c998c2a93c884f5d16fbb Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Sat, 16 Feb 2019 23:30:33 +0100 Subject: [PATCH 14/16] Update changelog with last changes --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da849c..f92a44d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 2.0.0 (unreleased) + * Remove response and stream factory, use direct implementation of nyholm/psr7 + * Async support with ext-async extension: see https://github.com/concurrent-php/ext-async * PSR18 and HTTPlug 2 support * Remove support for php 5.5, 5.6 and 7.0 * SSL Method now defaults to `STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT` From 3bdc0a2fa0e5fd4ada9c8914b4fdcff0a29c5aa3 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Wed, 20 Feb 2019 10:12:23 +0100 Subject: [PATCH 15/16] Fix travis file --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1344f3f..8b584a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ matrix: include: - php: 7.1 env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci" - - php: 7.2 + - php: 7.2 env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" - php: 7.3 env: USE_ASYNC=true From 6717d0cc3d00657cdbd00473af023ff7a74fbd7d Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Wed, 20 Feb 2019 10:26:32 +0100 Subject: [PATCH 16/16] Use correct exception on connect --- src/Client.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Client.php b/src/Client.php index 60b6f4e..9c5a3d6 100644 --- a/src/Client.php +++ b/src/Client.php @@ -6,6 +6,7 @@ use Http\Client\Socket\Exception\ConnectionException; use Http\Client\Socket\Exception\InvalidRequestException; use Http\Client\Socket\Exception\SSLConnectionException; +use Http\Client\Socket\Exception\TimeoutException; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Component\OptionsResolver\Options; @@ -116,6 +117,10 @@ protected function createSocket(RequestInterface $request, string $remote, bool $socket = @stream_socket_client($remote, $errNo, $errMsg, floor($this->config['timeout'] / 1000), STREAM_CLIENT_CONNECT, $this->config['stream_context']); if (false === $socket) { + if (110 === $errNo) { + throw new TimeoutException($errMsg, $request); + } + throw new ConnectionException($errMsg, $request); }