diff --git a/src/PSR7/Validators/BodyValidator/MultipartValidator.php b/src/PSR7/Validators/BodyValidator/MultipartValidator.php index a129fb15..aa29310f 100644 --- a/src/PSR7/Validators/BodyValidator/MultipartValidator.php +++ b/src/PSR7/Validators/BodyValidator/MultipartValidator.php @@ -28,7 +28,9 @@ use Riverline\MultiPartParser\StreamedPart; use RuntimeException; +use function array_map; use function array_replace; +use function explode; use function in_array; use function is_array; use function json_decode; @@ -117,29 +119,29 @@ private function validatePlainBodyMultipart( foreach ($parts as $part) { // 2.1 parts encoding - $partContentType = $part->getHeader(self::HEADER_CONTENT_TYPE); - $encodingContentType = $this->detectEncondingContentType($encoding, $part, $schema->properties[$partName]); - if (strpos($encodingContentType, '*') === false) { - // strict comparison (ie "image/jpeg") - if ($encodingContentType !== $partContentType) { - throw InvalidBody::becauseBodyDoesNotMatchSchemaMultipart( - $partName, - $partContentType, - $addr - ); - } - } else { - // loose comparison (ie "image/*") - $encodingContentType = str_replace('*', '.*', $encodingContentType); - if (! preg_match('#' . $encodingContentType . '#', $partContentType)) { - throw InvalidBody::becauseBodyDoesNotMatchSchemaMultipart( - $partName, - $partContentType, - $addr - ); + $partContentType = $part->getHeader(self::HEADER_CONTENT_TYPE); + $validContentTypes = $this->detectEncodingContentTypes($encoding, $part, $schema->properties[$partName]); + $match = false; + + foreach ($validContentTypes as $encodingContentType) { + if (strpos($encodingContentType, '*') === false) { + // strict comparison (ie "image/jpeg") + $match = $match || $encodingContentType === $partContentType; + } else { + // loose comparison (ie "image/*") + $encodingContentType = str_replace('*', '.*', $encodingContentType); + $match = $match || preg_match('#' . $encodingContentType . '#', $partContentType); } } + if (! $match) { + throw InvalidBody::becauseBodyDoesNotMatchSchemaMultipart( + $partName, + $partContentType, + $addr + ); + } + // 2.2. parts headers $validator = new SchemaValidator($this->detectValidationStrategy($message)); foreach ($encoding->headers as $headerName => $headerSpec) { @@ -195,7 +197,10 @@ private function parseMultipartData(OperationAddress $addr, StreamedPart $docume return $multipartData; } - private function detectEncondingContentType(Encoding $encoding, StreamedPart $part, Schema $partSchema): string + /** + * @return string[] + */ + private function detectEncodingContentTypes(Encoding $encoding, StreamedPart $part, Schema $partSchema): array { $contentType = $encoding->contentType; @@ -219,7 +224,7 @@ private function detectEncondingContentType(Encoding $encoding, StreamedPart $pa } } - return $contentType; + return array_map('trim', explode(',', $contentType)); } /** diff --git a/tests/stubs/multipart.yaml b/tests/stubs/multipart.yaml index df4fa9e9..7cd8fabd 100644 --- a/tests/stubs/multipart.yaml +++ b/tests/stubs/multipart.yaml @@ -91,7 +91,7 @@ paths: format: binary encoding: image: - contentType: image/* + contentType: specific/type, image/* responses: 204: description: good post