FrankenPHP 1.13.0 erschien am 4. Oktober um 14:01. Nach v1.12.7 enthält die Version Caddy 2.11.7 und Mercure 1.0. Sie unterstützt PHP 8.6 und aktualisiert auf Go 1.27.

Fünf Sicherheitsprobleme sind behoben. Unter Windows kann die Auflösung von `SCRIPT_FILENAME` nicht mehr aus dem Dokumentenstamm ausbrechen. Das betrifft GHSA-868c-7h7m-mmj9. Caddy 2.11.7 verwirft Headernamen mit Punkten standardmäßig. Damit entfällt ein Spoofing-Weg, bei dem PHP `Foo.Bar` wie `Foo-Bar` auf `HTTP_FOO_BAR` abbildet. Die Korrektur trägt GHSA-qcrp-8483-f2f2. Die CGI-Pfadaufteilung verlangt nun eine Grenze zwischen Pfadsegmenten. `/uploads/a.php.txt/b.php` kann dadurch nicht mehr `uploads/a.php` ausführen. Das betrifft GHSA-xxjp-cjxr-2x6m. `putenv()` verändert die OS-Umgebung des Prozesses nicht mehr, sodass Werte nicht zwischen Requests und Threads durchsickern. Das betrifft GHSA-996f-w38m-f574. Ein präpariertes Array für `frankenphp_log()` kann den gesamten Serverprozess nicht mehr zum Absturz bringen. Dafür gilt GHSA-4prg-hv4r-g6mv.

Caddy 2.11.7 enthält die Änderungen aus Caddy 2.11.6 und 2.11.7. Der Slowloris-Schutz setzt inaktive Lese- und Schreib-Timeouts nach erfolgreicher Ein- oder Ausgabe zurück. Die Direktive `timeouts` erlaubt eine Anpassung pro Route. Der Matcher `url_pattern` folgt dem URLPattern-Webstandard. Er unterstützt benannte Gruppen, Wildcards und reguläre Ausdrücke und stellt erfasste Gruppen als Platzhalter bereit.

Der Header `Incremental: ?1` aus RFC 10036 weist `reverse_proxy` und `encode` an, Antworten sofort zu streamen. Server-Sent Events hinter `encode` werden nicht mehr gepuffert, was Mercure zugutekommt. Ein ordnungsgemäßes Herunterfahren wartet auf Server aus früheren Konfigurationen. Lang laufende Antworten überstehen dadurch einen Reload.

Die globale Option `tls_automate_names` kann Zertifikate für Namen verwalten, die keinen eigenen Site-Block haben. Die Zertifikatssuche beim TLS-Handshake ist ungefähr doppelt so schnell und benötigt nun 10 Allokationen, zuvor 15. Der Reverse Proxy überträgt Teilantworten korrekt und gibt TCP-Half-Close bei aktualisierten Streams weiter. Aktive Health Checks werden für jede Prüfkonfiguration getrennt. Mit `expected_underscore_headers` und `expected_dot_headers` lassen sich ausgewählte Header behalten, die Caddy sonst verwerfen würde.

Mercure 1.0 ändert `mercure_publish()`. Die Funktion wirft einen `ValueError`, wenn ein Update ein Topic im reservierten Namespace `/.well-known/mercure`, eine mit `#` beginnende ID, Steuerzeichen, ungültiges UTF-8, einen negativen Retry-Wert oder kein Topic enthält. Scheitert die Zustellung, entsteht eine `RuntimeException` mit der Nachricht des Hubs. Der neue Block `issuer` bindet Publisher- und Subscriber-Schlüssel an einen vertrauenswürdigen Aussteller. Die Beispiel-Caddyfile und `php-server --mercure` verwenden diese Konfiguration.

Beim Upgrade gibt es mehrere Änderungen. `num_threads` zählt nun die Threads für Requests, die kein Worker bedient. Worker-Threads kommen zusätzlich hinzu. Konfigurationen mit Workern können deshalb mehr Threads starten als zuvor. Der Start schlägt fehl, wenn `max_threads` kleiner als `num_threads` plus die Worker-Threads ist. Die Fehlermeldung nennt alle drei Werte. Die Standardwerte bleiben unverändert.

`publisher_jwt` oder `subscriber_jwt` ohne `protocol_version_compatibility` ist nun ein Konfigurationsfehler. Mercure-Konfigurationen sollten den neuen Block `issuer` verwenden. Beim Hot Reload kündigt `$_SERVER['FRANKENPHP_HOT_RELOAD']` nun `/.well-known/mercure?match=<topic>` an. Fest eingetragene URLs mit `?topic=` müssen deshalb angepasst werden.

Caddy begrenzt Request-Header standardmäßig auf 16 KiB. Größere Werte können über `max_header_size` erlaubt werden. Blockierte Lese- und Schreibvorgänge werden nach einer Minute abgebrochen. Header mit Punkten werden wie Header mit Unterstrichen verworfen. `client_auth` eines Wildcard-Sites gilt nicht mehr für spezifischere Sites. Weitere ungültige Konfigurationen werden abgelehnt. Ein PHP-Build ohne `--disable-zend-signals` (ZTS) lässt FrankenPHP nun mit einer klaren Fehlermeldung stoppen. Zuvor konnte der Prozess hängen und weiter Speicher verbrauchen.

Die Version stellt eine Thread-API für PHP-Erweiterungen in Go bereit. Dazu gehören `Thread(index)`, `PHPThread.Pin()`, `PHPThread.IsRequestDone()` und die C-Funktion `frankenphp_thread_index()`. Konfigurationen werden vor dem Austausch der aktiven Konfiguration validiert. Fehlende Worker-Dateien, doppelte Workernamen und widersprüchliche Thread-Budgets werden abgelehnt, während die aktuelle Konfiguration weiter bedient. Bibliotheksnutzer können `frankenphp.Validate()` aufrufen.

Die Startprotokolle melden nun `total_threads` und `worker_threads`. Neustarts des Opcache-Shared-Memory werden protokolliert und über die experimentelle Metrik `frankenphp_opcache_restarts{reason}` für PHP 8.4 und neuer gezählt. Solche Neustarts sind unter ZTS unsicher, deshalb sollte der Zähler bei null bleiben. `php_server`-Blöcke werden auf der FrankenPHP-Seite gespiegelt. `phpinfo()` erhält einen FrankenPHP-Abschnitt mit der Caddy-Version. Go-Code kann über `frankenphp.AddPHPInfoEntry()` weitere Zeilen hinzufügen.

Ab PHP 8.5 verwendet `php-cli` die eingebaute CLI-SAPI von PHP. Die Version enthält außerdem die oben genannte Kompatibilität mit PHP 8.6.

Requests, die vor der Bereitschaft der regulären Threads eintreffen, hängen nicht mehr. Dadurch entfallen zufällige 499- und 504-Antworten nach dem Start eines Containers. Abstürze von Workern erscheinen mit Exit-Status auf Warnstufe. Saubere Neustarts bleiben auf Debug-Stufe. `Shutdown()` wartet nicht mehr endlos auf einen Worker, der den Start nach `max_consecutive_failures` aufgegeben hat.

Statische Builds wandeln behebbare Go-Fehler in der gebündelten Parallel-Erweiterung nicht mehr in Prozessabstürze um. Ein möglicher Use-after-free des von `register_extensions` gehaltenen Erweiterungs-Arrays ist behoben. `extgen` verarbeitet nun gruppierte und nullable Parameter, Callables, gemischte Rückgabewerte, Methoden-Wrapper, Konstanten und Integer-Literale in generierten Erweiterungen.

Die Dokumentation führt nun Laufzeit-Einstellungen der Engine auf, die im Worker-Modus zwischen Requests bestehen bleiben. Beispiele sind `ini_set()`, `stream_context_set_default()`, `date_default_timezone_set()` und `chdir()`. Hinzu kommen Hinweise zu Unterschieden bei der HTTP-Request-Filterung, eine erweiterte Metrik-Dokumentation, eine Seite zu Yii 3, eine reparierte Idiomorph-CDN-URL im Hot-Reload-Snippet und fehlende türkische Übersetzungen. johanjanssens, luminalpark, KalimeroMK und quyt0 leisteten ihren ersten Beitrag zu diesem Release.