Skip to content

feat: remove hydra prefix#590

Open
vincentchalamon wants to merge 3 commits into4.3from
feat/disable-hydra-prefix
Open

feat: remove hydra prefix#590
vincentchalamon wants to merge 3 commits into4.3from
feat/disable-hydra-prefix

Conversation

@vincentchalamon
Copy link
Contributor

@vincentchalamon vincentchalamon commented Feb 5, 2026

Fixes #449

Disabling hydra prefix breaks the admin.

@vincentchalamon

This comment was marked as outdated.

This comment was marked as outdated.

@vincentchalamon vincentchalamon force-pushed the feat/disable-hydra-prefix branch from acd767c to a7ff0ab Compare February 5, 2026 15:21
@vincentchalamon vincentchalamon removed the deploy Deploys Pull Request label Feb 5, 2026
@vincentchalamon vincentchalamon force-pushed the feat/disable-hydra-prefix branch 2 times, most recently from 3472289 to 5abcac6 Compare February 5, 2026 15:52
@vincentchalamon vincentchalamon force-pushed the feat/disable-hydra-prefix branch from 5abcac6 to 0f0322f Compare March 16, 2026 13:27
@vincentchalamon vincentchalamon changed the base branch from 4.2 to 4.3 March 16, 2026 13:31
@vincentchalamon vincentchalamon force-pushed the feat/disable-hydra-prefix branch from 0f0322f to b63a495 Compare March 16, 2026 13:37
@vincentchalamon
Copy link
Contributor Author

Bug : DocumentationNormalizer génère un terme nu non expansible pour owl:onProperty quand hydra_prefix est désactivé

Composant : api-platform/hydrasrc/Serializer/DocumentationNormalizer.php


Description

Depuis API Platform 4.x, le paramètre serializer.hydra_prefix est false par défaut, ce qui supprime le préfixe hydra: des clés JSON-LD des réponses. Cette configuration expose un bug dans DocumentationNormalizer : la valeur de owl:onProperty dans la documentation Hydra devient un terme nu ("member") que jsonld.js est incapable d'expandre correctement vers http://www.w3.org/ns/hydra/core#member. En conséquence, @api-platform/api-doc-parser échoue à initialiser HydraAdmin.


Reproduction

Configuration déclenchante

# config/packages/api_platform.yaml
api_platform:
    # serializer.hydra_prefix absent, ou explicitement false (défaut depuis 4.x)

Ce que génère DocumentationNormalizer (ligne 115)

// api-platform/hydra/src/Serializer/DocumentationNormalizer.php, ligne 115
'owl:onProperty' => ['@id' => $hydraPrefix.'member'],
hydra_prefix $hydraPrefix Valeur générée Après jsonld.expand
true 'hydra:' {"@id": "hydra:member"} http://www.w3.org/ns/hydra/core#member
false (défaut) '' {"@id": "member"} https://example.com/member (IRI relative)

Extrait de /docs.jsonld avec hydra_prefix: false

{
  "@context": ["http://www.w3.org/ns/hydra/context.jsonld", {"@vocab": "https://example.com/docs.jsonld#"}],
  "supportedClass": [{
    "@id": "#Entrypoint",
    "supportedProperty": [{
      "property": {
        "@id": "#Entrypoint/book",
        "range": [
          {"@id": "Collection"},
          {
            "owl:equivalentClass": {
              "owl:onProperty": {"@id": "member"},
              "owl:allValuesFrom": {"@id": "#Book"}
            }
          }
        ]
      }
    }]
  }]
}

Cause racine : JSON-LD IRI Expansion avec vocab=false

La clé owl:onProperty n'est pas définie dans le contexte Hydra. Sa valeur {"@id": "member"} est donc une référence de nœud (@id node reference).

Selon la spécification JSON-LD 1.1 §6.3 et son implémentation dans jsonld.js, les valeurs @id sont expansées avec vocab=false :

When expanding an IRI reference (an @id value), vocab is set to false. Term definitions from the active context are only used when vocab is true.

Conséquences pour chaque cas :

  • "hydra:member" → IRI compacte (prefix:localname) → expande toujours vers http://www.w3.org/ns/hydra/core#member, indépendamment de vocab
  • "member" → terme nu sans :vocab=false → pas de lookup dans les term definitions → résolution comme IRI relative contre le basehttps://example.com/member

Note : même si le contexte Hydra définit member avec @type: @id, cette coercition s'applique aux valeurs string de la propriété member, pas aux valeurs déjà en forme {"@id": "..."} dans d'autres propriétés.


Chaîne d'erreur côté frontend

DocumentationNormalizer::populateEntrypointProperties()
  → génère owl:onProperty: {"@id": "member"}

jsonld.expand(docsJsonLd, {base: docsUrl})
  → "member" avec vocab=false → IRI relative → https://example.com/member

@api-platform/api-doc-parser :: findRelatedClass() — stratégie 1
  → cherche owl:onProperty === "http://www.w3.org/ns/hydra/core#member"
  → pas de correspondance → échec

@api-platform/api-doc-parser :: findRelatedClass() — stratégie 2 (fallback)
  → cherche une opération POST retournant un type non-Hydra
  → Book n'a que GetCollection + Get (pas de POST public) → pas de correspondance

→ throw new Error("Cannot find the class related to https://example.com/docs.jsonld#Entrypoint/book.")
→ HydraAdmin ne s'initialise jamais

Erreur observée dans la console du navigateur :

Error: Cannot fetch API documentation: Cannot find the class related to https://localhost/docs.jsonld#Entrypoint/book.

Fix proposé

Option 1 — Utiliser l'IRI compacte (recommandé)

// DocumentationNormalizer.php, ligne 115
// Avant :
'owl:onProperty' => ['@id' => $hydraPrefix.'member'],

// Après :
'owl:onProperty' => ['@id' => 'hydra:member'],

'hydra:member' est une IRI compacte (préfixe explicite). jsonld.js l'expande toujours vers http://www.w3.org/ns/hydra/core#member quel que soit le réglage hydra_prefix, car le préfixe hydra est déclaré dans le contexte Hydra embarqué.

Option 2 — Utiliser l'IRI absolue

'owl:onProperty' => ['@id' => ContextBuilderInterface::HYDRA_NS.'member'],
// → "http://www.w3.org/ns/hydra/core#member"

Les deux options sont correctes. L'option 1 est plus lisible et cohérente avec le reste du document.


Test de régression

Un test PHPUnit a été ajouté dans cette PR pour exposer ce bug (HydraDocumentationTest::entrypointOwlOnPropertyIsMemberCompactIriNotBareTerm). Il échoue avec le code actuel et passera une fois la correction appliquée dans api-platform/hydra.

docker compose exec php bin/phpunit --filter entrypointOwlOnPropertyIsMemberCompactIriNotBareTerm

Composant affecté : api-platform/hydra (DocumentationNormalizer)
Versions confirmées : API Platform 4.3, hydra_prefix: false (défaut)
Régression : toute application utilisant HydraAdmin / @api-platform/api-doc-parser avec hydra_prefix: false

@vincentchalamon vincentchalamon force-pushed the feat/disable-hydra-prefix branch from 24a5c04 to 7e553f6 Compare March 16, 2026 15:59
vincentchalamon and others added 3 commits March 16, 2026 17:34
Fixes #449

# Conflicts:
#	api/src/Entity/Book.php
#	api/src/Entity/Review.php
#	api/tests/Api/Admin/BookTest.php
Adds a failing PHPUnit test that exposes the bug in api-platform/hydra's
DocumentationNormalizer: with hydra_prefix disabled (default), owl:onProperty
is emitted as {"@id": "member"} instead of {"@id": "hydra:member"}, which
jsonld.js cannot expand to hydra:member (vocab=false for @id values), causing
api-doc-parser to throw and HydraAdmin to fail to initialize.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vincentchalamon vincentchalamon force-pushed the feat/disable-hydra-prefix branch from 7e553f6 to 680544f Compare March 16, 2026 16:34
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.

Disable hydra prefix

2 participants