web: www-Hosts lösen aufs Apex-Domain-Theme auf statt aufs Portal-Fallback

Die Domain-Auflösung matchte den Host exakt gegen domain_name —
www.presseecho.de fiel dadurch aufs Portal-Default-Theme zurück, dessen
theme-portal.css im Web-Build nicht existiert. Alle Route::view-Seiten
ohne Controller (Impressum, Datenschutz, AGB, FAQ, …) antworteten auf
www-Hosts mit 500 (ViteException, Dauereintrag im Live-Log); die
Controller-Seiten traf es nicht, weil WebPortalContext den Host tolerant
matcht. resolve() normalisiert Hosts jetzt (lowercase, www. entfernt) auf
beiden Seiten des Vergleichs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-20 15:13:33 +00:00
parent 3d10cbf709
commit acf67211bf
2 changed files with 42 additions and 2 deletions

View file

@ -55,7 +55,13 @@ class DomainAssetContext
return array_merge($defaults, $configuredDomains[$themeOverride]);
}
$portalHost = (string) config('domains.domain_portal');
// www-Varianten zählen als ihre Apex-Domain: Ohne Normalisierung
// fiele z. B. www.presseecho.de auf das Portal-Default-Theme zurück,
// dessen theme-portal.css im Web-Build nicht existiert → 500
// (ViteException) auf allen Route::view-Seiten (Impressum, AGB, …).
$host = self::normalizedHost($host);
$portalHost = self::normalizedHost((string) config('domains.domain_portal'));
if ($host === $portalHost) {
$request ??= request();
@ -72,7 +78,9 @@ class DomainAssetContext
continue;
}
if (($config['domain_name'] ?? null) === $host) {
$domainName = $config['domain_name'] ?? null;
if (is_string($domainName) && self::normalizedHost($domainName) === $host) {
return array_merge($defaults, $config);
}
}
@ -80,6 +88,16 @@ class DomainAssetContext
return $defaults;
}
/**
* Kleingeschriebener Host ohne führendes "www.".
*/
private static function normalizedHost(string $host): string
{
$host = strtolower(trim($host));
return str_starts_with($host, 'www.') ? substr($host, 4) : $host;
}
public static function isBackendRequest(Request $request): bool
{
if ($request->routeIs(

View file

@ -50,6 +50,28 @@ test('presseecho resolves to its own web theme', function () {
->and($config['assets_dir'])->toBe('build/web');
});
test('www hosts resolve like their apex domain instead of the portal fallback', function () {
$defaults = ['theme' => 'portal', 'assets_dir' => 'build/portal'];
$domains = config('domains.domains');
// Ohne www-Normalisierung fiele der Host aufs Portal-Default zurück,
// dessen theme-portal.css im Web-Build fehlt → 500 auf Route::view-Seiten.
$config = DomainAssetContext::resolve('www.presseecho.test', $defaults, $domains);
expect($config['theme'])->toBe('presseecho')
->and($config['assets_dir'])->toBe('build/web');
$hub = DomainAssetContext::resolve(
'WWW.pressekonto.test',
$defaults,
$domains,
null,
Request::create('https://www.pressekonto.test/', 'GET'),
);
expect($hub['theme'])->toBe('pressekonto');
});
test('hot file path depends on asset bundle', function () {
expect(DomainAssetContext::hotFilePath('build/web'))
->toEndWith('hot-web')