Commit ade1708c authored by Stefan Bürk's avatar Stefan Bürk Committed by Christian Kuhn
Browse files

[BUGFIX] Avoid evaluating all regexp redirects if early match found

ext:redirects middleware collected all possible redirects,
thus evaluating all regexp redirects to find possible matches.
These collected possible redirects are looped afterwards and
checked, if redirect is active, meaning not having any start
and/or end time constraints or if time constrain is in the active
timespan, returning the first feasible redirect. However this
evaluated all regexp redirects, even if flat redirects with query
arguments, flat redirects without query arguments or a regexp
redirect is found.

This patch changes this behaviour and checks early for found subset
of possible redirects to avoid evaluating at least all regexp
redirects even if an early one would be used anyway.

This is a minor performance improvement in case an early redirect
can be matched, without any effect if no match could be found.

Further performance improvements may be possible but should be done
in dedicated follow up patches.

Resolves: #96480
Releases: main, 11.5
Change-Id: I84170a701d578a74a1780fd87a33d4f3a9af43e8
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72904

Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Reviewed-by: Nikita Hovratov's avatarNikita Hovratov <nikita.h@live.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Nikita Hovratov's avatarNikita Hovratov <nikita.h@live.de>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent d9508ced
......@@ -86,23 +86,30 @@ class RedirectService implements LoggerAwareInterface
continue;
}
$possibleRedirects = [];
// check if a flat redirect matches
if (!empty($allRedirects[$domainName]['flat'][rtrim($path, '/') . '/'])) {
$possibleRedirects = $allRedirects[$domainName]['flat'][rtrim($path, '/') . '/'];
}
// check if a flat redirect matches with the Query applied
if (!empty($query)) {
$pathWithQuery = rtrim($path, '/') . '?' . ltrim($query, '?');
if (!empty($allRedirects[$domainName]['respect_query_parameters'][$pathWithQuery])) {
$possibleRedirects = $allRedirects[$domainName]['respect_query_parameters'][$pathWithQuery];
if ($matchedRedirect = $this->getFirstActiveRedirectFromPossibleRedirects($allRedirects[$domainName]['respect_query_parameters'][$pathWithQuery])) {
return $matchedRedirect;
}
} else {
$pathWithQueryAndSlash = rtrim($path, '/') . '/?' . ltrim($query, '?');
if (!empty($allRedirects[$domainName]['respect_query_parameters'][$pathWithQueryAndSlash])) {
$possibleRedirects = $allRedirects[$domainName]['respect_query_parameters'][$pathWithQueryAndSlash];
if ($matchedRedirect = $this->getFirstActiveRedirectFromPossibleRedirects($allRedirects[$domainName]['respect_query_parameters'][$pathWithQueryAndSlash])) {
return $matchedRedirect;
}
}
}
}
// check if a flat redirect matches
if (!empty($allRedirects[$domainName]['flat'][rtrim($path, '/') . '/'])) {
if ($matchedRedirect = $this->getFirstActiveRedirectFromPossibleRedirects($allRedirects[$domainName]['flat'][rtrim($path, '/') . '/'])) {
return $matchedRedirect;
}
}
// check all redirects that are registered as regex
if (!empty($allRedirects[$domainName]['regexp'])) {
$allRegexps = array_keys($allRedirects[$domainName]['regexp']);
......@@ -113,7 +120,9 @@ class RedirectService implements LoggerAwareInterface
foreach ($allRegexps as $regexp) {
$matchResult = @preg_match((string)$regexp, $regExpPath);
if ($matchResult > 0) {
$possibleRedirects += $allRedirects[$domainName]['regexp'][$regexp];
if ($matchedRedirect = $this->getFirstActiveRedirectFromPossibleRedirects($allRedirects[$domainName]['regexp'][$regexp])) {
return $matchedRedirect;
}
continue;
}
......@@ -130,19 +139,14 @@ class RedirectService implements LoggerAwareInterface
if (!empty($query)) {
$matchResult = preg_match((string)$regexp, $path);
if ($matchResult > 0) {
$possibleRedirects += $allRedirects[$domainName]['regexp'][$regexp];
if ($matchedRedirect = $this->getFirstActiveRedirectFromPossibleRedirects($allRedirects[$domainName]['regexp'][$regexp])) {
return $matchedRedirect;
}
continue;
}
}
}
}
foreach ($possibleRedirects as $possibleRedirect) {
// check starttime and endtime for all existing records
if ($this->isRedirectActive($possibleRedirect)) {
return $possibleRedirect;
}
}
}
return null;
......@@ -405,4 +409,18 @@ class RedirectService implements LoggerAwareInterface
}
return $linkDetails;
}
/**
* Checks all possible redirects and return the first possible and active redirect if available.
*/
protected function getFirstActiveRedirectFromPossibleRedirects(array $possibleRedirects): ?array
{
foreach ($possibleRedirects as $possibleRedirect) {
if ($this->isRedirectActive($possibleRedirect)) {
return $possibleRedirect;
}
}
return null;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment