| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- <?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 Http\Discovery\Psr17Factory;
- use Http\Discovery\Psr17FactoryDiscovery;
- use Nyholm\Psr7\Factory\Psr17Factory as NyholmPsr17Factory;
- use Nyholm\Psr7\Request;
- use Nyholm\Psr7\Uri;
- use Psr\Http\Client\ClientInterface;
- use Psr\Http\Client\NetworkExceptionInterface;
- use Psr\Http\Client\RequestExceptionInterface;
- use Psr\Http\Message\RequestFactoryInterface;
- use Psr\Http\Message\RequestInterface;
- use Psr\Http\Message\ResponseFactoryInterface;
- use Psr\Http\Message\ResponseInterface;
- 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\StreamableInterface;
- use Symfony\Component\HttpClient\Response\StreamWrapper;
- use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
- use Symfony\Contracts\HttpClient\HttpClientInterface;
- use Symfony\Contracts\Service\ResetInterface;
- if (!interface_exists(ClientInterface::class)) {
- throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-client" package is not installed. Try running "composer require php-http/discovery psr/http-client-implementation:*".');
- }
- if (!interface_exists(RequestFactoryInterface::class)) {
- throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-factory" package is not installed. Try running "composer require php-http/discovery psr/http-factory-implementation:*".');
- }
- /**
- * An adapter to turn a Symfony HttpClientInterface into a PSR-18 ClientInterface.
- *
- * Run "composer require php-http/discovery psr/http-client-implementation:*"
- * to get the required dependencies.
- *
- * @author Nicolas Grekas <p@tchwork.com>
- */
- final class Psr18Client implements ClientInterface, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, ResetInterface
- {
- /**
- * @var \Symfony\Contracts\HttpClient\HttpClientInterface
- */
- private $client;
- /**
- * @var \Psr\Http\Message\ResponseFactoryInterface
- */
- private $responseFactory;
- /**
- * @var \Psr\Http\Message\StreamFactoryInterface
- */
- private $streamFactory;
- /**
- * @param \Symfony\Contracts\HttpClient\HttpClientInterface|null $client
- * @param \Psr\Http\Message\ResponseFactoryInterface|null $responseFactory
- * @param \Psr\Http\Message\StreamFactoryInterface|null $streamFactory
- */
- public function __construct($client = null, $responseFactory = null, $streamFactory = null)
- {
- $this->client = $client ?? HttpClient::create();
- $streamFactory = $streamFactory ?? ($responseFactory instanceof StreamFactoryInterface ? $responseFactory : null);
- if (null === $responseFactory || null === $streamFactory) {
- if (class_exists(Psr17Factory::class)) {
- $psr17Factory = new Psr17Factory();
- } elseif (class_exists(NyholmPsr17Factory::class)) {
- $psr17Factory = new NyholmPsr17Factory();
- } else {
- throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as no PSR-17 factories have been provided. Try running "composer require php-http/discovery psr/http-factory-implementation:*".');
- }
- $responseFactory = $responseFactory ?? $psr17Factory;
- $streamFactory = $streamFactory ?? $psr17Factory;
- }
- $this->responseFactory = $responseFactory;
- $this->streamFactory = $streamFactory;
- }
- /**
- * @return $this
- * @param mixed[] $options
- */
- public function withOptions($options)
- {
- $clone = clone $this;
- $clone->client = $clone->client->withOptions($options);
- return $clone;
- }
- /**
- * @param \Psr\Http\Message\RequestInterface $request
- */
- public function sendRequest($request)
- {
- try {
- $body = $request->getBody();
- if ($body->isSeekable()) {
- $body->seek(0);
- }
- $options = [
- 'headers' => $request->getHeaders(),
- 'body' => $body->getContents(),
- ];
- if ('1.0' === $request->getProtocolVersion()) {
- $options['http_version'] = '1.0';
- }
- $response = $this->client->request($request->getMethod(), (string) $request->getUri(), $options);
- $psrResponse = $this->responseFactory->createResponse($response->getStatusCode());
- foreach ($response->getHeaders(false) as $name => $values) {
- foreach ($values as $value) {
- try {
- $psrResponse = $psrResponse->withAddedHeader($name, $value);
- } catch (\InvalidArgumentException $e) {
- // ignore invalid header
- }
- }
- }
- $body = $response instanceof StreamableInterface ? $response->toStream(false) : StreamWrapper::createResource($response, $this->client);
- $body = $this->streamFactory->createStreamFromResource($body);
- if ($body->isSeekable()) {
- $body->seek(0);
- }
- return $psrResponse->withBody($body);
- } catch (TransportExceptionInterface $e) {
- if ($e instanceof \InvalidArgumentException) {
- throw new Psr18RequestException($e, $request);
- }
- throw new Psr18NetworkException($e, $request);
- }
- }
- /**
- * @param string $method
- */
- public function createRequest($method, $uri)
- {
- if ($this->responseFactory instanceof RequestFactoryInterface) {
- return $this->responseFactory->createRequest($method, $uri);
- }
- if (class_exists(Psr17FactoryDiscovery::class)) {
- return Psr17FactoryDiscovery::findRequestFactory()->createRequest($method, $uri);
- }
- if (class_exists(Request::class)) {
- return new Request($method, $uri);
- }
- throw new \LogicException(sprintf('You cannot use "%s()" as no PSR-17 factories have been found. Try running "composer require php-http/discovery psr/http-factory-implementation:*".', __METHOD__));
- }
- /**
- * @param string $content
- */
- public function createStream($content = '')
- {
- $stream = $this->streamFactory->createStream($content);
- if ($stream->isSeekable()) {
- $stream->seek(0);
- }
- return $stream;
- }
- /**
- * @param string $filename
- * @param string $mode
- */
- public function createStreamFromFile($filename, $mode = 'r')
- {
- return $this->streamFactory->createStreamFromFile($filename, $mode);
- }
- public function createStreamFromResource($resource)
- {
- return $this->streamFactory->createStreamFromResource($resource);
- }
- /**
- * @param string $uri
- */
- public function createUri($uri = '')
- {
- if ($this->responseFactory instanceof UriFactoryInterface) {
- return $this->responseFactory->createUri($uri);
- }
- if (class_exists(Psr17FactoryDiscovery::class)) {
- return Psr17FactoryDiscovery::findUrlFactory()->createUri($uri);
- }
- if (class_exists(Uri::class)) {
- return new Uri($uri);
- }
- throw new \LogicException(sprintf('You cannot use "%s()" as no PSR-17 factories have been found. Try running "composer require php-http/discovery psr/http-factory-implementation:*".', __METHOD__));
- }
- public function reset()
- {
- if ($this->client instanceof ResetInterface) {
- $this->client->reset();
- }
- }
- }
- /**
- * @internal
- */
- class Psr18NetworkException extends \RuntimeException implements NetworkExceptionInterface
- {
- /**
- * @var \Psr\Http\Message\RequestInterface
- */
- private $request;
- /**
- * @param \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface $e
- * @param \Psr\Http\Message\RequestInterface $request
- */
- public function __construct($e, $request)
- {
- parent::__construct($e->getMessage(), 0, $e);
- $this->request = $request;
- }
- public function getRequest()
- {
- return $this->request;
- }
- }
- /**
- * @internal
- */
- class Psr18RequestException extends \InvalidArgumentException implements RequestExceptionInterface
- {
- /**
- * @var \Psr\Http\Message\RequestInterface
- */
- private $request;
- /**
- * @param \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface $e
- * @param \Psr\Http\Message\RequestInterface $request
- */
- public function __construct($e, $request)
- {
- parent::__construct($e->getMessage(), 0, $e);
- $this->request = $request;
- }
- public function getRequest()
- {
- return $this->request;
- }
- }
|