Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow PSR-18 Http Clients #703

Closed
Tracked by #727
KDederichs opened this issue Nov 9, 2023 · 6 comments
Closed
Tracked by #727

Allow PSR-18 Http Clients #703

KDederichs opened this issue Nov 9, 2023 · 6 comments

Comments

@KDederichs
Copy link

Specifications

  • API Version: 2.63.0

Describe the issue

Hi,

I was wondering if you guys could add PSR18 (https://github.com/php-fig/http-client) as supported option for Http Clients.

The reason I'm asking is I'd like to use something like https://docs.php-http.org/en/latest/clients/mock-client.html in integration tests to mock mollie responses.

Sadly it currently only seems to support Guzzle's ClientInterface and your own one.

@Naoray
Copy link
Collaborator

Naoray commented Nov 10, 2023

Hi @KDederichs,

thanks for your suggestion. I will discuss this internally.

Nevertheless, this would be a breaking change and therefore won’t be included in any release before v3, which is scheduled for early next year.

@sandervanhooft
Copy link
Collaborator

How about adding a Mollie\Api\HttpAdapter\PSR18MollieHttpAdapter here that implements the Mollie\Api\HttpAdapter\ MollieHttpAdapterInterface, which in turn accepts a PSR18 enabled client on the constructor? I think that way it's possible to introduce PSR18 support without a breaking change.

@KDederichs would you need PSR17 support as well (RequestFactoryInterface, StreamFactoryInterface)?

@sandervanhooft
Copy link
Collaborator

For example (not tested):

<?php

namespace Mollie\Api\HttpAdapter;

use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\RequestInterface;
use Mollie\Api\Exceptions\ApiException;

class PSR18MollieHttpAdapter implements MollieHttpAdapterInterface
{
    /**
     * @var ClientInterface
     */
    private $httpClient;

    /**
     * @var RequestFactoryInterface
     */
    private $requestFactory;

    /**
     * @var StreamFactoryInterface
     */
    private $streamFactory;

    /**
     * PSR18MollieHttpAdapter constructor.
     *
     * @param ClientInterface $httpClient
     * @param RequestFactoryInterface $requestFactory
     * @param StreamFactoryInterface $streamFactory
     */
    public function __construct(ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory)
    {
        $this->httpClient = $httpClient;
        $this->requestFactory = $requestFactory;
        $this->streamFactory = $streamFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function send($httpMethod, $url, $headers, $httpBody)
    {
        try {
            $request = $this->createRequest($httpMethod, $url, $headers, $httpBody);
            $response = $this->httpClient->sendRequest($request);

            $body = (string) $response->getBody();
            return json_decode($body);
        } catch (\Exception $e) {
            throw new ApiException("Error while sending request to Mollie API: " . $e->getMessage(), 0, $e);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function versionString()
    {
        return 'PSR18MollieHttpAdapter';
    }

    /**
     * Create a PSR-7 request.
     *
     * @param string $httpMethod
     * @param string $url
     * @param string|array $headers
     * @param string $httpBody
     * @return RequestInterface
     */
    private function createRequest($httpMethod, $url, $headers, $httpBody)
    {
        $request = $this->requestFactory->createRequest($httpMethod, $url);
        
        if (is_array($headers)) {
            foreach ($headers as $name => $value) {
                $request = $request->withHeader($name, $value);
            }
        } else {
            // Assuming headers is a string in the form of 'Header-Name: Header-Value'
            $headerLines = explode("\r\n", $headers);
            foreach ($headerLines as $line) {
                list($name, $value) = explode(': ', $line, 2);
                $request = $request->withHeader($name, $value);
            }
        }
        
        $stream = $this->streamFactory->createStream($httpBody);
        $request = $request->withBody($stream);
        
        return $request;
    }
}

@KDederichs
Copy link
Author

That looks like it would work yeah.

@sandervanhooft
Copy link
Collaborator

@Naoray what do you think?

@Naoray Naoray mentioned this issue Jun 27, 2024
15 tasks
@sandervanhooft
Copy link
Collaborator

@KDederichs we really appreciate the idea here. We're preparing to ship a new major release of this package (v3), which will have an optional PSR-18 HTTP client included out of the box. For now, feel free to leverage (an adaptation of) this.

Closing this for now, let me know if it should be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants