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\CMS\Core\Http\RequestFactory is present as a simplified wrapper for accessing Guzzle clients.

All options available under $GLOBALS['TYPO3_CONF_VARS']['HTTP'] are automatically applied to the Guzzle clients when using the RequestFactory 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 GeneralUtility::getUrl() and a PSR-7-based API for HTTP requests.

The TYPO3-specific wrapper GeneralUtility::getUrl() 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 RequestFactory class can be used like this:

EXT:examples/Classes/Http/MeowInformationRequester.php
<?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 readonly 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 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);
    }
}
Copied!

A POST request can be achieved with:

EXT:my_extension/Classes/SomeClass.php
$additionalOptions = [
    'body' => 'Your raw post data',
    // OR form data:
    'form_params' => [
        'first_name' => 'Jane',
        'last_name' => 'Doe',
    ]
];

$response = $this->requestFactory->request($url, 'POST', $additionalOptions);
Copied!

Extension authors are advised to use the RequestFactory 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['TYPO3_CONF_VARS']['HTTP']['handler'] as an array. If a custom configuration is specified, the default handler stack will be extended and not overwritten.

config/system/additional.php | typo3conf/system/additional.php
// 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();
Copied!

HTTP Utility Methods

TYPO3 provides a small set of helper methods related to HTTP Requests in the class HttpUtility:

HttpUtility::buildUrl

Creates a URL string from an array containing the URL parts, such as those output by parse_url().

HttpUtility::buildQueryString

The buildQueryString() method is an enhancement to the PHP functionhttp_build_query(). 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.