From 9f4ed012137f0858a672f8ba24d12db38bd7ec55 Mon Sep 17 00:00:00 2001 From: Leo Bedrosian Date: Mon, 23 Sep 2024 05:33:31 -0500 Subject: [PATCH 1/5] Fixed file and data merging when validating nested multipart properties. --- src/PSR7/Validators/BodyValidator/MultipartValidator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PSR7/Validators/BodyValidator/MultipartValidator.php b/src/PSR7/Validators/BodyValidator/MultipartValidator.php index 8342ccae..8220b900 100644 --- a/src/PSR7/Validators/BodyValidator/MultipartValidator.php +++ b/src/PSR7/Validators/BodyValidator/MultipartValidator.php @@ -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; @@ -291,7 +291,7 @@ private function validateServerRequestMultipart( $files = $this->normalizeFiles($message->getUploadedFiles()); - $body = array_replace($body, $files); + $body = array_replace_recursive($body, $files); $validator = new SchemaValidator($this->detectValidationStrategy($message)); try { From 4eec51c0afac59defdc9cef511959f6667285a8d Mon Sep 17 00:00:00 2001 From: Leo Bedrosian Date: Mon, 23 Sep 2024 17:07:50 -0500 Subject: [PATCH 2/5] Added explanation text to clarify the purpose. --- .../BodyValidator/MultipartValidator.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/PSR7/Validators/BodyValidator/MultipartValidator.php b/src/PSR7/Validators/BodyValidator/MultipartValidator.php index 8220b900..0c1621dc 100644 --- a/src/PSR7/Validators/BodyValidator/MultipartValidator.php +++ b/src/PSR7/Validators/BodyValidator/MultipartValidator.php @@ -291,6 +291,23 @@ private function validateServerRequestMultipart( $files = $this->normalizeFiles($message->getUploadedFiles()); + // 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' => , 'file' => ] + // ['description' => , 'file' => ] + // ['description' => , 'file' => ] + // ] + // + // The 'description' would be in $body and 'file' would be in $files $body = array_replace_recursive($body, $files); $validator = new SchemaValidator($this->detectValidationStrategy($message)); From 896682371106b21ca2cc3e2ff653e3d0e1e3055f Mon Sep 17 00:00:00 2001 From: Leo Bedrosian Date: Mon, 23 Sep 2024 17:08:44 -0500 Subject: [PATCH 3/5] Added tests to verify proper validation occurs. --- .../BodyValidator/MultipartValidatorTest.php | 49 +++++++++++++++++++ tests/stubs/multipart.yaml | 27 ++++++++++ 2 files changed, 76 insertions(+) diff --git a/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php b/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php index 2e2580e6..e733f39e 100644 --- a/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php +++ b/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php @@ -81,6 +81,27 @@ public function dataProviderMultipartGreen(): array [file content goes there] ------WebKitFormBoundaryWfPNVh4wuWBlyEyQ-- HTTP +, + ], + // multipart mixed message with nested file objects (collections) + [ + << 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', diff --git a/tests/stubs/multipart.yaml b/tests/stubs/multipart.yaml index b018b4c6..3e8b0f57 100644 --- a/tests/stubs/multipart.yaml +++ b/tests/stubs/multipart.yaml @@ -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 From c45a82e0db802996a337fd9ac9d123ab08c62737 Mon Sep 17 00:00:00 2001 From: Leo Bedrosian Date: Mon, 23 Sep 2024 22:11:34 -0500 Subject: [PATCH 4/5] Changed to single-line array to pass cs. --- .../BodyValidator/MultipartValidatorTest.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php b/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php index e733f39e..51049ec6 100644 --- a/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php +++ b/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php @@ -476,22 +476,14 @@ public function dataProviderMultipartServerRequestGreen(): array '/multipart/files/collections', [ 'files' => [ - [ - 'caption' => 'Some caption', - ], - [ - 'caption' => 'Some caption', - ], + ['caption' => 'Some caption'], + ['caption' => 'Some caption'], ], ], [ 'files' => [ - [ - 'file' => new UploadedFile($imagePath, $imageSize, 0), - ], - [ - 'file' => new UploadedFile($imagePath, $imageSize, 0), - ], + ['file' => new UploadedFile($imagePath, $imageSize, 0)], + ['file' => new UploadedFile($imagePath, $imageSize, 0)], ], ], ], From 2785d404604cc686cff2795867b9c98e8fd3f5c0 Mon Sep 17 00:00:00 2001 From: Leo Bedrosian Date: Wed, 25 Sep 2024 14:23:33 -0500 Subject: [PATCH 5/5] Fixed typo in media type. --- tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php b/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php index 51049ec6..7f47e4a2 100644 --- a/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php +++ b/tests/PSR7/Validators/BodyValidator/MultipartValidatorTest.php @@ -97,7 +97,7 @@ public function dataProviderMultipartGreen(): array some-type ------WebKitFormBoundaryWRBHApnEKYVLfiJ1 Content-Disposition: form-data; name="files[0][file]"; filename="image1.png" -Content-Type: application/octet-steam +Content-Type: application/octet-stream {...file content...} ------WebKitFormBoundaryWRBHApnEKYVLfiJ1--