From 195292847120349d66e9572a48dfa3e7a5b41f24 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Tue, 2 Jul 2019 17:48:31 -0400 Subject: [PATCH] Improving the request/response format autodetection --- .../Component/HttpFoundation/Request.php | 23 ++++++++++++++++ .../Component/HttpFoundation/Response.php | 2 +- .../HttpFoundation/Tests/RequestTest.php | 26 +++++++++++++++++++ .../EventListener/DebugHandlersListener.php | 2 +- 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 83cdf60169..a950b0a159 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -192,6 +192,10 @@ class Request protected static $requestFactory; + /** + * @var string|null + */ + private $preferredFormat; private $isHostValid = true; private $isForwardedValid = true; @@ -1559,6 +1563,25 @@ class Request return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); } + public function getPreferredFormat(?string $default = 'html'): ?string + { + if (null !== $this->preferredFormat) { + return $this->preferredFormat; + } + + $this->preferredFormat = $this->getRequestFormat($this->getContentType()); + + if (null === $this->preferredFormat) { + foreach ($this->getAcceptableContentTypes() as $contentType) { + if (null !== $this->preferredFormat = $this->getFormat($contentType)) { + break; + } + } + } + + return $this->preferredFormat ?: $default; + } + /** * Returns the preferred language. * diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index d1263ca7a1..1681558499 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -270,7 +270,7 @@ class Response } else { // Content-type based on the Request if (!$headers->has('Content-Type')) { - $format = $request->getRequestFormat(); + $format = $request->getPreferredFormat(); if (null !== $format && $mimeType = $request->getMimeType($format)) { $headers->set('Content-Type', $mimeType); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index c1168f5e45..6573da0785 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -399,6 +399,32 @@ class RequestTest extends TestCase $this->assertEquals('xml', $dup->getRequestFormat()); } + public function testGetPreferredFormat() + { + $request = new Request(); + $this->assertNull($request->getPreferredFormat(null)); + $this->assertSame('html', $request->getPreferredFormat()); + $this->assertSame('json', $request->getPreferredFormat('json')); + + $request->setRequestFormat('atom'); + $request->headers->set('Content-Type', 'application/json'); + $request->headers->set('Accept', 'application/xml'); + $this->assertSame('atom', $request->getPreferredFormat()); + + $request = new Request(); + $request->headers->set('Content-Type', 'application/json'); + $request->headers->set('Accept', 'application/xml'); + $this->assertSame('json', $request->getPreferredFormat()); + + $request = new Request(); + $request->headers->set('Accept', 'application/xml'); + $this->assertSame('xml', $request->getPreferredFormat()); + + $request = new Request(); + $request->headers->set('Accept', 'application/json;q=0.8,application/xml;q=0.9'); + $this->assertSame('xml', $request->getPreferredFormat()); + } + /** * @dataProvider getFormatToMimeTypeMapProviderWithAdditionalNullFormat */ diff --git a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php index b0b9a94c28..ebf6c96fcb 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php @@ -174,7 +174,7 @@ class DebugHandlersListener implements EventSubscriberInterface $e = $request->attributes->get('exception'); try { - return new Response($this->errorFormatter->render($e, $request->getRequestFormat()), $e->getStatusCode(), $e->getHeaders()); + return new Response($this->errorFormatter->render($e, $request->getPreferredFormat()), $e->getStatusCode(), $e->getHeaders()); } catch (ErrorRendererNotFoundException $_) { return new Response($this->errorFormatter->render($e), $e->getStatusCode(), $e->getHeaders()); }