Skip to content

Skolem IRI and HTTP cacheability #5035

@tucksaun

Description

@tucksaun

API Platform version(s) affected: 2.6 (at least) and above

Description
When using JSON-LD, API Platform automatically exposes IRIs, but it also exposes some IRIs for anonymous resources which are not stable, leading to the body content changing from one answer to the other.
This is not desirable IMHO because it makes debugging and testing harder and also this results in the ETag header value being unstable which bust HTTP caches.

Before 2.7, the IRIs generation mechanism for anonymous resources relies on spl_object_id so this could lead to the issue when the overall number or order of PHP objects changes (cache clearing or cache miss for instance).
Since 2.7, the IRI generation relies on random_bytes so the IRI for anonymous resources becomes totally unstable preventing any HTTP caching.

Maybe I missed something but trying to override the JSON-LD context is currently of no use and the only workarounds I found are:

  • override ApiPlatform\JsonLd\ContextBuilder and unset the @id key manually,
  • or override ApiPlatform\Symfony\Routing\SkolemIriConverter to return a constant (empty) string.

How to reproduce
Expose an API Resource with a Doctrine embedded or a value object and hit the API using JSON-LD.
You can have a look at https://github.com/tucksaun/api-platform-iri-reproducer.

Possible Solution
IIUC the JSON-LD specs, for blank nodes the @id key is only recommended and not mandatory (https://www.w3.org/TR/json-ld11/#identifying-blank-nodes), and is useful essentially if one wants to use node references to them which is not done automatically by API Platform for anonymous resources as far as I know

So one solution could be to allow disabling the addition of Skolem IRI to anonymous resources globally or per subresource.

I even consider that (if my assumption about @id not being strictly required is correct) the use case where one wants to compare anonymous resources is probably an advanced use case and as such adding IRI to anonymous resources should probably be made an opt-in option?

Additional Context
Produced output (unstable):

{
  "@context": "/contexts/Greeting",
  "@id": "/greetings/1",
  "@type": "Greeting",
  "id": 1,
  "name": "Tugdual",
  "options": {
    "@type": "Options",
    "@id": "/.well-known/genid/493e0689a8264f70af65",
    "notify": false
  },
  "foo": {
    "@type": "ValueObject",
    "@id": "/.well-known/genid/659262289b3472742a7a",
    "bar": 42
  }
}

headers (unstable):

...
etag: "753c1f46a6df1e05ae9525539d217504"
...

Desired output:

{
  "@context": "/contexts/Greeting",
  "@id": "/greetings/1",
  "@type": "Greeting",
  "id": 1,
  "name": "Tugdual",
  "options": {
    "@type": "Options",
    "notify": false
  },
  "foo": {
    "@type": "ValueObject",
    "bar": 42
  }
}

headers (stable):

...
etag: "090f00d2c63731328b6a24352e4d74d8"
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions