HTTP Client Middleware
Since heptacom/heptaconnect-portal-base: 0.9.2
A portal, that connects to an HTTP API regularly needs to add headers, session handling or customized response handling, for every request/response. To provide features like this for multiple HTTP requests, you can use these middlewares.
Intention
Shared code will occur with more and more different API calls an HTTP Client is used for. Authenticated session handling is a common case, that can be solved by wrapping each sending of a request and ensure to use an authenticated session identifier. This is where the HTTP Client Middlewares come into play.
Intercepting outbound HTTP requests is already simplified, when using the shipped HTTP Client, or defining a decorator for the PSR-18
HTTP Client. With this HTTP Client Middleware it is simpler to build decorations around the HTTP Client as only a single file is needed with less potential to do it wrong. The underlying interface is similar to the PSR-15
middleware interface but for outbound HTTP requests.
Usage
Services of type \Heptacom\HeptaConnect\Portal\Base\Web\Http\Contract\HttpClientMiddlewareInterface
will automatically get the service tag heptaconnect.http.client.middleware
. All services with the tag heptaconnect.http.client.middleware
will be executed for each request, that is sent by the Psr\Http\Client\ClientInterface
service. Adding a single file to your code will be sufficient for reoccurring tasks of your HTTP client. See this pattern for dumping message or like the following example for profiling:
use Heptacom\HeptaConnect\Portal\Base\Profiling\ProfilerContract;
use Heptacom\HeptaConnect\Portal\Base\Web\Http\Contract\HttpClientMiddlewareInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
final class ProfilerMiddleware implements HttpClientMiddlewareInterface
{
private ProfilerContract $profiler;
private bool $profilingEnabled;
public function __construct(ProfilerContract $profiler, bool $configProfilingEnabled)
{
$this->profiler = $profiler;
$this->profilingEnabled = $configProfilingEnabled;
}
public function process(RequestInterface $request, ClientInterface $handler): ResponseInterface
{
if (!$this->profilingEnabled) {
return $handler->sendRequest($request);
}
$this->profiler->start(\sprintf('http client %s %s', $request->getMethod(), $request->getUri()));
try {
$response = $handler->sendRequest($request);
} catch (\Throwable $exception) {
$this->profiler->stop($exception);
throw $exception;
}
$this->profiler->stop();
return $response;
}
}