- Summary
- Requirements
- Installation
- Configuration
- Documentation
- Authorization
- Describe An Existing Object
- Create A New Object
- Modify An Existing Objects Properties
- Delete An Existing Object
- Search For Objects
- List Existing Relationships
- Add A New Relationship
- Remove An Existing Relationship
- Describe A Existing Datastream
- Create A New Datastream
- Modify An Existing Datastreams Properties And Content
- Delete An Existing Datastream
- Permission Mappings
- Todo
This module provides a number of REST end points for fetching/manipulating objects, datastreams, and object relationships from islandora.
The basic structure of the module is such that we define Drupal Menu’s for each resource type. Currently the resources are objects, datastreams, relationships, and solr. Each Menu defines a callback that generates the HTTP responses for any HTTP Methods requested of the given resource GET, PUT, POST, DELETE.
This callback will load a file dedicated to the particular resource located in includes folder and call a function associated with the HTTP method.
So for example if I make a GET request for an object, it will auto load the includes/object.inc file and call a function mapped to the GET method:
function islandora_rest_object_get_response(array $parameters) { ... }
If it were a PUT request for an object it would be:
function islandora_rest_object_put_response(array $parameters) { ... }
These functions are responsible for performing any required actions, say purge an object, etc. As well as generating a response for the client which will typically be a JSON response.
- Islandora
- Islandora SOLR Search (Optional)
Assumes the following global XACML polices have been removed from:
$FEDORA_HOME/data/fedora-xacml-policies/repository-policies/default
- deny-inactive-or-deleted-objects-or-datastreams-if-not-administrator.xml
- deny-policy-management-if-not-administrator.xml
- deny-purge-datastream-if-active-or-inactive.xml
- deny-purge-object-if-active-or-inactive.xml
This module will still function with those policies in place but the tests this module defines will fail. Also when installing Islandora don't forget to deploy the policies it includes!
Islandora SOLR Search is an optional dependancy that will allow you to perform SOLR searches via this REST API. Follow the directions it provides if you wish to enable SOLR searches.
For each of the REST end-points defined below in the documentation section there exists a corresponding Drupal Permission (with the exception of SOLR which uses the permissions defined by the Islandora SOLR Search module).
After enabling this module navigate to www.yoursite.com/admin/people/permissions and enable the features you want to expose. Note that XACML is still enforced on all REST end-points and access can still be denied regardless of what Drupal Permissions are enabled.
In an effort to simplify the datastream REST end-point multi-part responses for GET requests were investigated. With the intention of returning both the content and properties through a single request. While this is possible it is not well supported by jQuery, there exists a plug-in, I am unsure if this plugin works with all browsers. To get around this issue GET requests for a datastream can return either the content or properties but not both for the moment.
Also since PUT / DELETE support is lacking in IE6-9, we've provided the ability to mock PUT / DELETE requests as POST requests by adding an additional form-data field method to inform the server which method was actually intended.
At the moment multi-part PUT requests such as the one required to modify an existing datastream's content and properties are not implemented you can mock these PUT requests using aforementioned mechanism. POST and include an additional form-data field method with the value PUT.
Adding support for multi-part PUT requests is possible but would require writing or using and HTTP Request parsing library as PUT is not well supported in PHP.
Since we don't have an HTTP Request parsing library PUT requests are expecting raw application/json content as the request body.
In its most common use case - JavaScript executing AJAX callbacks inside module code - no authorization is needed. For external requests, however, an additional step is required.
Drupal doesn't support basic authorization out of the box; any script or other such code that needs authentication to hit the various REST endpoints should first make a POST request to the site login page and then maintain cookies for future requests.
For example, using cURL on a UNIX-like system, and replacing USERNAME
,
PASSWORD
, and SITE_URL
with those respective items:
curl --cookie-jar ./cookies.txt -X POST -H "Content-Type: multipart/form-data" -F "name=USERNAME" -F "pass=PASSWORD" -F "form_id=user_login" -F "op=Log in" "http://SITE_URL/user/login"
In this case:
name
andpass
represent the login credentialsform_id
represents the machine name of the form being POSTed toop
represents the element on the page being used to execute the POST
The stored session data in cookies.txt could then be used for future cURL requests to the API.
Of course, a more comprehensive solution is almost certainly desirable so that passwords are not stored in history - Bash or otherwise - but the same principles apply.
Alternatively the islandora_rest_api_auth submodule exists which can allow for token based user authentication instead.
{variable} Required Parameter.
[variable] Optional Parameter no default defined, NULL or empty string likely be used.
[variable, ’default’] Optional Parameter and it’s default.
Unless otherwise specified each end-point can return the following responses.
Name | Description |
---|---|
message | A message saying the request was invalid. |
400 errors will be triggered by invalid information being provided to a query. In these cases, the request should not be repeated, but rather fixed before another request is made.
In general 401 means an anonymous user attempted some action and was denied. Either the action is not granted to anonymous uses in the Drupal permissions, or XACML denied the action for the anonymous user.
In general 403 means an authenticated user attempted some action and was denied. Either the authenticated user does not have a Drupal role that grants him/her permission to perform that action, or XACML denied the action for that user.
In general a 404 will occur, when a user tries to perform an action on a object or datastream that doesn't not exist. Or XACML is hiding that object or datastream from the user.
404 Responses can be returned even if the user was not determined to have permission to perform the requested action, as the resource must be first fetched from fedora before the users permission can be determined.
Name | Description |
---|---|
message | A detail description of the error. |
Any problem can trigger a 500 error, but in general you'll find that this is typically an error returned by Fedora.
islandora/rest/v1/object/{pid}
GET
Accept: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object |
Name | Description |
---|---|
pid | Persistent identifier of the requested object |
label | The object’s label |
models | An array of the objects models. |
state | Object’s state, either “A”, “I”, “D” |
owner | The objects owner |
created | Created date of the object, yyyy-MM-ddTHH:mm:ssZ |
modified | Last modified date of the object, yyyy-MM-ddTHH:mm:ssZ |
datastreams | Any array of objects each describing a data stream. See GET datastream for more details. |
{
"pid": "islandora:root",
"label": "Root Object",
"owner": "fedoraAdmin",
"models": ["islandora:collectionCModel"],
"state": "A",
"created": "2013-05-27T09:53:39.286Z",
"modified": "2013-06-24T04:20:26.190Z",
"datastreams": [{
"dsid": "RELS-EXT",
"label": "Fedora Object to Object Relationship Metadata.",
"state": "A",
"size": 1173,
"mimeType": "application\/rdf+xml",
"controlGroup": "X",
"created": "2013-06-23T07:28:32.787Z",
"versionable": true,
"versions": []
}]
}
islandora/rest/v1/object
POST
Accept: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object, if not given the namespace will be used to create a new one (optional). |
label | The label of the new object (optional). |
owner | The owner of the new object, if not given it will be the currently logged in (optional). |
namespace | Used to create a PID for a new empty object if pid is not given (optional). |
Returns the same response as a GET Object request.
islandora/rest/v1/object/{pid}
PUT
Accept: application/json
Content-Type: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object, if not given the namespace will be used to create a new one. |
Name | Description |
---|---|
label | The new label of the object (optional) |
owner | The new owner of the object (optional) |
state | The new state of the object, either “A”, “I”, “D” (optional) |
Only given variables will change the object the others will retain their original values.
Name | Description |
---|---|
pid | Persistent identifier of the requested object |
label | The object’s label |
state | Object’s state, either “A”, “I”, “D” |
owner | The objects owner |
modified | Last modified date of the object, yyyy-MM-ddTHH:mm:ssZ |
islandora/rest/v1/object/{pid}
DELETE
Name | Description |
---|---|
pid | Persistent identifier of the object. |
islandora/rest/v1/object/{pid}/relationship?[predicate][uri][object][literal, false]
GET
Accept: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object. |
predicate | The predicate to limit the results to. (optional) |
uri | The uri of the predicate, required if predicate is present. |
object | The object to limit the results to. (optional) |
literal | True if the object is literal, false otherwise. Defaults to false. (optional) |
A JSON array with each field containing the following values.
Name | Description |
---|---|
predicate | object that describes the predicate |
object | An object that describes the object. |
[{
"predicate": {
"value": "hasModel",
"alias": "fedora-model",
"namespace": "info:fedora/fedora-system:def/model#"
},
"object": {
"literal": false,
"value": "islandora:collectionCModel"
}
}]
islandora/rest/v1/object/{pid}/relationship
POST
Accept: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object. |
Name | Description |
---|---|
uri | The predicate URI for the given predicate. |
predicate | The predicate of the relationship. |
object | Object of the relationship. |
type | The type of the relationship object. Can be either 'uri', 'string', 'int', 'date', 'none'. Defaults to 'uri'. |
islandora/rest/v1/object/{pid}/relationship
DELETE
Content-Type: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object. |
Name | Description |
---|---|
uri | The uri of the predicate, required if predicate is present. |
predicate | The predicate to limit the remove to (optional) |
object | The object to limit the remove to (optional) |
literal | True if the object is literal, false otherwise. Defaults to false (optional) |
islandora/rest/v1/object/{pid}/datastream/{dsid}?[content, true][version]
GET
Accept: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object |
dsid | Data stream Identifier. |
content | True to return the datastream’s content, False to return it’s properties. |
version | The version of the datastream to return, identified by its created date of the datastream in ISO 8601 format yyyy-MM-ddTHH:mm:ssZ (optional) If not given the latest version of the data stream will be returned. |
If content is false these properties are returned. When requesting a specific version of the data stream, these values are limited to a subset described here.
Name | Description |
---|---|
dsid | The datastream's persistent identifier |
label | The datastream's label |
size | The datastream's size in bytes |
state | The datastream’s state, either “A”, “I”, “D” |
mimeType | The datastream’s MIME Type |
controlGroup | The datastream's control group, either X, M, E, R |
versionable | A boolean value if the datastream is versionable |
created | Created date of the datastream, yyyy-MM-ddTHH:mm:ssZ |
checksumType | The checksum type, e.g., SHA-1, MD5. Value is "DISABLED" if checksums are not enabled for the datastream. |
checksum | The checksum value. Value is "none" if no checksum is available. |
versions | Any array of objects each describing each datastream version not including the latest, contains a subset of the fields described here. |
{
"dsid": "RELS-EXT",
"label": "Fedora Object to Object Relationship Metadata.",
"state": "A",
"size": 1173,
"mimeType": "application\/rdf+xml",
"controlGroup": "X",
"created": "2013-06-23T07:28:32.787Z",
"checksumType": "SHA-1",
"checksum": "46dbb3122dc1a140a5f344934251d7c1f680ff28",
"versionable": true,
"versions": [{
"label": "Old Label.",
"state": "A",
"size": "1000",
"mimeType": "application\/rdf+xml",
"controlGroup": "X",
"created": "2013-05-23T06:26:32.787Z"
}]
}
If content is true the datastream’s content is returned, and the appropriate content-type will be set by the server for the datastream’s content.
islandora/rest/v1/object/{pid}/datastream
POST
Accept: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object to add the datastream to. |
Name | Description |
---|---|
dsid | The new datastream's persistent identifier |
label | The new datastream's label (optional) |
state | The new datastream’s state, either “A”, “I”, “D” (optional) Defaults to “A” |
mimeType | The new datastream’s MIME Type (optional) if not provided then it is guessed from the uploaded file. |
checksumType | The new datastream’s checksum type (optional), e.g., SHA-1, MD5. Defaults to 'DISABLED'. |
controlGroup | The new datastream's control group, either X, M, E, R |
versionable | A boolean value if the datastream is versionable (optional) Defaults to true |
multipart file as request content | File to use as the datastream’s content |
Returns the same response as a GET Datastream request.
islandora/rest/v1/object/{pid}/datastream/{dsid}
PUT
Accept: application/json
Content-Type: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object to add the datastream to. |
dsid | The persistent datastream identifier. |
Name | Description |
---|---|
label | The datastream's new label (optional) |
state | The datastream’s new state, either “A”, “I”, “D” (optional) |
mimeType | The new datastream’s MIME Type (optional) if not provided then it is guessed from the uploaded file. |
checksumType | The datastream’s checksum type (optional), e.g., SHA-1, MD5. Defaults to 'DISABLED'. |
versionable | A boolean value if the datastream is versionable (optional) Defaults to true |
multipart file as request content | File to replace existing datastream (for Managed datastreams) |
Returns the same response as a GET Datastream request.
islandora/rest/v1/object/{pid}/datastream/{dsid}
DELETE
Accept: application/json
Name | Description |
---|---|
pid | Persistent identifier of the object, if not given the namespace will be used to create a new one. |
dsid | Data stream Identifier. |
This is a light wrapper for the SOLR own end point. It incorporates XACML alters to restrict the search results for the given user. The Islandora Solr Search 'Search the Solr index' permission is used for authentication instead of any custom permissions from this module.
Because parameters are passed through to Solr carte blanche, invalid requests
may trigger 400 errors. Apache_Solr_Service
does not provide details about the
error in these cases, so a generic message is given.
islandora/rest/v1/solr/{query}
GET
Accept: application/json
Name | Description |
---|---|
query | The SOLR query to execute. |
... | See the SOLR documentation for the additional parameters it can take. |
The result will be unmodified server side since all the query types support the return of JSON directly to the user. So this will more or less just delegate to those respective end points. See the documentation for SOLR for more info.
To ensure all object restrictions are respected on Islandora REST requests, core islandora permissions are mapped in the following way:
Rest Permission Name | Islandora Core Permission |
---|---|
ISLANDORA_REST_OBJECT_GET_PERM | ISLANDORA_VIEW_OBJECTS |
ISLANDORA_REST_OBJECT_PUT_PERM | ISLANDORA_MANAGE_PROPERTIES |
ISLANDORA_REST_OBJECT_POST_PERM | ISLANDORA_INGEST |
ISLANDORA_REST_OBJECT_DELETE_PERM | ISLANDORA_PURGE |
ISLANDORA_REST_DATASTREAM_GET_PERM | ISLANDORA_VIEW_OBJECTS |
ISLANDORA_REST_DATASTREAM_PUT_PERM | ISLANDORA_METADATA_EDIT |
ISLANDORA_REST_DATASTREAM_POST_PERM | ISLANDORA_ADD_DS |
ISLANDORA_REST_DATASTREAM_DELETE_PERM | ISLANDORA_PURGE |
ISLANDORA_REST_DATASTREAM_TOKEN_GET_PERM | ISLANDORA_VIEW_OBJECTS |
ISLANDORA_REST_RELATIONSHIP_GET_PERM | ISLANDORA_VIEW_OBJECTS |
ISLANDORA_REST_RELATIONSHIP_POST_PERM | ISLANDORA_METADATA_EDIT |
ISLANDORA_REST_RELATIONSHIP_DELETE_PERM | ISLANDORA_PURGE |
- mjordan/irc: PHP/Guzzle library for creating Islandora REST clients
- SFULibrary/islandora_rest_ingester CLI Ingestor using the above
- kulibraries/islandora7-rest Python client library for Islandora REST
- Update Solution Packs to use datastream ingested/modified hooks rather than object ingested hooks.
- Move DC transform logic out of XML Forms and have it use ingested/modified hooks instead.
- Add support for purging previous versions of datastreams
- Add checksum support to datastream end-points.
- Add describe json end-point for the repository.
- Make PUT requests support multi-part form data, populate $_FILES.
- Investigate a making a jQuery plugin to ease interaction with REST API?