Skip to content

Commit

Permalink
Replace HTTPlug factories by PSR-17 (#1184)
Browse files Browse the repository at this point in the history
* Replace HTTPlug factories by PSR-17

* minor fix

---------

Co-authored-by: Nyholm <[email protected]>
  • Loading branch information
nicolas-grekas and Nyholm authored Dec 15, 2023
1 parent 15629fd commit bdb892a
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 13 deletions.
134 changes: 128 additions & 6 deletions Provider/AbstractHttpProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@
use Geocoder\Exception\InvalidServerResponse;
use Geocoder\Exception\QuotaExceeded;
use Geocoder\Provider\AbstractProvider;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Discovery\Psr17Factory;
use Http\Message\MessageFactory;
use Psr\Http\Client\ClientInterface;
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\UriInterface;

/**
* @author William Durand <[email protected]>
Expand All @@ -33,14 +39,17 @@ abstract class AbstractHttpProvider extends AbstractProvider
private $client;

/**
* @var MessageFactory
* @var RequestFactoryInterface&StreamFactoryInterface)|MessageFactory
*/
private $messageFactory;

public function __construct(ClientInterface $client, MessageFactory $factory = null)
/**
* @param Psr17Factory|MessageFactory|null $factory Passing a MessageFactory is @deprecated
*/
public function __construct(ClientInterface $client, MessageFactory|Psr17Factory $factory = null)
{
$this->client = $client;
$this->messageFactory = $factory ?: MessageFactoryDiscovery::find();
$this->messageFactory = $factory ?? ($client instanceof RequestFactoryInterface && $client instanceof StreamFactoryInterface ? $client : new Psr17Factory());
}

/**
Expand All @@ -57,7 +66,35 @@ protected function getUrlContents(string $url): string

protected function getRequest(string $url): RequestInterface
{
return $this->getMessageFactory()->createRequest('GET', $url);
return $this->createRequest('GET', $url);
}

/**
* @param array<string,string|string[]> $headers
*/
protected function createRequest(string $method, string $uri, array $headers = [], string $body = null): RequestInterface
{
if ($this->messageFactory instanceof MessageFactory) {
return $this->messageFactory->createRequest($method, $uri, $headers, $body);
}

$request = $this->messageFactory->createRequest($method, $uri);

foreach ($headers as $name => $value) {
$request = $request->withAddedHeader($name, $value);
}

if (null === $body) {
return $request;
}

$stream = $this->messageFactory->createStream($body);

if ($stream->isSeekable()) {
$stream->seek(0);
}

return $request->withBody($stream);
}

/**
Expand Down Expand Up @@ -94,8 +131,93 @@ protected function getHttpClient(): ClientInterface
return $this->client;
}

/**
* @deprecated Use createRequest instead
*/
protected function getMessageFactory(): MessageFactory
{
return $this->messageFactory;
if ($this->messageFactory instanceof MessageFactory) {
return $this->messageFactory;
}

$factory = $this->messageFactory instanceof ResponseFactoryInterface ? $this->messageFactory : new Psr17Factory();

return new class($factory) implements MessageFactory {
public function __construct(
/**
* @param RequestFactoryInterface&ResponseFactoryInterface&StreamFactoryInterface $factory
*/
private RequestFactoryInterface|ResponseFactoryInterface|StreamFactoryInterface $factory,
) {
}

/**
* @param string $method
* @param string|UriInterface $uri
* @param array<string,string|string[]> $headers
* @param resource|string|StreamInterface|null $body
* @param string $protocolVersion
*/
public function createRequest($method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1'): RequestInterface
{
$request = $this->factory->createRequest($method, $uri);

foreach ($headers as $name => $value) {
$request = $request->withAddedHeader($name, $value);
}

if (null !== $body) {
$request = $request->withBody($this->createStream($body));
}

return $request->withProtocolVersion($protocolVersion);
}

/**
* @param int $statusCode
* @param string|null $reasonPhrase
* @param array<string,string|string[]> $headers
* @param resource|string|StreamInterface|null $body
* @param string $protocolVersion
*/
public function createResponse($statusCode = 200, $reasonPhrase = null, array $headers = [], $body = null, $protocolVersion = '1.1'): ResponseInterface
{
$response = $this->factory->createResponse($statusCode, $reasonPhrase);

foreach ($headers as $name => $value) {
$response = $response->withAddedHeader($name, $value);
}

if (null !== $body) {
$response = $response->withBody($this->createStream($body));
}

return $response->withProtocolVersion($protocolVersion);
}

/**
* @param string|resource|StreamInterface|null $body
*/
private function createStream($body = ''): StreamInterface
{
if ($body instanceof StreamInterface) {
return $body;
}

if (\is_string($body ?? '')) {
$stream = $this->factory->createStream($body ?? '');
} elseif (\is_resource($body)) {
$stream = $this->factory->createStreamFromResource($body);
} else {
throw new \InvalidArgumentException(sprintf('"%s()" expects string, resource or StreamInterface, "%s" given.', __METHOD__, get_debug_type($body)));
}

if ($stream->isSeekable()) {
$stream->seek(0);
}

return $stream;
}
};
}
}
16 changes: 9 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@
],
"require": {
"php": "^8.0",
"php-http/client-implementation": "^1.0",
"php-http/discovery": "^1.6",
"php-http/httplug": "^1.0 || ^2.0",
"php-http/message-factory": "^1.0.2",
"psr/http-message": "^1.0 || ^2.0",
"psr/http-message-implementation": "^1.0",
"php-http/discovery": "^1.17",
"psr/http-client-implementation": "^1.0",
"psr/http-factory-implementation": "^1.0",
"willdurand/geocoder": "^4.0"
},
"require-dev": {
Expand Down Expand Up @@ -48,5 +45,10 @@
"scripts": {
"test": "vendor/bin/phpunit",
"test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml"
},
"config": {
"allow-plugins": {
"php-http/discovery": false
}
}
}
}

0 comments on commit bdb892a

Please sign in to comment.