From 89470adcc2cb16a43c32720ed27a1145010929c5 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Wed, 30 Jul 2025 22:00:39 +0200 Subject: [PATCH] [HttpFoundation] Add new MIME type mappings to `getMimeTypes()` Expanded the MIME type list in `Request::getMimeTypes()` to include mappings for YAML, WBXML, PDF, and CSV formats. --- .../Component/HttpFoundation/CHANGELOG.md | 1 + .../Component/HttpFoundation/Request.php | 58 ++++++++++++++++++- .../HttpFoundation/Tests/RequestTest.php | 31 ++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index ca58a4032d8b8..9ee60d40c7dad 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Deprecate using `Request::sendHeaders()` after headers have already been sent; use a `StreamedResponse` instead + * Add support for structured MIME suffix 7.3 --- diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 2f8f0add430ca..53fc69056a299 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1225,7 +1225,7 @@ public static function getMimeTypes(string $format): array /** * Gets the format associated with the mime type. */ - public function getFormat(?string $mimeType): ?string + public function getFormat(?string $mimeType, bool $subtypeFallback = false): ?string { $canonicalMimeType = null; if ($mimeType && false !== $pos = strpos($mimeType, ';')) { @@ -1245,6 +1245,27 @@ public function getFormat(?string $mimeType): ?string } } + if (!$canonicalMimeType) { + $canonicalMimeType = $mimeType; + } + + if (str_starts_with($canonicalMimeType, 'application/') && str_contains($canonicalMimeType, '+')) { + $suffix = substr(strrchr($canonicalMimeType, '+'), 1); + if (isset(static::getStructuredSuffixFormats()[$suffix])) { + return static::getStructuredSuffixFormats()[$suffix]; + } + } + + if ($subtypeFallback && str_contains($canonicalMimeType, '/')) { + [, $subtype] = explode('/', $canonicalMimeType, 2); + if (str_starts_with($subtype, 'x-')) { + $subtype = substr($subtype, 2); + } + if (!str_contains($subtype, '+')) { + return $subtype; + } + } + return null; } @@ -1917,6 +1938,41 @@ protected static function initializeFormats(): void 'atom' => ['application/atom+xml'], 'rss' => ['application/rss+xml'], 'form' => ['application/x-www-form-urlencoded', 'multipart/form-data'], + 'soap' => ['application/soap+xml'], + 'problem' => ['application/problem+json'], + 'hal' => ['application/hal+json', 'application/hal+xml'], + 'jsonapi' => ['application/vnd.api+json'], + 'yaml' => ['text/yaml', 'application/x-yaml'], + 'wbxml' => ['application/vnd.wap.wbxml'], + 'pdf' => ['application/pdf'], + 'csv' => ['text/csv'], + ]; + } + + /** + * Structured MIME suffix fallback formats + * + * This mapping is used when no exact MIME match is found in $formats. + * It enables handling of types like application/soap+xml → 'xml'. + * + * @see https://datatracker.ietf.org/doc/html/rfc6839 + * @see https://datatracker.ietf.org/doc/html/rfc7303 + * + * @return array + */ + private static function getStructuredSuffixFormats(): array + { + return [ + 'json' => 'json', + 'xml' => 'xml', + 'xhtml' => 'html', + 'cbor' => 'cbor', + 'zip' => 'zip', + 'ber' => 'asn1', + 'der' => 'asn1', + 'tlv' => 'tlv', + 'wbxml' => 'xml', + 'yaml' => 'yaml', ]; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 62284e725cdcb..4bb93cc791aa6 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -531,7 +531,38 @@ public static function getFormatToMimeTypeMapProvider() ['xml', ['text/xml', 'application/xml', 'application/x-xml']], ['rdf', ['application/rdf+xml']], ['atom', ['application/atom+xml']], + ['rss', ['application/rss+xml']], + ['soap', ['application/soap+xml']], ['form', ['application/x-www-form-urlencoded', 'multipart/form-data']], + ['html', ['application/xhtml+xml']], + ['problem', ['application/problem+json']], + ['hal', ['application/hal+json', 'application/hal+xml']], + ['jsonapi', ['application/vnd.api+json']], + ['yaml', ['application/x-yaml', 'text/yaml']], + ['wbxml', ['application/vnd.wap.wbxml']], + ]; + } + + /** + * @dataProvider getFormatWithSubtypeFallbackProvider + */ + public function testGetFormatFromMimeTypeWithSubtypeFallback($expectedFormat, $mimeTypes) + { + $request = new Request(); + foreach ($mimeTypes as $mime) { + $this->assertEquals($expectedFormat, $request->getFormat($mime, true)); + } + } + + public static function getFormatWithSubtypeFallbackProvider() + { + return [ + ['cbor', ['application/example+cbor']], + ['asn1', ['application/ber-stream+ber', 'application/secure-data+der']], + ['zip', ['application/foobar+zip']], + ['tlv', ['application/device-config+tlv']], + ['pdf', ['application/pdf']], + ['csv', ['text/csv']], ]; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy