-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Signposting * Consistency * Fixing bad copy/paste on header output
- Loading branch information
Showing
1 changed file
with
120 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# 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]( | ||
https://tools.ietf.org/html/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 respionse 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: | ||
|
||
```bash | ||
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: | ||
|
||
```bash | ||
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" | ||
|
||
``` |