EXT:redirects
Install EXT: (composer require typo3/) and
the standard redirect manager works as usual. EXT:headless then
automatically swaps the relevant frontend middlewares so a matched
redirect surfaces to a headless frontend as JSON rather than a 30x
response — no feature flag required.
The replaced middlewares are:
typo3/→cms- frontend/ base- redirect- resolver FriendsOf TYPO3Headless Middleware Site Base Redirect Resolver typo3/→cms- frontend/ shortcut- and- mountpoint- redirect FriendsOf TYPO3Headless Middleware Shortcut And Mount Point Redirect
Matched redirects from the redirect manager are turned into JSON by the
headless/ event listener (see below) — the core
redirecthandler middleware stays in place.
Note
The middleware swap only registers when EXT: is
installed. Without it, all redirects — including plain shortcut
and mount-point pages — are served as real HTTP 30x responses
even in headless mode. The same applies per request in MIXED mode:
without exactly Accept: application/ as the first Accept
header value, redirects degrade to real 30x responses.
Requests for the headless page-content type (?type=834) bypass
shortcut and mount-point redirect handling entirely and are resolved
downstream instead.
JSON response shape
A matched redirect produces:
{
"redirectUrl": "https://example.com/new-target",
"statusCode": 301
}
redirect is run through Url,
so internal targets come back as relative paths (/new-) when
they land on the same frontend host.
The HTTP response itself is always 200 — status tells the
frontend which redirect to perform, and the frontend must apply the
usual method semantics itself (301/302 may switch to GET,
307/308 preserve the request method). Its value depends on the
source:
- redirect-manager records: the record's configured target status code;
- shortcut/mount-point and site-base redirects: the HTTP code the core
middleware would have sent (typically
307).
Customising the redirect
The JSON envelope is built by
Friends,
which listens to the core TYPO3CMSRedirects
(identifier headless/). Register your own listener for
the same event after it and replace the response:
final readonly class TagRedirectsForAnalytics
{
public function __invoke(RedirectWasHitEvent $event): void
{
$response = $event->getResponse();
if (!$response instanceof JsonResponse) {
return;
}
$payload = json_decode((string)$response->getBody(), true);
$payload['redirectUrl'] .= '?utm_source=redirect';
$event->setResponse(new JsonResponse($payload));
}
}
# Configuration/Services.yaml
services:
Vendor\MyExt\EventListener\TagRedirectsForAnalytics:
tags:
- name: event.listener
identifier: 'myext/redirect/analytics'
after: 'headless/RedirectWasHit'
Page targets carrying Extbase plugin parameters in the typolink
additional segment are rebuilt through the site router by
Friends (the core
Redirect drops that segment unless "keep query parameters"
is enabled). Override or extend that service via Services.
when you need different target URL resolution.
Short URLs & QR codes (5.x)
The "Short URLs" and "QR Codes" backend modules of EXT: show
source URLs on the TYPO3 host — useless when the public site lives on the
frontend domain. With headless, both modules (and the QR-code/short-URL
fields in redirect records) resolve source URLs against the site's
frontend instead, so copied links and scanned codes land on the
public frontend. No configuration needed beyond frontend; resolution
logic can be replaced by overriding
Friends via Services..