Skip to content

Commit fddb55d

Browse files
committed
Add async support
1 parent 927aabb commit fddb55d

File tree

6 files changed

+60
-6
lines changed

6 files changed

+60
-6
lines changed

.travis.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@ matrix:
2626
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci"
2727
- php: 7.2
2828
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest"
29+
- php: 7.3
30+
env: USE_ASYNC=true
2931

3032
before_install:
3133
- travis_retry composer self-update
34+
- if [[ "$USE_ASYNC" = true ]]; then git clone https://github.com/concurrent-php/ext-async.git /tmp/async; fi
35+
- if [[ "$USE_ASYNC" = true ]]; then cd /tmp/async && phpize && ./configure && sudo make install; fi
36+
- if [[ "$USE_ASYNC" = true ]]; then echo "extension = async.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini && php -m && cd $TRAVIS_BUILD_DIR; fi
3237

3338
install:
34-
- travis_retry composer update ${COMPOSER_FLAGS} --prefer-source --no-interaction
39+
- travis_retry composer update ${COMPOSER_FLAGS} --prefer-source --no-interaction --ignore-platform-reqs
3540

3641
before_script:
3742
- vendor/bin/http_test_server > /dev/null 2>&1 &

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"symfony/options-resolver": "^2.6 || ^3.0 || ^4.0"
1717
},
1818
"require-dev": {
19+
"concurrent-php/async-api": "dev-master",
1920
"friendsofphp/php-cs-fixer": "^2.2",
2021
"php-http/client-integration-tests": "dev-master",
2122
"php-http/message": "^1.0",

src/Client.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class Client implements HttpClient
3333
'ssl_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
3434
];
3535

36+
private $hasAsync;
37+
3638
/**
3739
* Constructor.
3840
*
@@ -49,6 +51,8 @@ class Client implements HttpClient
4951
*/
5052
public function __construct($config1 = [], $config2 = null, array $config = [])
5153
{
54+
$this->hasAsync = PHP_VERSION_ID >= 70300 && \extension_loaded('async');
55+
5256
if (\is_array($config1)) {
5357
$this->config = $this->configure($config1);
5458

@@ -182,6 +186,10 @@ private function determineRemoteFromRequest(RequestInterface $request)
182186
$endpoint = $request->getHeaderLine('Host');
183187
}
184188

189+
if ($this->hasAsync) {
190+
return sprintf('async-tcp://%s', $endpoint);
191+
}
192+
185193
return sprintf('tcp://%s', $endpoint);
186194
}
187195
}

src/ResponseReader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected function readResponse(RequestInterface $request, $socket): ResponseInt
4646
$metadatas = stream_get_meta_data($socket);
4747

4848
if (array_key_exists('timed_out', $metadatas) && true === $metadatas['timed_out']) {
49-
throw new TimeoutException('Error while reading response, stream timed out', null, null, $request);
49+
throw new TimeoutException('Error while reading response, stream timed out', $request, null);
5050
}
5151

5252
$parts = explode(' ', array_shift($headers), 3);

tests/AsyncTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Http\Client\Socket\Tests;
4+
5+
use function Concurrent\all;
6+
use Concurrent\Task;
7+
use GuzzleHttp\Psr7\Request;
8+
use Http\Client\Socket\Client;
9+
use PHPUnit\Framework\TestCase;
10+
11+
class AsyncTest extends TestCase
12+
{
13+
public function testAsync()
14+
{
15+
if (PHP_VERSION_ID < 70300 || !extension_loaded('async')) {
16+
$this->markTestSkipped('Test need async extension');
17+
}
18+
19+
$client = new Client();
20+
$request = new Request('GET', 'https://httpbin.org/delay/1');
21+
22+
$timeStart = microtime(true);
23+
$task1 = Task::async(function () use ($request, $client) {
24+
return $client->sendRequest($request);
25+
});
26+
$task2 = Task::async(function () use ($request, $client) {
27+
return $client->sendRequest($request);
28+
});
29+
30+
[$response1, $response2] = Task::await(all([$task1, $task2]));
31+
$timeTaken = microtime(true) - $timeStart;
32+
33+
self::assertLessThan(2, $timeTaken);
34+
self::assertEquals(200, $response1->getStatusCode());
35+
self::assertEquals(200, $response2->getStatusCode());
36+
}
37+
}

tests/SocketHttpClientTest.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,16 @@ public function testSslRemoteInUri()
6868
{
6969
$this->startServer('tcp-ssl-server');
7070
$client = $this->createClient([
71+
'remote_socket' => 'tcp://127.0.0.1:19999',
72+
'ssl' => true,
7173
'stream_context_options' => [
7274
'ssl' => [
7375
'peer_name' => 'socket-adapter',
7476
'cafile' => __DIR__.'/server/ssl/ca.pem',
7577
],
7678
],
7779
]);
78-
$response = $client->get('https://127.0.0.1:19999/', []);
80+
$response = $client->get('/', []);
7981

8082
$this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response);
8183
$this->assertEquals(200, $response->getStatusCode());
@@ -184,11 +186,12 @@ public function testNetworkExceptionOnSslError()
184186
}
185187

186188
/**
187-
* @expectedException \Http\Client\Socket\Exception\NetworkException
189+
* @expectedException \Http\Client\Socket\Exception\TimeoutException
188190
*/
189191
public function testNetworkExceptionOnTimeout()
190192
{
191-
$client = $this->createClient(['timeout' => 10]);
192-
$client->get('http://php.net', []);
193+
$client = $this->createClient(['timeout' => 1]);
194+
$response = $client->get('https://php.net', []);
195+
$response->getBody()->getContents();
193196
}
194197
}

0 commit comments

Comments
 (0)