-
-
Notifications
You must be signed in to change notification settings - Fork 920
add a specific "documentation_formats" that may differ from the API "… #1891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -222,6 +222,9 @@ public function getConfigTreeBuilder() | |
|
||
$this->addFormatSection($rootNode, 'formats', [ | ||
'jsonld' => ['mime_types' => ['application/ld+json']], | ||
]); | ||
$this->addFormatSection($rootNode, 'documentation_formats', [ | ||
'jsonld' => ['mime_types' => ['application/ld+json']], // Hydra documentation, admin and PWA generator | ||
'json' => ['mime_types' => ['application/json']], // Swagger support | ||
'html' => ['mime_types' => ['text/html']], // Swagger UI support | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HTML must be defined also in |
||
]); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,12 +28,14 @@ final class AddFormatListener | |
{ | ||
private $negotiator; | ||
private $formats; | ||
private $documentationFormats; | ||
private $mimeTypes; | ||
|
||
public function __construct(Negotiator $negotiator, array $formats) | ||
public function __construct(Negotiator $negotiator, array $formats, array $documentationFormats = []) | ||
{ | ||
$this->negotiator = $negotiator; | ||
$this->formats = $formats; | ||
$this->documentationFormats = $documentationFormats; | ||
} | ||
|
||
/** | ||
|
@@ -51,13 +53,15 @@ public function onKernelRequest(GetResponseEvent $event) | |
return; | ||
} | ||
|
||
$this->populateMimeTypes(); | ||
$this->addRequestFormats($request, $this->formats); | ||
$requestAcceptedFormats = $this->getRequestAcceptedFormats($request); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, this private function can be replaced by |
||
|
||
$this->populateMimeTypes($requestAcceptedFormats); | ||
$this->addRequestFormats($request, $requestAcceptedFormats); | ||
|
||
// Empty strings must be converted to null because the Symfony router doesn't support parameter typing before 3.2 (_format) | ||
if (null === $routeFormat = $request->attributes->get('_format') ?: null) { | ||
$mimeTypes = array_keys($this->mimeTypes); | ||
} elseif (!isset($this->formats[$routeFormat])) { | ||
} elseif (!isset($requestAcceptedFormats[$routeFormat])) { | ||
throw new NotFoundHttpException(sprintf('Format "%s" is not supported', $routeFormat)); | ||
} else { | ||
$mimeTypes = Request::getMimeTypes($routeFormat); | ||
|
@@ -84,11 +88,11 @@ public function onKernelRequest(GetResponseEvent $event) | |
return; | ||
} | ||
|
||
throw $this->getNotAcceptableHttpException($mimeType); | ||
throw $this->getNotAcceptableHttpException($mimeType ?? $requestFormat); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
// Finally, if no Accept header nor Symfony request format is set, return the default format | ||
foreach ($this->formats as $format => $mimeType) { | ||
foreach ($requestAcceptedFormats as $format => $mimeType) { | ||
$request->setRequestFormat($format); | ||
|
||
return; | ||
|
@@ -110,15 +114,17 @@ private function addRequestFormats(Request $request, array $formats) | |
|
||
/** | ||
* Populates the $mimeTypes property. | ||
* | ||
* @param array $requestAcceptedFormats | ||
*/ | ||
private function populateMimeTypes() | ||
private function populateMimeTypes(array $requestAcceptedFormats) | ||
{ | ||
if (null !== $this->mimeTypes) { | ||
return; | ||
} | ||
|
||
$this->mimeTypes = []; | ||
foreach ($this->formats as $format => $mimeTypes) { | ||
foreach ($requestAcceptedFormats as $format => $mimeTypes) { | ||
foreach ($mimeTypes as $mimeType) { | ||
$this->mimeTypes[$mimeType] = $format; | ||
} | ||
|
@@ -145,4 +151,16 @@ private function getNotAcceptableHttpException(string $accept, array $mimeTypes | |
implode('", "', $mimeTypes) | ||
)); | ||
} | ||
|
||
/** | ||
* Retrieves the list of accepted format in the request depending on some parameters. | ||
*/ | ||
private function getRequestAcceptedFormats(Request $request): array | ||
{ | ||
if (!$request->attributes->has('_api_endpoint_type')) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Just drop this function, see below. |
||
return $this->formats; | ||
} | ||
|
||
return 'documentation' === $request->attributes->get('_api_endpoint_type') ? $this->documentationFormats : $this->formats; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ public function testNoResourceClass() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['notexist' => 'application/vnd.notexist']); | ||
$listener = new AddFormatListener(new Negotiator(), ['notexist' => 'application/vnd.notexist'], []); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As the new array argument has a default value we don't really need to change this right? |
||
$listener->onKernelRequest($event); | ||
|
||
$this->assertNull($request->getFormat('application/vnd.notexist')); | ||
|
@@ -47,7 +47,7 @@ public function testSupportedRequestFormat() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['text/xml']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['text/xml']], []); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('xml', $request->getRequestFormat()); | ||
|
@@ -63,7 +63,7 @@ public function testRespondFlag() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['text/xml']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['text/xml']], []); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('xml', $request->getRequestFormat()); | ||
|
@@ -83,7 +83,7 @@ public function testUnsupportedRequestFormat() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['json' => ['application/json']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['json' => ['application/json']], []); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('json', $request->getRequestFormat()); | ||
|
@@ -98,7 +98,7 @@ public function testSupportedAcceptHeader() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['binary' => ['application/octet-stream'], 'json' => ['application/json']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['binary' => ['application/octet-stream'], 'json' => ['application/json']], []); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('json', $request->getRequestFormat()); | ||
|
@@ -113,7 +113,7 @@ public function testAcceptAllHeader() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['binary' => ['application/octet-stream'], 'json' => ['application/json']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['binary' => ['application/octet-stream'], 'json' => ['application/json']], []); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('binary', $request->getRequestFormat()); | ||
|
@@ -133,7 +133,7 @@ public function testUnsupportedAcceptHeader() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['binary' => ['application/octet-stream'], 'json' => ['application/json']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['binary' => ['application/octet-stream'], 'json' => ['application/json']], []); | ||
$listener->onKernelRequest($event); | ||
} | ||
|
||
|
@@ -150,7 +150,7 @@ public function testInvalidAcceptHeader() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['json' => ['application/json']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['json' => ['application/json']], []); | ||
$listener->onKernelRequest($event); | ||
} | ||
|
||
|
@@ -164,7 +164,7 @@ public function testAcceptHeaderTakePrecedenceOverRequestFormat() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['application/xml'], 'json' => ['application/json']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['application/xml'], 'json' => ['application/json']], []); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('json', $request->getRequestFormat()); | ||
|
@@ -182,7 +182,42 @@ public function testInvalidRouteFormat() | |
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['json' => ['application/json']]); | ||
$listener = new AddFormatListener(new Negotiator(), ['json' => ['application/json']], []); | ||
$listener->onKernelRequest($event); | ||
} | ||
|
||
public function testSupportedDocumentationAcceptHeader() | ||
{ | ||
$request = new Request([], [], ['_api_respond' => '1', '_api_endpoint_type' => 'documentation']); | ||
$request->setRequestFormat('json'); | ||
|
||
$eventProphecy = $this->prophesize(GetResponseEvent::class); | ||
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['text/xml']], ['json' => ['application/json']]); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('json', $request->getRequestFormat()); | ||
$this->assertSame('application/json', $request->getMimeType($request->getRequestFormat())); | ||
} | ||
|
||
/** | ||
* @expectedException \Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException | ||
* @expectedExceptionMessageRegExp /^Requested format "(jsonld|application\/ld\+json)" is not supported. Supported MIME types are "application\/json".$/ | ||
*/ | ||
public function testUnsupportedDocumentationRequestFormat() | ||
{ | ||
$request = new Request([], [], ['_api_respond' => '1', '_api_endpoint_type' => 'documentation']); | ||
$request->setRequestFormat('jsonld'); | ||
|
||
$eventProphecy = $this->prophesize(GetResponseEvent::class); | ||
$eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); | ||
$event = $eventProphecy->reveal(); | ||
|
||
$listener = new AddFormatListener(new Negotiator(), ['xml' => ['text/xml']], ['json' => ['application/json']]); | ||
$listener->onKernelRequest($event); | ||
|
||
$this->assertSame('json', $request->getRequestFormat()); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you keep this test (and duplicate it for XML if appropriate)? It checks that the documentation for any URL feature works (for instance when you open
http://localhost/books/1
, Swagger UI shows up and automatically runs the AJAX request).