Files
tsv08kulmbach-website/public/.htaccess
fs 06a18a2d19 301-Weiterleitungen der alten CMS-Adressen
Der Aufnahmeantrag der Turnabteilung ging als alte URL in den Einladungen an
die neuen Familien raus und lief seit dem Umzug in einen 404, ebenso der Link
auf die Turn-Seite. Beide leiten jetzt weiter, dazu alle uebrigen Seiten der
alten Navigation unter /08/de/.

Die PDF-Regel matcht am Umlaut vorbei: der Dateiname kommt je nach Mailprogramm
als NFC, als NFD (so stand er in der alten Datenbank) oder roh als UTF-8 an.
Die Sammelregel wirft den alten Query-String weg, sonst haengt mod_rewrite
?group_filter_id=14 ans neue Ziel.

Erledigt damit den offenen Punkt F3 aus docs/deploy.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWoqDYuANFbJDGFQAgaRdT
2026-07-31 22:11:08 +02:00

93 lines
4.7 KiB
ApacheConf

RewriteEngine On
# --- Kanonische Adresse: HTTPS erzwingen, nackte Domain auf www ---
# Die Formulare übertragen Name, Adresse und Geburtsdatum — nie über http.
# Der HTTPS-Redirect ist bewusst host-neutral (funktioniert auch auf einer
# Test-/Preview-Domain); nur tsv08kulmbach.de wird hart auf www gezogen.
# Drei unabhängige TLS-Indikatoren, damit kein Redirect-Loop entsteht, falls der
# Hoster die Verschlüsselung anders durchreicht als erwartet.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{SERVER_PORT} !=443
RewriteCond %{HTTP_HOST} !^(localhost|127\.0\.0\.1)(:[0-9]+)?$ [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^tsv08kulmbach\.de$ [NC]
RewriteRule ^ https://www.tsv08kulmbach.de%{REQUEST_URI} [R=301,L]
# --- Umbenannte Seiten (301) ---
# Step Aerobic findet nicht mehr statt (31.07.2026), die Seite heißt jetzt
# „Fitness & Pilates" und liegt unter turnen/fitness-pilates. Der alte Slug war
# in der Sitemap und ist von Google indexiert, deshalb 301 statt 404 — sonst
# verliert die Seite ihre Position und alte Links laufen ins Leere.
# Steht VOR dem Front Controller, sonst würde index.php den Pfad zuerst als
# unbekannten Slug abfangen und einen 404 rendern.
RewriteRule ^turnen/step-aerobic-fitness-pilates/?$ /turnen/fitness-pilates [R=301,L]
# --- Alte CMS-Adressen (301) ---
# Die alte Seite lief unter /08/de/<seite>/ und lieferte Dateien aus /userdata/.
# Beides ist seit dem Umzug tot, die Adressen stehen aber in Einladungen, Aushängen
# und im Google-Index. Steht wie die Regel darüber VOR dem Front Controller.
#
# Der Aufnahmeantrag der Turnabteilung ist der dringendste Fall: er ging so an die
# neuen Familien raus. Der Dateiname trägt ein „ä" und kommt je nach Mailprogramm in
# drei Fassungen an: NFC (%C3%A4), NFD (a%CC%88 — genau so stand der Link in der alten
# Datenbank) oder roh als UTF-8. mod_rewrite prüft den dekodierten Pfad, also matchen
# wir am Umlaut vorbei, statt eine der drei Fassungen zu raten.
RewriteRule ^userdata/01_Basis/Beitrittserkl[^/]*\.pdf$ /assets/downloads/beitrittserklaerung-turnen.pdf [R=301,L,NC]
# Seiten, die ihren Namen behalten haben. Das abschließende „?" wirft den alten
# Query-String weg (die Turn-Seite hatte ?group_filter_id=<n> als Disziplin-Filter,
# 14 war „Allgemeines") — ohne das hängt mod_rewrite ihn ungefragt ans neue Ziel.
RewriteRule ^08/de/(fussball|jugendfussball|matchcenter|turnen|mitglied-werden|kontakt|historie|impressum|datenschutz)/?$ /$1? [R=301,L]
# Seiten, die heute anders heißen
RewriteRule ^08/de/home/?$ / [R=301,L]
RewriteRule ^08/de/aktuelles/?$ /news [R=301,L]
RewriteRule ^08/de/der-verein/?$ /verein [R=301,L]
RewriteRule ^08/de/der-verein/historie/?$ /historie [R=301,L]
RewriteRule ^08/de/der-verein/sportheim/?$ /sportheimbuchung [R=301,L]
RewriteRule ^08/de/personen/?$ /ansprechpartner [R=301,L]
# --- Front Controller ---
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
# --- Security-Header ---
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
# HSTS nur über HTTPS ausliefern (1 Jahr, ohne includeSubDomains — Subdomains
# wie Webmail liegen nicht in unserer Hand).
Header always set Strict-Transport-Security "max-age=31536000" env=HTTPS
# Streng möglich, weil ausnahmslos alles self-hosted ist (CLAUDE.md Regel 1).
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'"
</IfModule>
# --- Kompression ---
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/json image/svg+xml
</IfModule>
# --- Caching: Assets 1 Jahr (Busting via ?v=filemtime), HTML nie ---
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
AddType font/woff2 .woff2
AddDefaultCharset utf-8
Options -Indexes