Skip to content

Editing metadata of resources

What is a description resource

Description resources contain auxiliary information about a resource. In CSS, these represent metadata corresponding to that resource. Every resource always has a corresponding description resource and therefore description resources can not be created or deleted directly.

Description resources are discoverable by interacting with their subject resource: the response to a GET or HEAD request on a subject resource will contain a describedby Link Header with a URL that points to its description resource.

Clients should always follow this link rather than guessing its URL, because the Solid Protocol does not mandate a specific description resource URL. The default CSS configurations use as a convention that has as its description resource.

How to edit the metadata of a resource

Editing the metadata of a resource is performed by editing the description resource directly. This can only be done using PATCH requests (see example workflow).

PUT requests on description resources are not allowed, because they would replace the entire resource state, whereas some metadata is protected or generated by the server.

Similarly, DELETE on description resources is not allowed because a resource will always have some metadata (e.g. rdf:type). Instead, the lifecycle of description resources is managed by the server.

Protected metadata

Some metadata is managed by the server and can not be modified directly, such as the last modified date. The CSS will throw an error (409 ConflictHttpError) when trying to change this protected metadata.

Preserving metadata

PUT requests on a resource will reset the description resource. There is however a way to keep the contents of description resource prior to the PUT request: adding the HTTP Link header targeting the description resource with rel="preserve".

When the resource URL is http://localhost:3000/foobar, preserving its description resource when updating its contents can be achieved like in the following example:

curl -X PUT 'http://localhost:3000/foobar' \
-H 'Content-Type: text/turtle' \
-H 'Link: <http://localhost:3000/foobar.meta>;rel="preserve"' \
-d "<ex:s> <ex:p> <ex:o>."

Impact on creating containers

When creating a container the input body is ignored and performing a PUT request on an existing container will result in an error. Container metadata can only be added and modified by performing a PATCH on the description resource, similarly to documents. This is done to clearly differentiate between a container's representation and its metadata.

Example of a workflow for editing a description resource

In this example, we add an inbox description to http://localhost:3000/foo/. This allows discovery of the ldp:inbox as described in the Linked Data Notifications specification.

We have started the CSS with the default configuration and have already created an inbox at http://localhost:3000/inbox/.

Since we don't know the location of the description resource, we first send a HEAD request to the resource to obtain the URL of its description resource.

curl --head 'http://localhost:3000/foo/'

which will produce a response with at least these headers:

HTTP/1.1 200 OK
Link: <http://localhost:3000/foo/.meta>; rel="describedby"

Now that we have the URL of the description resource, we create a patch for adding the inbox in the description of the resource.

curl -X PATCH 'http://localhost:3000/foo/.meta' \
-H 'Content-Type: text/n3' \
--data-raw '@prefix solid: <>.
<> a solid:InsertDeletePatch;
solid:inserts { <http://localhost:3000/foo/> <> <http://localhost:3000/inbox/>. }.'

After this update, we can verify that the inbox is added by performing a GET request to the description resource

curl 'http://localhost:3000/foo/.meta'

With as result for the body

@prefix dc: <>.
@prefix ldp: <>.
@prefix posix: <>.
@prefix xsd: <>.

<http://localhost:3000/foo/> a ldp:Container, ldp:BasicContainer, ldp:Resource;
    dc:modified "2022-06-09T08:17:07.000Z"^^xsd:dateTime;
    ldp:inbox <http://localhost:3000/inbox/>;.

This can also be verified by sending a GET request to the subject resource itself. The inbox location can also be found in the Link headers.

curl -v 'http://localhost:3000/foo/'
HTTP/1.1 200 OK
Link: <http://localhost:3000/inbox/>; rel=""