FriendsOfREDAXO / FriendsOfREDAXO/api

media/{filename}/update (PUT/PATCH): Multipart-File-Upload schlägt bei aktivem enable_post_data_reading fehl

Open
#81 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.