Skip to content

Commit

Permalink
Merge pull request #1 from leobedrosian/fix-array-merging-with-nested…
Browse files Browse the repository at this point in the history
…-files

Fix Multipart Validation Bug
  • Loading branch information
leobedrosian authored Sep 30, 2024
2 parents a665e22 + 2785d40 commit 1973342
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/PSR7/Validators/BodyValidator/MultipartValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

use function array_diff_assoc;
use function array_map;
use function array_replace;
use function array_replace_recursive;
use function array_shift;
use function explode;
use function in_array;
Expand Down Expand Up @@ -291,7 +291,24 @@ private function validateServerRequestMultipart(

$files = $this->normalizeFiles($message->getUploadedFiles());

$body = array_replace($body, $files);
// The PHP kernel separates file data (binary) from body data so it's
// imperative to combine the two arrays __recursively__ to have properly
// constructed arrays of objects (collections) prior to validating
// them against the schema
//
// Otherwise, the file array will overwrite the body array at the common
// __root__ element, which may result in an object validation error if
// the object also contains other properties (stored in the body array)
//
// Eg: Array of file objects with a text descriptor
// [
// ['description' => <string>, 'file' => <binary>]
// ['description' => <string>, 'file' => <binary>]
// ['description' => <string>, 'file' => <binary>]
// ]
//
// The 'description' would be in $body and 'file' would be in $files
$body = array_replace_recursive($body, $files);

$validator = new SchemaValidator($this->detectValidationStrategy($message));
try {
Expand Down
41 changes: 41 additions & 0 deletions tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,27 @@ public function dataProviderMultipartGreen(): array
[file content goes there]
------WebKitFormBoundaryWfPNVh4wuWBlyEyQ--
HTTP
,
],
// multipart mixed message with nested file objects (collections)
[
<<<HTTP
POST /multipart/files/collections HTTP/1.1
Content-Length: 311
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWRBHApnEKYVLfiJ1
------WebKitFormBoundaryWRBHApnEKYVLfiJ1
Content-Disposition: form-data; name="files[0][caption]"
Content-Type: text/plain
some-type
------WebKitFormBoundaryWRBHApnEKYVLfiJ1
Content-Disposition: form-data; name="files[0][file]"; filename="image1.png"
Content-Type: application/octet-stream
{...file content...}
------WebKitFormBoundaryWRBHApnEKYVLfiJ1--
HTTP
,
],
// specified encoding for one part
Expand Down Expand Up @@ -446,6 +467,26 @@ public function dataProviderMultipartServerRequestGreen(): array
'profileImage' => new UploadedFile($imagePath, $imageSize, 0),
],
],
// multipart mixed message with nested file objects (collections)
// The PHP kernel separates binary data (files) from body data so it's
// important to test that this is correctly handled by the validator
// when dealing with nested objects
[
'post',
'/multipart/files/collections',
[
'files' => [
['caption' => 'Some caption'],
['caption' => 'Some caption'],
],
],
[
'files' => [
['file' => new UploadedFile($imagePath, $imageSize, 0)],
['file' => new UploadedFile($imagePath, $imageSize, 0)],
],
],
],
// Missing optional field with defined encoding
[
'post',
Expand Down
27 changes: 27 additions & 0 deletions tests/stubs/multipart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,33 @@ paths:
type: string
format: binary

responses:
204:
description: good post
/multipart/files/collections:
post:
summary: ---
operationId: post-multipart-file-collections
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
files:
type: array
items:
type: object
required:
- caption
- file
properties:
caption:
type: string
file:
type: string
format: binary

responses:
204:
description: good post
Expand Down

0 comments on commit 1973342

Please sign in to comment.