FriendsOfREDAXO / FriendsOfREDAXO/api
media/{filename}/update (PUT/PATCH): Multipart-File-Upload schlägt bei aktivem enable_post_data_reading fehl
- Dominant language
- PHP
- Stars
- 20
- Forks
- 0
- Avg merge
- 49m
- Merged PRs (30d)
- 17
Description
## Problem
`handleUpdateMedia()` erwartet bei `multipart/form-data`-Requests, dass `parseMultipartInput()` den Body manuell aus `php://input` parsen kann, weil PHP `$_FILES` nur bei POST automatisch befüllt (Kommentar im Code: "PUT/PATCH füllt $_FILES nicht").
Das stimmt nur zur Hälfte: Ist `enable_post_data_reading` aktiv (php.ini-Default, `On`), liest PHP den kompletten `multipart/form-data`-Body bereits **vor jedem Nutzcode** aus `php://input`, um ihn (nur bei POST) in `$_FILES` zu befüllen. Bei PUT/PATCH wird der Body dabei **trotzdem vollständig konsumiert und verworfen**, ohne `$_FILES` zu befüllen. Für `parseMultipartInput()` bleibt dann buchstäblich nichts mehr übrig — `file_get_contents('php://input')` liefert einen leeren String, obwohl `CONTENT_LENGTH` einen echten Body ankündigt.
Der Request schlägt dabei **nicht sichtbar fehl**: `handleUpdateMedia()` fällt in diesem Fall auf reine Metadaten zurück (Titel/Kategorie unverändert), `rex_media_service::updateMedia()` läuft trotzdem "erfolgreich" durch (bumpt nur `updatedate`), die Antwort ist ein normales 200 `{"message":"Media updated",...}`. Der Client bekommt also Erfolg gemeldet, die Datei wird aber nie ersetzt.
## Reproduktion
1. `enable_post_data_reading = On` (Standard).
2. Multipart-Request mit `method: PATCH` (oder PUT) und einem `file`-Feld an `media/{filename}/update` senden (z.B. per `fetch()` mit `FormData`+`method:'PATCH'`).
3. Response ist 200 mit Erfolgsmeldung.
4. Die Mediendatei auf dem Server ist unverändert (Dateigröße/Breite/Höhe/Inhalt identisch zu vorher), nur `updatedate` hat sich geändert.
Direkt verifiziert per Debug-Logging in `parseMultipartInput()`:
```
AT HANDLE() START rawlen=0 CONTENT_LENGTH=2723 method_raw=PATCH FILES=[] POST=[]
boundary='----WebKitFormBoundaryXXX' rawlen=0
```
`CONTENT_LENGTH` zeigt den echten Body an, `php://input` ist aber bereits leer, noch bevor `RouteCollection::handle()` überhaupt mit dem eigentlichen Routing beginnt.
## Mögliche Fixes
- In `handleUpdateMedia()` vor dem Aufruf von `parseMultipartInput()` prüfen, ob der Request **tatsächlich als POST** hereinkam (z.B. über einen `X-HTTP-Method-Override: PATCH`-Header geroutet) und in dem Fall `$_FILES`/`$_POST` bevorzugen, die PHP dann bereits korrekt nativ befüllt hat.
- Und/oder: In der Doku/im Code-Kommentar explizit darauf hinweisen, dass ein Client die Datei **nur zuverlässig** per echtem PUT/PATCH übertragen kann, wenn `enable_post_data_reading = Off` gesetzt ist — das ist aber eine globale, invasive Einstellung (macht `$_POST`/`$_FILES` für die GESAMTE REDAXO-Installation leer, betrifft z.B. auch den Login), in der Praxis für die meisten Installationen keine Option.
- Alternativ die Route zusätzlich für POST öffnen (mit einem separaten Unterscheidungsmerkmal, z.B. einem Query-Parameter oder eigenen Scope), damit Clients native POST-Uploads nutzen können, ohne den PUT/PATCH-Semantikbruch zu riskieren.
## Umgebung
- PHP 8.4.24, Apache/mod_php, Debian-Docker-Image (`docker-library/php`)
- `enable_post_data_reading => On => On` (php.ini-Default, nicht projektspezifisch verändert)
Ich habe das für ein abhängiges Addon (MediaPlace) vorerst über einen eigenen, addon-internen Endpunkt umgangen (echtes POST an eine eigene Route, ruft serverseitig direkt `rex_media_service::updateMedia()`), wollte den eigentlichen Bug hier aber melden, da er wahrscheinlich jede Installation mit PHP-Default-Einstellungen betrifft, die versucht, `media/{filename}/update` mit einer neuen Datei aufzurufen.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by tracing handleUpdateMedia(), parseMultipartInput(), and the media/{filename}/update route under PHP enable_post_data_reading=On, reproducing the empty php://input with a multipart PATCH or PUT. Compare native POST handling, method override behavior, and the proposed POST-route alternative; done means a multipart update reliably replaces the media file rather than only updating metadata, with the response reflecting the actual result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 45/100