Merge branch '4.4' into 5.0
* 4.4: Use ">=" for the "php" requirement [HttpClient] Fix promise behavior in HttplugClient
This commit is contained in:
commit
085e66cfc2
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\HttpClient;
|
namespace Symfony\Component\HttpClient;
|
||||||
|
|
||||||
use GuzzleHttp\Promise\Promise as GuzzlePromise;
|
use GuzzleHttp\Promise\Promise as GuzzlePromise;
|
||||||
|
use GuzzleHttp\Promise\RejectedPromise;
|
||||||
use Http\Client\Exception\NetworkException;
|
use Http\Client\Exception\NetworkException;
|
||||||
use Http\Client\Exception\RequestException;
|
use Http\Client\Exception\RequestException;
|
||||||
use Http\Client\HttpAsyncClient;
|
use Http\Client\HttpAsyncClient;
|
||||||
@ -22,7 +23,6 @@ use Http\Message\RequestFactory;
|
|||||||
use Http\Message\StreamFactory;
|
use Http\Message\StreamFactory;
|
||||||
use Http\Message\UriFactory;
|
use Http\Message\UriFactory;
|
||||||
use Http\Promise\Promise;
|
use Http\Promise\Promise;
|
||||||
use Http\Promise\RejectedPromise;
|
|
||||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||||
use Nyholm\Psr7\Request;
|
use Nyholm\Psr7\Request;
|
||||||
use Nyholm\Psr7\Uri;
|
use Nyholm\Psr7\Uri;
|
||||||
@ -114,7 +114,7 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF
|
|||||||
try {
|
try {
|
||||||
$response = $this->sendPsr7Request($request, true);
|
$response = $this->sendPsr7Request($request, true);
|
||||||
} catch (NetworkException $e) {
|
} catch (NetworkException $e) {
|
||||||
return new RejectedPromise($e);
|
return new HttplugPromise(new RejectedPromise($e));
|
||||||
}
|
}
|
||||||
|
|
||||||
$waitLoop = $this->waitLoop;
|
$waitLoop = $this->waitLoop;
|
||||||
|
@ -54,6 +54,12 @@ final class HttplugPromise implements HttplugPromiseInterface
|
|||||||
*/
|
*/
|
||||||
public function wait($unwrap = true)
|
public function wait($unwrap = true)
|
||||||
{
|
{
|
||||||
return $this->promise->wait($unwrap);
|
$result = $this->promise->wait($unwrap);
|
||||||
|
|
||||||
|
while ($result instanceof HttplugPromiseInterface || $result instanceof GuzzlePromiseInterface) {
|
||||||
|
$result = $result->wait($unwrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,18 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\HttpClient\Tests;
|
namespace Symfony\Component\HttpClient\Tests;
|
||||||
|
|
||||||
|
use GuzzleHttp\Promise\FulfilledPromise as GuzzleFulfilledPromise;
|
||||||
use Http\Client\Exception\NetworkException;
|
use Http\Client\Exception\NetworkException;
|
||||||
use Http\Client\Exception\RequestException;
|
use Http\Client\Exception\RequestException;
|
||||||
|
use Http\Promise\FulfilledPromise;
|
||||||
use Http\Promise\Promise;
|
use Http\Promise\Promise;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||||
use Symfony\Component\HttpClient\HttplugClient;
|
use Symfony\Component\HttpClient\HttplugClient;
|
||||||
|
use Symfony\Component\HttpClient\MockHttpClient;
|
||||||
use Symfony\Component\HttpClient\NativeHttpClient;
|
use Symfony\Component\HttpClient\NativeHttpClient;
|
||||||
|
use Symfony\Component\HttpClient\Response\MockResponse;
|
||||||
use Symfony\Contracts\HttpClient\Test\TestHttpServer;
|
use Symfony\Contracts\HttpClient\Test\TestHttpServer;
|
||||||
|
|
||||||
class HttplugClientTest extends TestCase
|
class HttplugClientTest extends TestCase
|
||||||
@ -152,4 +157,114 @@ class HttplugClientTest extends TestCase
|
|||||||
$this->expectException(RequestException::class);
|
$this->expectException(RequestException::class);
|
||||||
$client->sendRequest($client->createRequest('BAD.METHOD', 'http://localhost:8057'));
|
$client->sendRequest($client->createRequest('BAD.METHOD', 'http://localhost:8057'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRetry404()
|
||||||
|
{
|
||||||
|
$client = new HttplugClient(new NativeHttpClient());
|
||||||
|
|
||||||
|
$successCallableCalled = false;
|
||||||
|
$failureCallableCalled = false;
|
||||||
|
|
||||||
|
$promise = $client
|
||||||
|
->sendAsyncRequest($client->createRequest('GET', 'http://localhost:8057/404'))
|
||||||
|
->then(
|
||||||
|
function (ResponseInterface $response) use (&$successCallableCalled, $client) {
|
||||||
|
$this->assertSame(404, $response->getStatusCode());
|
||||||
|
$successCallableCalled = true;
|
||||||
|
|
||||||
|
return $client->sendAsyncRequest($client->createRequest('GET', 'http://localhost:8057'));
|
||||||
|
},
|
||||||
|
function (\Exception $exception) use (&$failureCallableCalled) {
|
||||||
|
$failureCallableCalled = true;
|
||||||
|
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
$response = $promise->wait(true);
|
||||||
|
|
||||||
|
$this->assertTrue($successCallableCalled);
|
||||||
|
$this->assertFalse($failureCallableCalled);
|
||||||
|
$this->assertSame(200, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRetryNetworkError()
|
||||||
|
{
|
||||||
|
$client = new HttplugClient(new NativeHttpClient());
|
||||||
|
|
||||||
|
$successCallableCalled = false;
|
||||||
|
$failureCallableCalled = false;
|
||||||
|
|
||||||
|
$promise = $client
|
||||||
|
->sendAsyncRequest($client->createRequest('GET', 'http://localhost:8057/chunked-broken'))
|
||||||
|
->then(function (ResponseInterface $response) use (&$successCallableCalled) {
|
||||||
|
$successCallableCalled = true;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}, function (\Exception $exception) use (&$failureCallableCalled, $client) {
|
||||||
|
$this->assertSame(NetworkException::class, \get_class($exception));
|
||||||
|
$this->assertSame(TransportException::class, \get_class($exception->getPrevious()));
|
||||||
|
$failureCallableCalled = true;
|
||||||
|
|
||||||
|
return $client->sendAsyncRequest($client->createRequest('GET', 'http://localhost:8057'));
|
||||||
|
})
|
||||||
|
;
|
||||||
|
|
||||||
|
$response = $promise->wait(true);
|
||||||
|
|
||||||
|
$this->assertFalse($successCallableCalled);
|
||||||
|
$this->assertTrue($failureCallableCalled);
|
||||||
|
$this->assertSame(200, $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRetryEarlierError()
|
||||||
|
{
|
||||||
|
$isFirstRequest = true;
|
||||||
|
$errorMessage = 'Error occurred before making the actual request.';
|
||||||
|
|
||||||
|
$client = new HttplugClient(new MockHttpClient(function () use (&$isFirstRequest, $errorMessage) {
|
||||||
|
if ($isFirstRequest) {
|
||||||
|
$isFirstRequest = false;
|
||||||
|
throw new TransportException($errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MockResponse('OK', ['http_code' => 200]);
|
||||||
|
}));
|
||||||
|
|
||||||
|
$request = $client->createRequest('GET', 'http://test');
|
||||||
|
|
||||||
|
$successCallableCalled = false;
|
||||||
|
$failureCallableCalled = false;
|
||||||
|
|
||||||
|
$promise = $client
|
||||||
|
->sendAsyncRequest($request)
|
||||||
|
->then(
|
||||||
|
function (ResponseInterface $response) use (&$successCallableCalled) {
|
||||||
|
$successCallableCalled = true;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
},
|
||||||
|
function (\Exception $exception) use ($errorMessage, &$failureCallableCalled, $client, $request) {
|
||||||
|
$this->assertSame(NetworkException::class, \get_class($exception));
|
||||||
|
$this->assertSame($errorMessage, $exception->getMessage());
|
||||||
|
$failureCallableCalled = true;
|
||||||
|
|
||||||
|
// Ensure arbitrary levels of promises work.
|
||||||
|
return (new FulfilledPromise(null))->then(function () use ($client, $request) {
|
||||||
|
return (new GuzzleFulfilledPromise(null))->then(function () use ($client, $request) {
|
||||||
|
return $client->sendAsyncRequest($request);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
$response = $promise->wait(true);
|
||||||
|
|
||||||
|
$this->assertFalse($successCallableCalled);
|
||||||
|
$this->assertTrue($failureCallableCalled);
|
||||||
|
$this->assertSame(200, $response->getStatusCode());
|
||||||
|
$this->assertSame('OK', (string) $response->getBody());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user