Skip to content

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

Closed

Conversation

jdeniau
Copy link
Contributor

@jdeniau jdeniau commented Apr 25, 2018

Q A
Bug fix? yes
New feature? yes
BC breaks? See descrption
Deprecations? no
Tests pass? yes
Fixed tickets #1854
License MIT
Doc PR api-platform/docs#475

This PR allow to disable the "json" format from the api and only allow jsonld for example, without breaking the swagger documentation.

About the deprecation though: I removed "json" and "html" from the formats, to keep only "jsonld", and moved "json" and "html" to the documentation formats only.
Technically, it's a compatibility break, but as often can be seen as a bugfix (at least for the html format).

If you like, I can add the json format back, but as I see it, api-platform default is really nicely coupled with json-jd, so I assumed that the json format it was for documentation only.

private $mimeTypes;

public function __construct(Negotiator $negotiator, array $formats)
public function __construct(Negotiator $negotiator, array $formats, array $documentationFormats)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It must have a default value (= []), or it's BC break.


private function getRequestFormats(Request $request): array
{
return $this->isDocumentation($request)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you inline this please?

;
}

private function isDocumentation(Request $request): bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove this function? (It's in the hot path, and function calls are costly).


private function isDocumentation(Request $request): bool
{
return 'api_platform.action.documentation' === $request->attributes->get('_controller');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternative proposal:

set a _api_documentation attribute here https://github.com/api-platform/core/blob/master/src/Bridge/Symfony/Bundle/Resources/config/routing/docs.xml#L10, and test for the presence of this flag. It would be more flexible and give an extension point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dunglas What you think about a _api_endpoint_type set to documentation instead ? It may avoid anyone to add another variable later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually prefer boolean flags (almost all others are boolean). What other type can it be?

Copy link
Contributor Author

@jdeniau jdeniau Apr 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may something related to graphql for example 🤷‍♂️

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch 3 times, most recently from 9bfc712 to e5a9af8 Compare April 26, 2018 07:32
@@ -34,4 +34,10 @@ public function onKernelRequest(GetResponseEvent $event)

$request->attributes->set('_controller', 'api_platform.swagger.action.ui');
}

public function addEndpointTypeToRequest(GetResponseEvent $event)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary? The flag will always be set for every request even if it's not caught by Swagger UI isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I need to set the same check as onKernelRequest function.

I need to separate the two listener because the AddFormatListener come between priority 0 and 7

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch 2 times, most recently from 5e06a1e to d4ebcc9 Compare April 26, 2018 10:04
@jdeniau
Copy link
Contributor Author

jdeniau commented Apr 26, 2018

@dunglas done, I just changed _api_documentation by _api_endpoint_type set to documentation.

For the circleci test, I think it's a problem with circleci configuration

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch from d4ebcc9 to d3d2660 Compare April 26, 2018 10:28
@jdeniau
Copy link
Contributor Author

jdeniau commented Apr 26, 2018

@dunglas I'm kind of stuck here with a circular exception on the SwaggerUiListener, maybe you have an idea :

The SwaggerUiListener depends on the AddFormatListener for the text/html request format to be set.

The AddFormatListener need to know if we are on a documentation page or not, and thus needs to have the documentation attribute set.

The only solution I see here is to dissociate the AddFormatListener and something that throw the exception but it seems really overkill for such a small feature, don't yout think ?

@dunglas
Copy link
Member

dunglas commented Apr 30, 2018

I would handle Swagger UI in two different ways:

  • For the /docs URL: handle it using documentation_formats as done in this PR
  • For all others URL, consider that HTML is not a "documentation" format (because it is not really, it allows to serialize the resource itself as HTML). So there are no need to mark all those routes as "documentation" (they are not, they are resources routes). I would just let the hijacking mechanism working as it is currently, except that I suggest to disable the hijacking if Swagger is not present in documentation_formats. To clarify: disable the HTML format if Swagger is not enabled in the DI extension.

WDYT?

@dunglas
Copy link
Member

dunglas commented May 14, 2018

Any news on this one?

@jdeniau
Copy link
Contributor Author

jdeniau commented May 14, 2018 via email

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch from d3d2660 to 3645e4f Compare May 18, 2018 08:57
@dunglas
Copy link
Member

dunglas commented May 24, 2018

Any news :)

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch from ebfab4c to 70e809b Compare May 24, 2018 12:05
@jdeniau
Copy link
Contributor Author

jdeniau commented May 24, 2018

@dunglas should be OK.

I removed the weird listener that I previously added.

As it is very internal functionality, I am not 100% sure of what I have done though ;)

@@ -7,7 +7,7 @@
<services>

<service id="api_platform.swagger.listener.ui" class="ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? 0 is the default priority.

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch from 70e809b to cdf3c2b Compare May 24, 2018 12:28
@jdeniau
Copy link
Contributor Author

jdeniau commented May 24, 2018

Still an issue due to changes I made in the available formats

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch 3 times, most recently from 7ac99f8 to 7b07a71 Compare May 25, 2018 14:16
@jdeniau
Copy link
Contributor Author

jdeniau commented May 25, 2018

@dunglas everything is good

@jdeniau jdeniau force-pushed the jd-feat-documentationFormats branch from 7b07a71 to c106cb2 Compare June 4, 2018 07:43
@jdeniau
Copy link
Contributor Author

jdeniau commented Jun 4, 2018

My turn to ping you @dunglas ;)

@@ -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'], []);
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Member

@dunglas dunglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also install this PR in the demo and check that URLs such as /books or /books/1 still display Swagger UI with the correct content inside when loaded trough a web browser please?

@@ -110,8 +110,8 @@ Feature: Content Negotiation support
Then the response status code should be 406
And the header "Content-Type" should be equal to "application/problem+json; charset=utf-8"

Scenario: If the request format is HTML, the error should be in HTML
Copy link
Member

@dunglas dunglas Jun 4, 2018

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).

@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTML must be defined also in addFormatSection section to have the "documentation for any URL" feature working.

*/
private function getRequestAcceptedFormats(Request $request): array
{
if (!$request->attributes->has('_api_endpoint_type')) {
Copy link
Member

@dunglas dunglas Jun 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can call get directly and store the result in a variable to prevent an extra function call. (get will return null if the attribute is not defined)

Just drop this function, see below.

@@ -51,13 +53,15 @@ public function onKernelRequest(GetResponseEvent $event)
return;
}

$this->populateMimeTypes();
$this->addRequestFormats($request, $this->formats);
$requestAcceptedFormats = $this->getRequestAcceptedFormats($request);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this private function can be replaced by 'documentation' === $request->attributes->get('_api_endpoint_type') ? $this->documentationFormats : $this->formats. It removes 2 function calls in the hot path.

@@ -84,11 +88,11 @@ public function onKernelRequest(GetResponseEvent $event)
return;
}

throw $this->getNotAcceptableHttpException($mimeType);
throw $this->getNotAcceptableHttpException($mimeType ?? $requestFormat);
Copy link
Member

@dunglas dunglas Jun 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$requestAcceptedFormats right? This should be covered by a test (because the error isn't caught now)

@jdeniau
Copy link
Contributor Author

jdeniau commented Jun 16, 2018

I'm kinda lost here because of #1798 : it added a format resolver but does not include error format.

Does documentation format should be in FormatsProvider ? What do you thing @antograssiot ?

@antograssiot
Copy link
Contributor

Indeed there is no ErrorFormatsProvider (yet ?).
I can add it if there is a need, it should be pretty easy, and I guess that if you feel that document format needs in some cases to be specified at resource/operation level, you could use a DocumentFormatsProvider or something similar but it seems less likely to be used IMO.

Let's see maintainers opinion.

@dunglas
Copy link
Member

dunglas commented Aug 26, 2018

@jdeniau, do you need any help to finish this PR?

@jdeniau
Copy link
Contributor Author

jdeniau commented Aug 26, 2018

Actually I think I do yes!
I am kind of lost here, because I don't know api-platform internals as you guys do.
Maybe I should look back at #1798 and try harder but any help would be appreciated!

@dunglas dunglas added this to the 2.5.0 milestone Jul 8, 2019
@flug
Copy link
Contributor

flug commented Nov 14, 2019

@jdeniau Up is this pull request still valid?

@jdeniau
Copy link
Contributor Author

jdeniau commented Nov 14, 2019

I did not manage to fix this and have no motivation on that now. I am closing this one.

@jdeniau jdeniau closed this Nov 14, 2019
@jdeniau jdeniau deleted the jd-feat-documentationFormats branch September 27, 2023 06:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants