EFL
API

HTTP

HTTP layer reference for EflHttpClient, HttpClientInterface, HttpResponse and adapters.

Overview

The SDK does not talk to the EFL Leasing Online API directly. Instead, it uses a small HTTP abstraction that separates:

  • Config – base URL and authentication settings.
  • HttpClientInterface – your HTTP library (Guzzle, Symfony HttpClient, custom).
  • EflHttpClient – high-level helper that knows how to build URLs, apply headers and map errors.
  • HttpResponse – simple value object used by the SDK.

This section describes these building blocks so you can plug in your own HTTP client implementation safely.

HttpClientInterface

HttpClientInterface is the only contract the SDK needs in order to perform HTTP requests:

use Imoli\EflLeasingSdk\Exception\HttpException;
use Imoli\EflLeasingSdk\Http\HttpClientInterface;
use Imoli\EflLeasingSdk\Http\HttpResponse;

interface HttpClientInterface
{
    /**
     * @param non-empty-string $method HTTP method, e.g. GET, POST.
     * @param non-empty-string $url Absolute URL including scheme and host.
     * @param array<string, string> $headers
     * @param string|null $body
     *
     * @throws HttpException When the request fails at transport level.
     */
    public function request(
        string $method,
        string $url,
        array $headers = [],
        ?string $body = null,
    ): HttpResponse;
}

The implementation is responsible for:

  • Executing the HTTP request with the given method, URL, headers and optional body.
  • Returning a HttpResponse object for all requests (even when the status code is 4xx/5xx).
  • Throwing HttpException when a transport-level error occurs (network failures, timeouts, low-level library errors).

HttpResponse

HttpResponse is a small immutable value object used by the SDK and exposed by low-level API clients:

use Imoli\EflLeasingSdk\Http\HttpResponse;

final class HttpResponse
{
    public function __construct(int $statusCode, array $headers, string $body);

    public function getStatusCode(): int;

    /** @return array<string, string> */
    public function getHeaders(): array;

    public function getBody(): string;
}
  • statusCode – numeric HTTP status code returned by the server.
  • headers – flattened associative array of response headers.
  • body – raw response body as a string.

High-level methods on EflClient usually deserialize the body for you. Low-level clients expose HttpResponse so you can inspect and parse the payload manually when needed.

EflHttpClient

EflHttpClient connects your Config and HttpClientInterface implementation with the EFL Leasing Online API semantics:

use Imoli\EflLeasingSdk\Config;
use Imoli\EflLeasingSdk\Http\EflHttpClient;
use Imoli\EflLeasingSdk\Http\HttpClientInterface;
use Imoli\EflLeasingSdk\Http\HttpResponse;
use Imoli\EflLeasingSdk\Http\RequestLoggerInterface;

final class EflHttpClient
{
    public function __construct(
        Config $config,
        HttpClientInterface $httpClient,
        ?RequestLoggerInterface $logger = null,
    );

    /** @return HttpResponse */
    public function requestWithApiKey(
        string $method,
        string $path,
        array $query = [],
        array $headers = [],
        ?string $body = null,
    ): HttpResponse;

    /** @return HttpResponse */
    public function requestWithBearerToken(
        string $method,
        string $path,
        string $token,
        array $query = [],
        array $headers = [],
        ?string $body = null,
    ): HttpResponse;

    /** @return HttpResponse */
    public function request(
        string $method,
        string $path,
        array $query = [],
        array $headers = [],
        ?string $body = null,
    ): HttpResponse;
}

Key responsibilities:

  • URL building – combines Config::getBaseUrl() with relative paths such as /lon/api/v1/... and serializes query parameters.
  • Authentication:
    • requestWithApiKey() adds the ApiKey header from Config.
    • requestWithBearerToken() adds the Authorization: Bearer ... header.
  • Logging (optional) – calls RequestLoggerInterface before and after the request.
  • Error mapping – for HTTP status codes >= 400 it throws ApiException with parsed ProblemDetails when available.

You normally do not instantiate EflHttpClient directly. It is created inside EflClient and in low-level API clients.

Built-in adapters

The SDK ships with ready-made adapters for popular HTTP libraries. They all implement HttpClientInterface, so you can swap them without changing the rest of your code.

GuzzleHttpAdapter

use GuzzleHttp\Client as GuzzleClient;
use Imoli\EflLeasingSdk\Http\Adapter\GuzzleHttpAdapter;
use Imoli\EflLeasingSdk\Http\HttpClientInterface;

$guzzle = new GuzzleClient([
    'timeout' => 30,
    'connect_timeout' => 10,
]);

/** @var HttpClientInterface $httpClient */
$httpClient = new GuzzleHttpAdapter($guzzle);
  • Requires the guzzlehttp/guzzle package.
  • Disables automatic exceptions on 4xx/5xx (http_errors is set to false) so that EflHttpClient can handle API errors consistently.

SymfonyHttpAdapter

use Imoli\EflLeasingSdk\Http\Adapter\SymfonyHttpAdapter;
use Symfony\Component\HttpClient\HttpClient;

$symfonyClient = HttpClient::create();
$httpClient = new SymfonyHttpAdapter($symfonyClient);
  • Requires the symfony/http-client package.
  • Adapts Symfony's response object to HttpResponse, flattening multi-value headers.

NativeHttpClient

use Imoli\EflLeasingSdk\Http\HttpClientInterface;
use Imoli\EflLeasingSdk\Http\NativeHttpClient;

/** @var HttpClientInterface $httpClient */
$httpClient = new NativeHttpClient();

NativeHttpClient is a minimal placeholder implementation. At the moment it throws HttpException for all calls and is intended only as a starting point. For real integrations you should:

  • Use the Guzzle or Symfony adapters, or
  • Provide your own robust implementation of HttpClientInterface.

Custom adapters

If you use a different HTTP client library, implement HttpClientInterface yourself. As a quick checklist:

  • Do not throw exceptions on HTTP 4xx/5xx – always return a HttpResponse.
  • Do throw HttpException for network/transport errors or misconfiguration.
  • Normalize response headers to a simple array<string, string>.
  • Preserve the raw response body exactly as returned by the server.

Once you have an implementation, pass it to EflClient together with Config:

use Imoli\EflLeasingSdk\Config;
use Imoli\EflLeasingSdk\EflClient;
use Imoli\EflLeasingSdk\Http\HttpClientInterface;

/** @var HttpClientInterface $httpClient */
$config = Config::sandbox('your-sandbox-api-key');

$client = new EflClient($config, $httpClient);