Skip to content

Resource Management

Aaron Coburn edited this page May 26, 2020 · 6 revisions

The primary mechanism for creating, updating and deleting resources is defined by the W3C Linked Data Platform (LDP) specification. For those unfamiliar with LDP, an introductory primer is available.

In brief, all resources can be managed with standard HTTP methods: GET for retrieval, POST for creation, PATCH for modification of RDF resources, PUT for replacing content, DELETE for removing content. In addition HEAD and OPTIONS are very useful for determining the capabilities of a given resource.

Retrieving resources

GET /repository/resource HTTP/1.1

RDF-based resources support content negotiation: representations can be requested in text/turtle, application/n-triples and application/ld+json. In addition, an HTML representation is provided for user convenience.

When Non-RDF (binary) resources are added, a corresponding RDF resource is created. Link headers will lead a client to that resource.

That is, if you create an LDP-NR at http://www.example.com/binary and then try to fetch the resource from that URL, you will see a link header for:

Link: <http://www.example.com/binary?ext=description>; rel="describedby"

Requesting the URL from that Link header, you get the description. That description contains these headers:

Link: <http://www.example.com/binary>; rel="describes"
Link: <http://www.example.com/binary?ext=description>; rel="canonical"
Link: <http://www.example.com/binary#description>; rel="alternate"

Note the rel="alternate"— an HTTP server will ignore a fragment in a request path, which means that this "alternate" URL is functionally equivalent to the binary's URL when it comes to matching the resource path.

For example, if you request a LDP-NR http://www.example.com/binary using an Accept header such as text/turtle, you'll get the description. You can PATCH to that URL with SPARQL Update, though the Accept-Patch header is only returned when the description is returned.

The reason for this convolution has to do with RDF contexts: if you PATCH to the description with <>, we want that to expand to the value of the request URL itself, but we also want the subject of the RDF to be the LDP-NR, and the only way to do that is with this sleight of hand where the request URL context is the same as the LDP-NR while also ensuring that the LDP-NR and its description are available at separate URLs. The ?ext=description will only ever respond with RDF.

In general, when an RDF representation is desired, a client should include an Accept header in the request:

Accept: application/ld+json;q=1.0, text/turtle;q=0.5

Resource representations

The default representation of a resource will contain user-managed triples, containment triples (if any) and membership triples (if any). By using a Prefer header in the request, it is possible to manipulate which triples to include or exclude from that representation. It is also possible to add categories of triples that are typically excluded from responses, such as audit triples:

Prefer: return=representation; include="http://www.trellisldp.org/ns/trellis#PreferAudit"

More information about using Prefer headers can be found in the LDP specification.

Creating resources

Using POST:

When a client creates a resource, it is recommended that the request include a Link header defining the LDP resource type to be created along with the Content-Type of the request:

POST /container/ HTTP/1.1
Link: <http://www.w3.org/ns/ldp#RDFSource>; rel="type"
Content-Type: application/ld+json
Slug: resource

In the absence of a Link header, Trellis will guess the LDP resource type based on the Content-Type and/or request body. The default type for RDF-based resources is LDP-RS. The Slug header provides a client-supplied hint for the new resource. That value may not contain slashes or other invalid characters. In the absence of a Slug header, a unique identifier will be generated automatically. The response will include a Location header with the URL of the new resource along with the LDP type of the resource:

Location: https://example.org/container/resource
Link: <http://www.w3.org/ns/ldp#RDFSource>; rel="type"

Using PUT:

POST /container/resource HTTP/1.1
Link: <http://www.w3.org/ns/ldp#RDFSource>; rel="type"
Content-Type: application/ld+json

It is also possible to create resources with PUT. Doing so, however, may lead to a disconnected graph of resources, as any intermediate containers will not be generated automatically. If a client wishes to avoid this situation, the client should use only POST for resource creation.

Modifying resources

Using PATCH:

PATCH /container/resource-1 HTTP/1.1
Content-Type: application/sparql-update
If-Match: "aeb02953618b318fde4a1b162f138b77b981c71c"

RDF resources can be modified in-place with the HTTP PATCH method. Trellis supports the application/sparql-update content type for this, which is a standards-based mechanism for modifying RDF documents. Binary resources do not allow PATCH on the resource bitstream, but they do allow PATCH for modifying the corresponding RDF description.

Using PUT:

PUT /container/resource-1 HTTP/1.1
Content-Type: application/ld+json
If-Match: "aeb02953618b318fde4a1b162f138b77b981c71c"

When modifying an existing resource with PUT or PATCH, it is recommended that a client use an If-Match header along with the ETag identifier for the resource. Note: the supplied ETag value must be a strong ETag, even if the resource generally responds with a weak ETag value.

It is possible to modify the LDP Resource type with PUT so long as the new type is a subtype of the existing resource. To do this, an appropriate Link header would need to be supplied. Trellis will respond with an error if the new LDP type is not a subtype of the existing resource.

Deleting resources

DELETE /container/resource-1 HTTP/1.1

A resource can be deleted with the HTTP DELETE method. It is worth noting that recursive deletes are not supported, and so a DELETE operation on a resource that contains child resources will result in the deletion of the target resource but no change to the child resources. This can lead to a disconnected graph of resources, and so a client wishing to avoid this possibility will need to first walk the resource hierarchy before deleting resources. It is also recommended to first manipulate the ACL resources of the resources in the hierarchy, preventing any modification while the DELETE is in-flight.