Skip to content

add a specific "documentation_formats" that may differ from the API "…#1891

Closed
jdeniau wants to merge 3 commits into
api-platform:masterfrom
jdeniau:jd-feat-documentationFormats
Closed

add a specific "documentation_formats" that may differ from the API "…#1891
jdeniau wants to merge 3 commits into
api-platform:masterfrom
jdeniau:jd-feat-documentationFormats

Conversation

@jdeniau

@jdeniau jdeniau commented Apr 25, 2018

Copy link
Copy Markdown
Contributor
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.

Comment thread src/EventListener/AddFormatListener.php Outdated
private $mimeTypes;

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

Copy link
Copy Markdown
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.

Comment thread src/EventListener/AddFormatListener.php Outdated

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

Copy link
Copy Markdown
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?

Comment thread src/EventListener/AddFormatListener.php Outdated
;
}

private function isDocumentation(Request $request): bool

Copy link
Copy Markdown
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).

Comment thread src/EventListener/AddFormatListener.php Outdated

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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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?

@jdeniau jdeniau Apr 26, 2018

Copy link
Copy Markdown
Contributor Author

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
$request->attributes->set('_controller', 'api_platform.swagger.action.ui');
}

public function addEndpointTypeToRequest(GetResponseEvent $event)

Copy link
Copy Markdown
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
Copy Markdown
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

jdeniau commented Apr 26, 2018

Copy link
Copy Markdown
Contributor Author

@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

jdeniau commented Apr 26, 2018

Copy link
Copy Markdown
Contributor Author

@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

dunglas commented Apr 30, 2018

Copy link
Copy Markdown
Member

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

dunglas commented May 14, 2018

Copy link
Copy Markdown
Member

Any news on this one?

@jdeniau

jdeniau commented May 14, 2018 via email

Copy link
Copy Markdown
Contributor Author

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

dunglas commented May 24, 2018

Copy link
Copy Markdown
Member

Any news :)

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

jdeniau commented May 24, 2018

Copy link
Copy Markdown
Contributor Author

@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 ;)

<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
Copy Markdown
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

jdeniau commented May 24, 2018

Copy link
Copy Markdown
Contributor Author

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

jdeniau commented May 25, 2018

Copy link
Copy Markdown
Contributor Author

@dunglas everything is good

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

jdeniau commented Jun 4, 2018

Copy link
Copy Markdown
Contributor Author

My turn to ping you @dunglas ;)

$event = $eventProphecy->reveal();

$listener = new AddFormatListener(new Negotiator(), ['notexist' => 'application/vnd.notexist']);
$listener = new AddFormatListener(new Negotiator(), ['notexist' => 'application/vnd.notexist'], []);

Copy link
Copy Markdown
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?

@dunglas dunglas left a comment

Copy link
Copy Markdown
Member

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?

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

@dunglas dunglas Jun 4, 2018

Copy link
Copy Markdown
Member

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

$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
Copy Markdown
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')) {

@dunglas dunglas Jun 4, 2018

Copy link
Copy Markdown
Member

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.


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

Copy link
Copy Markdown
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.

}

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

@dunglas dunglas Jun 4, 2018

Copy link
Copy Markdown
Member

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

jdeniau commented Jun 16, 2018

Copy link
Copy Markdown
Contributor Author

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
Copy Markdown
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

dunglas commented Aug 26, 2018

Copy link
Copy Markdown
Member

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

@jdeniau

jdeniau commented Aug 26, 2018

Copy link
Copy Markdown
Contributor Author

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

flug commented Nov 14, 2019

Copy link
Copy Markdown
Contributor

@jdeniau Up is this pull request still valid?

@jdeniau

jdeniau commented Nov 14, 2019

Copy link
Copy Markdown
Contributor Author

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants