2023-07-15 10:16:32 +08:00
< ? 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 ;
use Symfony\Component\HttpClient\Exception\TransportException ;
use Symfony\Component\HttpClient\Response\MockResponse ;
use Symfony\Component\HttpClient\Response\ResponseStream ;
use Symfony\Contracts\HttpClient\HttpClientInterface ;
use Symfony\Contracts\HttpClient\ResponseInterface ;
use Symfony\Contracts\HttpClient\ResponseStreamInterface ;
use Symfony\Contracts\Service\ResetInterface ;
/**
* A test - friendly HttpClient that doesn ' t make actual HTTP requests .
*
* @ author Nicolas Grekas < p @ tchwork . com >
*/
class MockHttpClient implements HttpClientInterface , ResetInterface
{
use HttpClientTrait ;
2023-08-09 15:01:26 +08:00
private $responseFactory ;
2023-07-15 10:16:32 +08:00
private int $requestsCount = 0 ;
private array $defaultOptions = [];
/**
* @ param callable | callable [] | ResponseInterface | ResponseInterface [] | iterable | null $responseFactory
*/
public function __construct ( callable | iterable | ResponseInterface $responseFactory = null , ? string $baseUri = 'https://example.com' )
{
$this -> setResponseFactory ( $responseFactory );
$this -> defaultOptions [ 'base_uri' ] = $baseUri ;
}
/**
* @ param callable | callable [] | ResponseInterface | ResponseInterface [] | iterable | null $responseFactory
*/
public function setResponseFactory ( $responseFactory ) : void
{
if ( $responseFactory instanceof ResponseInterface ) {
$responseFactory = [ $responseFactory ];
}
if ( ! $responseFactory instanceof \Iterator && null !== $responseFactory && ! \is_callable ( $responseFactory )) {
$responseFactory = ( static function () use ( $responseFactory ) {
yield from $responseFactory ;
})();
}
2023-08-09 15:01:26 +08:00
$this -> responseFactory = ! \is_callable ( $responseFactory ) || $responseFactory instanceof \Closure ? $responseFactory : \Closure :: fromCallable ( $responseFactory );
2023-07-15 10:16:32 +08:00
}
2023-08-09 15:01:26 +08:00
/**
* { @ inheritdoc }
*/
2023-07-15 10:16:32 +08:00
public function request ( string $method , string $url , array $options = []) : ResponseInterface
{
[ $url , $options ] = $this -> prepareRequest ( $method , $url , $options , $this -> defaultOptions , true );
$url = implode ( '' , $url );
if ( null === $this -> responseFactory ) {
$response = new MockResponse ();
} elseif ( \is_callable ( $this -> responseFactory )) {
$response = ( $this -> responseFactory )( $method , $url , $options );
} elseif ( ! $this -> responseFactory -> valid ()) {
throw new TransportException ( 'The response factory iterator passed to MockHttpClient is empty.' );
} else {
$responseFactory = $this -> responseFactory -> current ();
$response = \is_callable ( $responseFactory ) ? $responseFactory ( $method , $url , $options ) : $responseFactory ;
$this -> responseFactory -> next ();
}
++ $this -> requestsCount ;
if ( ! $response instanceof ResponseInterface ) {
2023-08-09 15:01:26 +08:00
throw new TransportException ( sprintf ( 'The response factory passed to MockHttpClient must return/yield an instance of ResponseInterface, "%s" given.' , \is_object ( $response ) ? \get_class ( $response ) : \gettype ( $response )));
2023-07-15 10:16:32 +08:00
}
return MockResponse :: fromRequest ( $method , $url , $options , $response );
}
2023-08-09 15:01:26 +08:00
/**
* { @ inheritdoc }
*/
2023-07-15 10:16:32 +08:00
public function stream ( ResponseInterface | iterable $responses , float $timeout = null ) : ResponseStreamInterface
{
if ( $responses instanceof ResponseInterface ) {
$responses = [ $responses ];
}
return new ResponseStream ( MockResponse :: stream ( $responses , $timeout ));
}
public function getRequestsCount () : int
{
return $this -> requestsCount ;
}
2023-08-09 15:01:26 +08:00
/**
* { @ inheritdoc }
*/
2023-07-15 10:16:32 +08:00
public function withOptions ( array $options ) : static
{
$clone = clone $this ;
$clone -> defaultOptions = self :: mergeDefaultOptions ( $options , $this -> defaultOptions , true );
return $clone ;
}
public function reset ()
{
$this -> requestsCount = 0 ;
}
}