Skip to content

Commit

Permalink
[HttpClient] add StreamableInterface to ease turning responses into P…
Browse files Browse the repository at this point in the history
…HP streams
  • Loading branch information
nicolas-grekas committed Jun 28, 2020
1 parent 61aaa98 commit e8f06b5
Show file tree
Hide file tree
Showing 12 changed files with 50 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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
-----
Expand Down
5 changes: 2 additions & 3 deletions Internal/HttplugWaitLoop.php
Expand Up @@ -15,9 +15,8 @@
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;
Expand Down Expand Up @@ -120,7 +119,7 @@ public function createPsr7Response(ResponseInterface $response, bool $buffer = f
}
}

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));
Expand Down
5 changes: 2 additions & 3 deletions Psr18Client.php
Expand Up @@ -27,9 +27,8 @@
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;

Expand Down Expand Up @@ -105,7 +104,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface
}
}

$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()) {
Expand Down
2 changes: 1 addition & 1 deletion Response/AmpResponse.php
Expand Up @@ -33,7 +33,7 @@
*
* @internal
*/
final class AmpResponse implements ResponseInterface
final class AmpResponse implements ResponseInterface, StreamableInterface
{
use CommonResponseTrait;
use TransportResponseTrait;
Expand Down
4 changes: 2 additions & 2 deletions Response/AsyncResponse.php
Expand Up @@ -25,7 +25,7 @@
*
* @author Nicolas Grekas <p@tchwork.com>
*/
final class AsyncResponse implements ResponseInterface
final class AsyncResponse implements ResponseInterface, StreamableInterface
{
use CommonResponseTrait;

Expand Down Expand Up @@ -95,7 +95,7 @@ public function toStream(bool $throw = true)
}

$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);
};
Expand Down
13 changes: 1 addition & 12 deletions Response/CommonResponseTrait.php
Expand Up @@ -16,10 +16,6 @@
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.
Expand Down Expand Up @@ -123,14 +119,7 @@ public function toArray(bool $throw = true): array
}

/**
* 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)
{
Expand Down
2 changes: 1 addition & 1 deletion Response/CurlResponse.php
Expand Up @@ -25,7 +25,7 @@
*
* @internal
*/
final class CurlResponse implements ResponseInterface
final class CurlResponse implements ResponseInterface, StreamableInterface
{
use CommonResponseTrait {
getContent as private doGetContent;
Expand Down
2 changes: 1 addition & 1 deletion Response/MockResponse.php
Expand Up @@ -23,7 +23,7 @@
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class MockResponse implements ResponseInterface
class MockResponse implements ResponseInterface, StreamableInterface
{
use CommonResponseTrait;
use TransportResponseTrait {
Expand Down
2 changes: 1 addition & 1 deletion Response/NativeResponse.php
Expand Up @@ -24,7 +24,7 @@
*
* @internal
*/
final class NativeResponse implements ResponseInterface
final class NativeResponse implements ResponseInterface, StreamableInterface
{
use CommonResponseTrait;
use TransportResponseTrait;
Expand Down
2 changes: 1 addition & 1 deletion Response/StreamWrapper.php
Expand Up @@ -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)) {
Expand Down
35 changes: 35 additions & 0 deletions Response/StreamableInterface.php
@@ -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);
}
4 changes: 2 additions & 2 deletions Response/TraceableResponse.php
Expand Up @@ -27,7 +27,7 @@
*
* @internal
*/
class TraceableResponse implements ResponseInterface
class TraceableResponse implements ResponseInterface, StreamableInterface
{
private $client;
private $response;
Expand Down Expand Up @@ -99,7 +99,7 @@ public function toStream(bool $throw = true)
$this->response->getHeaders(true);
}

if (\is_callable([$this->response, 'toStream'])) {
if ($this->response instanceof StreamableInterface) {
return $this->response->toStream(false);
}

Expand Down

0 comments on commit e8f06b5

Please sign in to comment.