Signposting¶
Signposting is a technique used in RESTful APIs where other relevant resources are exposed to clients as Link
headers in
GET
and HEAD
requests. These Link
headers follow a standard format as specified in RFC8288. Drupal already makes use of this technique for content entities, and Islandora takes it
even further by providing additional Link
headers that enable the client to navigate the repository and discover
additional information about various resources. Because the links are returned in response headers, they can be relied upon
without having to parse the message body. This makes them consistent across all serialization formats that can be returned in a message body
(XML, JSON, JSONLD, etc...).
As a general precaution, link headers for Drupal entities are not exposed to users that do not have the permissions to view
the entity linked in the header. So making GET and HEAD requests anonymously will yield a different set of headers than
what an authenticated user would see. For example, anonymous users don't have the view media
permission, so they will not
see the link headers for media associated with a node.
Link Headers Provided by Islandora¶
Alternate Representations¶
Other representations generated by different serializers available through Drupal's REST API are exposed as link headers
with rel="alternate"
and type
equal to the mimetype that will be received when dereferencing the link. For example,
if an entity in Drupal has a JSONLD representation, then the link header returned in a GET or HEAD response would look like
Link: <http://example.org/node/1?_format=jsonld>; rel="alternate"; type="application/ld+json"
Referenced Entities¶
Entity reference fields are exposed as link headers with rel="related"
and a title equal to the entity reference field's display label.
For example, if http://example.org/node/1
has an entity reference field name "Associated Content" that references
http://example.org/node/2
, then the link header returned in a GET or HEAD response would look like
Link: <http://example.org/node/2>; rel="related"; title="Associated Content"
Referenced Taxonomy Terms¶
Entity reference fields for taxonomy terms get special handling. The taxonomy terms used to tag content are exposed as link headers
with rel="tag"
and a title equal to the taxonomy term's display label. If the term has an external URI in a controlled vocabulary,
then that URI is provided. Otherwise, the local Drupal URI is provided. For example, if a piece of content is tagged with
taxonomy/term/1
, which has a display label of "Example Term", then the link header returned in a GET or HEAD response would look like
Link: <http://example.org/taxonomy/term/1>; rel="tag"; title="Example Term"
If instead the term were to have the field_external_uri
field with a value of http://exampletwo.org/vocab#term
then the link
header would look like
Link: <http://exampletwo.org/vocab#term>; rel="tag"; title="Example Term"
.
Associated Media¶
Media entities belonging to nodes are exposed as link headers with rel="related"
and a title equal to the display label of
their field_media_use
taxonomy term. For example, if a media is tagged as Original File
indicating
that it is the initial file uploaded, the link header returned in a GET or HEAD response for a node would look like
Link: <http://example.org/media/1>; rel="related"; title="Original File"
.
Source Files¶
Files that are the source for media entities are exposed as Link headers in the GET and HEAD responses with rel="describes"
.
The endpoint to edit the contents of the source file is also exposed using rel="edit-media"
. For example, if
http://example.org/media/1
has the source file http://example.org/file.txt
, then a GET or HEAD response would contain
both
Link: <http://example.org/file.txt>; rel="describes"
Link: <http://example.org/media/1/source>; rel="edit-media"
Examples¶
Requesting a Node¶
After creating a node, adding it to a Collection, uploading a file and kicking off derivatives, the link headers returned for said node would look like the following. Note that non-Link headers have been removed for brevity:
vagrant@claw:~$ curl -I http://localhost:8000/node/1?_format=json
HTTP/1.1 200 OK
...
# These are provided by Drupal core
Link: <http://localhost:8000/node/1>; rel="canonical"
Link: <http://localhost:8000/node/1/delete>; rel="https://drupal.org/link-relations/delete-form"
Link: <http://localhost:8000/admin/content/node/delete?node=1>; rel="https://drupal.org/link-relations/delete-multiple-form"
Link: <http://localhost:8000/node/1/edit>; rel="edit-form"
Link: <http://localhost:8000/node/1/revisions>; rel="version-history"
Link: <http://localhost:8000/node/1>; rel="https://drupal.org/link-relations/revision"
Link: <http://localhost:8000/node?node=1>; rel="https://drupal.org/link-relations/create"
# These are provided by Islandora
Link: <http://localhost:8000/node/2>; rel="related"; title="Member of"
Link: <http://purl.org/coar/resource_type/c_c513>; rel="tag"; title="Image"
Link: <http://localhost:8000/media/1>; rel="related"; title="Original File"
Link: <http://localhost:8000/media/2>; rel="related"; title="Service File"
Link: <http://localhost:8000/media/3>; rel="related"; title="Thumbnail Image"
Link: <http://localhost:8000/node/1?_format=jsonld>; rel="alternate"; type="application/ld+json"
Requesting a Media¶
If we were to inspect one of the Media associated with this node (which we would've gotten in the response above), the results would look like:
vagrant@claw:~$ curl -I http://localhost:8000/media/1?_format=json
HTTP/1.1 200 OK
...
# These are provided by Drupal core
Link: <http://localhost:8000/media/add>; rel="https://drupal.org/link-relations/add-page"
Link: <http://localhost:8000/media/add/image>; rel="https://drupal.org/link-relations/add-form"
Link: <http://localhost:8000/media/1>; rel="canonical"
Link: <http://localhost:8000/admin/content/media>; rel="collection"
Link: <http://localhost:8000/media/1/delete>; rel="https://drupal.org/link-relations/delete-form"
Link: <http://localhost:8000/media/delete?media=1>; rel="https://drupal.org/link-relations/delete-multiple-form"
Link: <http://localhost:8000/media/1/edit>; rel="edit-form"
Link: <http://localhost:8000/media/1>; rel="https://drupal.org/link-relations/revision"
# These are provided by Islandora
Link: <http://localhost:8000/node/1>; rel="related"; title="Media of"
Link: <http://pcdm.org/use#OriginalFile>; rel="tag"; title="Original File"
Link: <http://localhost:8000/media/1?_format=jsonld>; rel="alternate"; type="application/ld+json"
Link: <http://localhost:8000/media/1/source>; rel="edit-media"
Link: <http://localhost:8000/_flysystem/fedora/2019-03/IF-Org-Chart_0.jpg>; rel="describes"; type="image/jpeg"