[HttpClient] add StreamableInterface to ease turning responses into PHP streams
This commit is contained in:
parent
75031a1230
commit
de103b31a9
@ -6,6 +6,7 @@ CHANGELOG
|
||||
|
||||
* added `AsyncDecoratorTrait` to ease processing responses without breaking async
|
||||
* added support for pausing responses with a new `pause_handler` callable exposed as an info item
|
||||
* added `StreamableInterface` to ease turning responses into PHP streams
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
@ -15,9 +15,8 @@ use Http\Client\Exception\NetworkException;
|
||||
use Psr\Http\Message\ResponseFactoryInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
|
||||
use Psr\Http\Message\StreamFactoryInterface;
|
||||
use Symfony\Component\HttpClient\Response\CommonResponseTrait;
|
||||
use Symfony\Component\HttpClient\Response\StreamableInterface;
|
||||
use Symfony\Component\HttpClient\Response\StreamWrapper;
|
||||
use Symfony\Component\HttpClient\Response\TraceableResponse;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
@ -120,7 +119,7 @@ final class HttplugWaitLoop
|
||||
}
|
||||
}
|
||||
|
||||
if ($response instanceof TraceableResponse || isset(class_uses($response)[CommonResponseTrait::class])) {
|
||||
if ($response instanceof StreamableInterface) {
|
||||
$body = $this->streamFactory->createStreamFromResource($response->toStream(false));
|
||||
} elseif (!$buffer) {
|
||||
$body = $this->streamFactory->createStreamFromResource(StreamWrapper::createResource($response, $this->client));
|
||||
|
@ -27,9 +27,8 @@ use Psr\Http\Message\StreamFactoryInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UriFactoryInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Symfony\Component\HttpClient\Response\CommonResponseTrait;
|
||||
use Symfony\Component\HttpClient\Response\StreamableInterface;
|
||||
use Symfony\Component\HttpClient\Response\StreamWrapper;
|
||||
use Symfony\Component\HttpClient\Response\TraceableResponse;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
@ -105,7 +104,7 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str
|
||||
}
|
||||
}
|
||||
|
||||
$body = $response instanceof TraceableResponse || isset(class_uses($response)[CommonResponseTrait::class]) ? $response->toStream(false) : StreamWrapper::createResource($response, $this->client);
|
||||
$body = $response instanceof StreamableInterface ? $response->toStream(false) : StreamWrapper::createResource($response, $this->client);
|
||||
$body = $this->streamFactory->createStreamFromResource($body);
|
||||
|
||||
if ($body->isSeekable()) {
|
||||
|
@ -33,7 +33,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class AmpResponse implements ResponseInterface
|
||||
final class AmpResponse implements ResponseInterface, StreamableInterface
|
||||
{
|
||||
use CommonResponseTrait;
|
||||
use TransportResponseTrait;
|
||||
|
@ -25,7 +25,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class AsyncResponse implements ResponseInterface
|
||||
final class AsyncResponse implements ResponseInterface, StreamableInterface
|
||||
{
|
||||
use CommonResponseTrait;
|
||||
|
||||
@ -95,7 +95,7 @@ final class AsyncResponse implements ResponseInterface
|
||||
}
|
||||
|
||||
$handle = function () {
|
||||
$stream = StreamWrapper::createResource($this->response);
|
||||
$stream = $this->response instanceof StreamableInterface ? $this->response->toStream(false) : StreamWrapper::createResource($this->response);
|
||||
|
||||
return stream_get_meta_data($stream)['wrapper_data']->stream_cast(STREAM_CAST_FOR_SELECT);
|
||||
};
|
||||
|
@ -16,10 +16,6 @@ use Symfony\Component\HttpClient\Exception\JsonException;
|
||||
use Symfony\Component\HttpClient\Exception\RedirectionException;
|
||||
use Symfony\Component\HttpClient\Exception\ServerException;
|
||||
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
/**
|
||||
* Implements common logic for response classes.
|
||||
@ -123,14 +119,7 @@ trait CommonResponseTrait
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts the response to a PHP stream resource.
|
||||
*
|
||||
* @return resource
|
||||
*
|
||||
* @throws TransportExceptionInterface When a network error occurs
|
||||
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
|
||||
* @throws ClientExceptionInterface On a 4xx when $throw is true
|
||||
* @throws ServerExceptionInterface On a 5xx when $throw is true
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toStream(bool $throw = true)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class CurlResponse implements ResponseInterface
|
||||
final class CurlResponse implements ResponseInterface, StreamableInterface
|
||||
{
|
||||
use CommonResponseTrait {
|
||||
getContent as private doGetContent;
|
||||
|
@ -23,7 +23,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class MockResponse implements ResponseInterface
|
||||
class MockResponse implements ResponseInterface, StreamableInterface
|
||||
{
|
||||
use CommonResponseTrait;
|
||||
use TransportResponseTrait {
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class NativeResponse implements ResponseInterface
|
||||
final class NativeResponse implements ResponseInterface, StreamableInterface
|
||||
{
|
||||
use CommonResponseTrait;
|
||||
use TransportResponseTrait;
|
||||
|
@ -49,7 +49,7 @@ class StreamWrapper
|
||||
*/
|
||||
public static function createResource(ResponseInterface $response, HttpClientInterface $client = null)
|
||||
{
|
||||
if ($response instanceof TraceableResponse || (\is_callable([$response, 'toStream']) && isset(class_uses($response)[CommonResponseTrait::class]))) {
|
||||
if ($response instanceof StreamableInterface) {
|
||||
$stack = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||||
|
||||
if ($response !== ($stack[1]['object'] ?? null)) {
|
||||
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpClient\Response;
|
||||
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
interface StreamableInterface
|
||||
{
|
||||
/**
|
||||
* Casts the response to a PHP stream resource.
|
||||
*
|
||||
* @return resource
|
||||
*
|
||||
* @throws TransportExceptionInterface When a network error occurs
|
||||
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
|
||||
* @throws ClientExceptionInterface On a 4xx when $throw is true
|
||||
* @throws ServerExceptionInterface On a 5xx when $throw is true
|
||||
*/
|
||||
public function toStream(bool $throw = true);
|
||||
}
|
@ -27,7 +27,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class TraceableResponse implements ResponseInterface
|
||||
class TraceableResponse implements ResponseInterface, StreamableInterface
|
||||
{
|
||||
private $client;
|
||||
private $response;
|
||||
@ -99,7 +99,7 @@ class TraceableResponse implements ResponseInterface
|
||||
$this->response->getHeaders(true);
|
||||
}
|
||||
|
||||
if (\is_callable([$this->response, 'toStream'])) {
|
||||
if ($this->response instanceof StreamableInterface) {
|
||||
return $this->response->toStream(false);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user