HTTP requests to external sources¶
The PHP library "Guzzle" is available in TYPO3 as a feature-rich solution for creating HTTP requests based on the PSR-7 interfaces.
Guzzle automatically detects the underlying adapters available on the system, such as cURL or stream wrappers, and chooses the best solution for the system.
A TYPO3-specific PHP class named \TYPO3\
is
present as a simplified wrapper for accessing Guzzle clients.
All options available under $GLOBALS
are
automatically applied to the Guzzle clients when using the Request
class. The options are a subset of the available options from Guzzle, but can be
extended.
Although Guzzle can handle Promises/A+ and asynchronous requests, it currently
serves as a drop-in replacement for the previous mixed options and
implementations within General
and a PSR-7-based API for
HTTP requests.
The TYPO3-specific wrapper General
uses Guzzle for
remote files, eliminating the need to directly configure settings based on
specific implementations such as stream wrappers or cURL.
Basic usage¶
The Request
class can be used like this:
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project. [...]
*/
namespace T3docs\Examples\Http;
use TYPO3\CMS\Core\Http\RequestFactory;
final class MeowInformationRequester
{
private const API_URL = 'https://catfact.ninja/fact';
// We need the RequestFactory for creating and sending a request,
// so we inject it into the class using constructor injection.
public function __construct(
private readonly RequestFactory $requestFactory,
) {}
/**
* @throws \JsonException
* @throws \RuntimeException
*/
public function request(): string
{
// Additional headers for this specific request
// See: https://docs.guzzlephp.org/en/stable/request-options.html
$additionalOptions = [
'headers' => ['Cache-Control' => 'no-cache'],
'allow_redirects' => false,
];
// Get a PSR-7-compliant response object
$response = $this->requestFactory->request(
self::API_URL,
'GET',
$additionalOptions
);
if ($response->getStatusCode() !== 200) {
throw new \RuntimeException(
'Returned status code is ' . $response->getStatusCode()
);
}
if ($response->getHeaderLine('Content-Type') !== 'application/json') {
throw new \RuntimeException(
'The request did not return JSON data'
);
}
// Get the content as a string on a successful request
$content = $response->getBody()->getContents();
return (string)json_decode($content, true, flags: JSON_THROW_ON_ERROR)['fact'] ??
throw new \RuntimeException('The service returned an unexpected format.', 1666413230);
}
}
A POST request can be achieved with:
$additionalOptions = [
'body' => 'Your raw post data',
// OR form data:
'form_params' => [
'first_name' => 'Jane',
'last_name' => 'Doe',
]
];
$response = $this->requestFactory->request($url, 'POST', $additionalOptions);
Extension authors are advised to use the Request
class instead of
using the Guzzle API directly in order to ensure a clear upgrade path when
updates to the underlying API need to be done.
Custom middleware handlers¶
Guzzle accepts a stack of custom middleware handlers which can be configured
in $GLOBALS
as an array. If a
custom configuration is specified, the default handler stack will be extended
and not overwritten.
// Add custom middlewares to default Guzzle handler stack
$GLOBALS['TYPO3_CONF_VARS']['HTTP']['handler'][] =
(\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
\MyVendor\MyExtension\Middleware\Guzzle\CustomMiddleware::class
))->handler();
$GLOBALS['TYPO3_CONF_VARS']['HTTP']['handler'][] =
(\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
\MyVendor\MyExtension\Middleware\Guzzle\SecondCustomMiddleware::class
))->handler();
HTTP Utility Methods¶
TYPO3 provides a small set of helper methods related to HTTP Requests in the class Http
:
HttpUtility::buildUrl¶
Creates a URL string from an array containing the URL parts, such as those
output by parse_
.
HttpUtility::buildQueryString¶
The build
method is an enhancement to the PHP function
http_
. It implodes multidimensional parameter arrays and
properly encodes parameter names as well as values into a valid query string
with an optional prepend of ?
or &
.
If the query is not empty, ?
or &
are prepended in the correct sequence.
Empty parameters are skipped.