Bug #88177
closedUpgrading symfony routing causes endless redirects
0%
Description
It appears that something changes in the symfony router that causes endless redirect loop with TYPO3 routing.
Using symfony/routing, v4.2.4:
$ curl -I http://test.localhost.ops.ch/de/ HTTP/1.1 200 OK Server: nginx/1.14.0 Date: Fri, 19 Apr 2019 10:00:00 GMT Content-Type: text/html; charset=utf-8 Content-Length: 113072 Connection: keep-alive Vary: Accept-Encoding Set-Cookie: fe_typo_user=20588581a60dd933465b18fe21b7fd02; path=/; HttpOnly Content-Language: de
Updating only symfony/routing to v4.2.7:
$ curl -I http://test.localhost.ops.ch/de/ HTTP/1.1 307 Temporary Redirect Server: nginx/1.14.0 Date: Fri, 19 Apr 2019 09:47:55 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive location: //test.localhost.ops.ch/de/
Redirect comes from TYPO3\CMS\Core\Http\RedirectResponse
(thanks to unique lowercase 'location'
). Btw, it would be nice here to have some identifier in http headers, similar to what realurl did to identify the exact place that causes redirects (see, for example, https://github.com/dmitryd/typo3-realurl/blob/development/Classes/Decoder/UrlDecoder.php#L214 for such header).
I could trace the redirect to SiteBasedRedirectResolver::process()
:
if ($site instanceof Site && !($language instanceof SiteLanguage)) { $language = $site->getDefaultLanguage(); return new RedirectResponse($language->getBase(), 307); }
$language
is null.
It seems that language is not detected due to this change in symfony router: https://github.com/symfony/routing/commit/0e5719d216017b1a0342fa48e86467cedca1c954
In UrlMatcher::matchCollection():
$pos = strrpos($regex, '$'); $hasTrailingSlash = '/' === $regex[$pos - 1]; $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); if (!preg_match($regex, $pathinfo, $matches)) { continue; } $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); if ($hasTrailingVar && ($hasTrailingSlash || '/' !== substr($matches[(\count($matches) - 1) >> 1], -1)) && preg_match($regex, $trimmedPathinfo, $m)) { if ($hasTrailingSlash) { $matches = $m; } else { $hasTrailingVar = false; } }
Even though there is a trailing slash, regexp looks like #^/de(?:/(?P<tail>.*))?$#sDu
. Later $hasTrailingVar
becomes false
and everything after the site name is ignored. Therefore TYPO3 tries to redirect to /de/
again.
My site configuration is quite ordinary:
rootPageId: 1 base: 'https://www.test.ch/' baseVariants: - base: test.localhost.ops.ch condition: 'getenv("SITE_ENV") == "DEV"' - base: test.test00.snowflakehosting.ch condition: 'getenv("SITE_ENV") == "STAGE"' languages: - title: Deutsch enabled: true languageId: '0' base: /de/ typo3Language: de locale: de_CH.UTF-8 iso-639-1: de navigationTitle: '' hreflang: '' direction: '' flag: de - title: English enabled: true languageId: '1' base: /en/ typo3Language: default locale: en_US.UTF-8 iso-639-1: en navigationTitle: '' hreflang: '' direction: '' fallbackType: strict fallbacks: '0' flag: gb - title: Français enabled: true languageId: '2' base: /fr/ typo3Language: fr locale: fr_CH.UTF-8 iso-639-1: fr navigationTitle: '' hreflang: '' direction: '' fallbackType: strict fallbacks: '0' flag: fr - title: Italiano enabled: true languageId: '3' base: /it/ typo3Language: it locale: it_CH.UTF-8 iso-639-1: it navigationTitle: '' hreflang: '' direction: '' fallbackType: strict fallbacks: '0' flag: it