Skip to content
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

fix(hydra): use correctly enable_docs #7062

Open
wants to merge 1 commit into
base: 4.1
Choose a base branch
from

Conversation

alanpoulain
Copy link
Member

Q A
Branch? 4.1
Tickets N/A
License MIT
Doc PR N/A

This PR aims to fix definitively a recurring issue: JSON-LD documentation is mandatory but users don't want to expose their endpoints when the API is private: #1568

The enable_docs configuration parameter removes the api_doc route: the documentation is not exposed anymore, but the URL is needed in some parts of the API Platform code: JSON-LD context, Hydra links, etc.
It regularly causes some bugs.

A relating PR was done in 2018:
#1731

This PR was removing the code adding the Hydra headers when the docs is disabled.
IMO @dunglas's comment was right:

IMO we must never disable the Hydra docs (or throw) when JSON-LD is enabled. The hydra "doc" is mandatory for JSON-LD (because we use Hydra types everywhere in JSON-LD documents) and Hydra compliance.

In 2023 another PRs were done but never merged:
#5676
#5862

@dunglas's comments were having the same point:

#5676 (comment)

No, contexts must always exist according to the JSON-LD spec.

IMHO we have two options:

  • Always register the docs route but "manually" throw a NotFoundHttpException if enable_docs is set to false (consequently the route will technically exists in the Symfony router and the error will be prevented)
  • Always generate the Hydra "docs" if JSON-LD is enabled, even if enable_docs is set to false (but continue to disable the OpenAPI endpoint, Swagger UI etc)

IMHO option 2 is more correct and easier to implement.

#5862 (comment)

I wonder if we cannot do that in a cleaner way: for instance, we could set docs_formats in the DI Extension to jsonld if enabled_docs is false, so we can simplify the routing part and always register the route, as it will work only for JSON-LD.

My proposal:

  • Always enable the route.
  • If enable_docs is set to false, only the jsonld documentation format is registered.
  • Since the JSON-LD/Hydra documentation is always exposed, if enable_docs is false, hydra:supportedClass is not filled: the API resources are not included in the documentation but all the other keys stay (@context, @vocab...).
  • Bonus: if the entrypoint is also disabled (enable_entrypoint set to false), the entrypoint is not added to hydra:entrypoint and hydra:supportedClass.

@alanpoulain alanpoulain requested review from dunglas and soyuka April 2, 2025 14:38
@alanpoulain alanpoulain force-pushed the fix-hydra-enable-docs branch from 9a5eac4 to b7033a4 Compare April 2, 2025 14:50
@@ -111,7 +111,11 @@ public function load(array $configs, ContainerBuilder $container): void
$formats = $this->getFormats($config['formats']);
$patchFormats = $this->getFormats($config['patch_formats']);
$errorFormats = $this->getFormats($config['error_formats']);
$docsFormats = $this->getFormats($config['docs_formats']);
// JSON-LD documentation format is mandatory, even if documentation is disabled.
$docsFormats = ['jsonld' => ['application/ld+json']];
Copy link
Member

Choose a reason for hiding this comment

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

this should be the defaults only if jsonld is actually in the formats (isset($formats['jsonld']))

@@ -65,8 +67,9 @@ public function normalize(mixed $object, ?string $format = null, array $context
$classes = [];
$entrypointProperties = [];
$hydraPrefix = $this->getHydraPrefix($context + $this->defaultContext);
$resourceClasses = $this->docsEnabled ? $object->getResourceNameCollection() : [];
Copy link
Member

Choose a reason for hiding this comment

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

I think that this could be a single configuration like:

defaults:
    hideHydraOperation: true

since 12c4209

$hydraPrefix.'returns' => 'Entrypoint',
],
];
}
Copy link
Member

Choose a reason for hiding this comment

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

I think it's quite weird to have an API with hydra that's not discoverable but nothing in the spec says we can't. We should check whether the Link is sent when entrypointEnabled is set to false (I think we do).

@@ -538,11 +542,6 @@ private function registerJsonLdHydraConfiguration(ContainerBuilder $container, a
if (!$container->has('api_platform.json_schema.schema_factory')) {
$container->removeDefinition('api_platform.hydra.json_schema.schema_factory');
}

if (!$config['enable_docs']) {
$container->removeDefinition('api_platform.hydra.listener.response.add_link_header');
Copy link
Member

Choose a reason for hiding this comment

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

I think that we should check if the operation has hideHydraOperation directly we can do this inside the listener to avoid playing with DI

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.

2 participants