Skip to content

Commit

Permalink
Merge fd4bef9 into 2e204c3
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Aug 22, 2019
2 parents 2e204c3 + fd4bef9 commit 6f320e8
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 5 deletions.
12 changes: 8 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"amphp/php-cs-fixer-config": "dev-master",
"phpunit/phpunit": "^7 || ^8",
"friendsofphp/php-cs-fixer": "^2.15",
"amphp/http-server": "v2.x-dev"
"amphp/http-server": "v2.0.0-rc1"
},
"suggest": {
"ext-zlib": "*",
Expand All @@ -57,8 +57,12 @@
}
},
"scripts": {
"cs-fix": [
"php-cs-fixer fix --config=./.php_cs.dist"
]
"check": [
"@cs",
"@test"
],
"cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
"test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
}
}
1 change: 0 additions & 1 deletion src/Connection/Http2Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\CancellationTokenSource;
use Amp\CancelledException;
Expand Down
19 changes: 19 additions & 0 deletions src/Interceptor/SetRequestTimeout.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;

final class SetRequestTimeout extends ModifyRequest
{
public function __construct(int $tcpConnectTimeout = 10000, int $tlsHandshakeTimeout = 10000, int $transferTimeout = 10000)
{
parent::__construct(static function (Request $request) use ($tcpConnectTimeout, $tlsHandshakeTimeout, $transferTimeout) {
$request->setTcpConnectTimeout($tcpConnectTimeout);
$request->setTlsHandshakeTimeout($tlsHandshakeTimeout);
$request->setTransferTimeout($transferTimeout);

return $request;
});
}
}
113 changes: 113 additions & 0 deletions test/TimeoutTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Amp\Deferred;
use Amp\Http\Client\Client;
use Amp\Http\Client\Connection\DefaultConnectionPool;
use Amp\Http\Client\Interceptor\SetRequestTimeout;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Client\TimeoutException;
Expand Down Expand Up @@ -133,4 +134,116 @@ public function testTimeoutDuringTlsEnable(): \Generator
$server->close();
}
}

public function testTimeoutDuringBodyInterceptor(): \Generator
{
$server = Socket\Server::listen("tcp://127.0.0.1:0");

asyncCall(static function () use ($server) {
/** @var Socket\EncryptableSocket $client */
while ($client = yield $server->accept()) {
yield $client->write("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\n.");

Loop::delay(3000, static function () use ($client) {
$client->close();
});
}
});

try {
$uri = "http://" . $server->getAddress() . "/";

$start = \microtime(true);

$request = new Request($uri);

/** @var Response $response */
$client = new Client;
$client->addApplicationInterceptor(new SetRequestTimeout(10000, 10000, 1000));
$response = yield $client->request($request);

$this->expectException(TimeoutException::class);
$this->expectExceptionMessage("Allowed transfer timeout exceeded, took longer than 1000 ms");

yield $response->getBody()->buffer();
} finally {
$this->assertLessThan(2, \microtime(true) - $start);
$server->close();
}
}

public function testTimeoutDuringConnectInterceptor(): \Generator
{
$start = \microtime(true);

Loop::repeat(1000, static function () {
// dummy watcher, because socket pool doesn't do anything
});

$connector = $this->createMock(Socket\Connector::class);
$connector->method('connect')
->willReturnCallback(static function (
string $uri,
?Socket\ConnectContext $connectContext = null,
?CancellationToken $token = null
): Promise {
$deferred = new Deferred;

if ($token) {
$token->subscribe([$deferred, 'fail']);
}

return $deferred->promise(); // never resolve
});

$client = new Client(new DefaultConnectionPool($connector));
$client->addApplicationInterceptor(new SetRequestTimeout(1));

$this->expectException(TimeoutException::class);
$this->expectExceptionMessage("Connection to 'localhost:1337' timed out, took longer than 1 ms");

$request = new Request('http://localhost:1337/');

yield $client->request($request);

$this->assertLessThan(\microtime(true) - $start, 0.6);
}

public function testTimeoutDuringTlsEnableInterceptor(): \Generator
{
$tlsContext = (new Socket\ServerTlsContext)
->withDefaultCertificate(new Socket\Certificate(__DIR__ . "/tls/amphp.org.pem"));

$server = Socket\Server::listen("tcp://127.0.0.1:0", (new Socket\BindContext)->withTlsContext($tlsContext));

asyncCall(static function () use ($server) {
/** @var Socket\ResourceSocket $client */
while ($client = yield $server->accept()) {
Loop::delay(3000, static function () use ($client) {
$client->close();
});
}
});

try {
$uri = "https://" . $server->getAddress() . "/";

$start = \microtime(true);

$this->expectException(TimeoutException::class);
$this->expectExceptionMessageRegExp("(TLS handshake with '127.0.0.1:\d+' @ '127.0.0.1:\d+' timed out, took longer than 100 ms)");

$request = new Request($uri);
$request->setTlsHandshakeTimeout(100);


$client = new Client();
$client->addApplicationInterceptor(new SetRequestTimeout(10000, 100));

yield $client->request($request);
} finally {
$this->assertLessThan(0.6, \microtime(true) - $start);
$server->close();
}
}
}

0 comments on commit 6f320e8

Please sign in to comment.