Problem Description
For multipart/form-data requests, the converter passes $rawRequest->rawBody() as the $content parameter to Symfony's Request constructor. This means $request->getContent() returns the raw multipart body (including file contents). Under PHP-FPM, php://input is empty for multipart requests — PHP consumes the body during $_POST/$_FILES parsing.
Location
src/DTO/RequestConverter.php, line 29
Technical Analysis
PHP-FPM behavior
From the PHP manual:
php://input is not available with enctype="multipart/form-data".
Under PHP-FPM, $request->getContent() returns "" for multipart requests.
Current converter behavior
$request = new Request(
...
content: $rawRequest->rawBody(), // Raw multipart body with file contents
);
For a multipart request uploading a 10MB file, $rawRequest->rawBody() contains the entire 10MB body. This is stored in $request->content — meaning the file data exists in memory twice (once in the content string, once in the temp file created by Workerman).
Impact
- Memory usage — file data stored twice in memory. A 50MB upload consumes ~100MB.
- Data exposure — code that logs
$request->getContent() will log raw file contents.
- Behavioral inconsistency — code tested under PHP-FPM that expects
getContent() to be empty for multipart will behave differently under Workerman.
When this does NOT matter
- Most Symfony applications never call
getContent() on multipart requests
- File access goes through
$request->files, which works correctly
Proposed Solution
Detect multipart content type and pass empty content:
$contentType = $rawRequest->header('content-type', '');
$isMultipart = stripos($contentType, 'multipart/form-data') !== false;
$request = new Request(
...
content: $isMultipart ? '' : $rawRequest->rawBody(),
);
Priority
🟡 LOW — does not affect typical application behavior. Primarily a memory optimization and consistency improvement.
Tests
// Multipart request
$this->assertSame('', $symfonyRequest->getContent());
$this->assertNotNull($symfonyRequest->files->get('file'));
// JSON request — body preserved
$this->assertSame('{"key":"value"}', $symfonyRequest->getContent());
// Form-urlencoded — body preserved
$this->assertSame('key=value', $symfonyRequest->getContent());
Problem Description
For
multipart/form-datarequests, the converter passes$rawRequest->rawBody()as the$contentparameter to Symfony's Request constructor. This means$request->getContent()returns the raw multipart body (including file contents). Under PHP-FPM,php://inputis empty for multipart requests — PHP consumes the body during$_POST/$_FILESparsing.Location
src/DTO/RequestConverter.php, line 29Technical Analysis
PHP-FPM behavior
From the PHP manual:
Under PHP-FPM,
$request->getContent()returns""for multipart requests.Current converter behavior
For a multipart request uploading a 10MB file,
$rawRequest->rawBody()contains the entire 10MB body. This is stored in$request->content— meaning the file data exists in memory twice (once in the content string, once in the temp file created by Workerman).Impact
$request->getContent()will log raw file contents.getContent()to be empty for multipart will behave differently under Workerman.When this does NOT matter
getContent()on multipart requests$request->files, which works correctlyProposed Solution
Detect multipart content type and pass empty content:
Priority
🟡 LOW — does not affect typical application behavior. Primarily a memory optimization and consistency improvement.
Tests