This module allows Drupal to be operated via RESTful HTTP requests, using best practices for security, performance, and usability.
These are the differences between RESTful and other modules, such as RestWs and Services Entity:
- RESTful requires explicitly declaring the exposed API. When enabling the module, nothing happens until a plugin declares it.
- Resources are exposed by bundle, rather than by entity. This would allow a developer to expose only nodes of a certain type, for example.
- The exposed properties need to be explicitly declared. This allows a clean
output without Drupal's internal implementation leaking out. This means the
consuming client doesn't need to know if an entity is a node or a term, nor will
they be presented with the
field_
prefix. - Resource versioning is built-in, so that resources can be reused with multiple consumers. The versions are at the resource level, for more flexibility and control.
- It has configurable output formats. It ships with JSON (the default one), JSON+HAL and as an example also XML.
- Audience is developers and not site builders.
- Provide a key tool for a headless Drupal. See the AngularJs form example module.
- Entity API, with the following patch:
- Prevent notice in entity_metadata_no_hook_node_access() when node is not saved
Read even more examples on how to use the RESTful module in the module documentation node in Drupal.org. Make sure you read the Recipes section. If you have any to share, feel free to add your own recipes.
A RESTful endpoint is declared via a custom module that includes a plugin which describes the resource you want to make available. Here are the bare essentials from one of the multiple examples in the example module:
####restful_custom/restful_custom.info
name = RESTful custom
description = Custom RESTful resource.
core = 7.x
dependencies[] = restful
####restful_custom/restful_custom.module
/**
* Implements hook_ctools_plugin_directory().
*/
function restful_custom_ctools_plugin_directory($module, $plugin) {
if ($module == 'restful') {
return 'plugins/' . $plugin;
}
}
####restful_custom/plugins/restful/articles.inc
$plugin = array(
'label' => t('Articles'),
'resource' => 'articles',
'name' => 'articles',
'entity_type' => 'node',
'bundle' => 'article',
'description' => t('Export the article content type.'),
'class' => 'RestfulCustomResource',
);
The resource
key determines the root URL of the resource. The name
key must match
the filename of the plugin: in this case, the name is articles
, and therefore, the
filename is articles.inc
.
####restful_custom/plugins/restful/RestfulCustomResource.class.php
class RestfulCustomResource extends RestfulEntityBaseNode {
/**
* Overrides RestfulEntityBaseNode::publicFieldsInfo().
*/
public function publicFieldsInfo() {
$public_fields = parent::publicFieldsInfo();
$public_fields['body'] = array(
'property' => 'body',
'sub_property' => 'value',
);
return $public_fields;
}
}
After declaring this plugin, the resource could be accessed at its root URL,
which would be http://example.com/api/v1.0/articles
.
See the Defining a RESTful Plugin document for more details.
The following examples use the articles resource from the restful_example module.
// Get handler v1.0
$handler = restful_get_restful_handler('articles');
// Get handler v1.1
$handler = restful_get_restful_handler('articles', 1, 1);
$handler = restful_get_restful_handler('articles');
// POST method, to create.
$result = $handler->post('', array('label' => 'example title'));
$id = $result['id'];
// PATCH method to update only the title.
$request['label'] = 'new title';
$handler->patch($id, $request);
$handler = restful_get_restful_handler('articles');
$result = $handler->get();
// Output:
array(
'data' => array(
array(
'id' => 1,
'label' => 'example title',
'self' => 'https://example.com/node/1',
);
array(
'id' => 2,
'label' => 'another title',
'self' => 'https://example.com/node/2',
);
),
);
See the Using your API within drupal documentation for more details.
The following examples use the articles resource from the restful_example module.
# Handler v1.0
curl https://example.com/api/articles/1 \
-H "X-API-Version: v1.0"
# or
curl https://example.com/api/v1.0/articles/1
# Handler v1.1
curl https://example.com/api/articles/1 \
-H "X-API-Version: v1.1"
# or
curl https://example.com/api/v1.1/articles/1
# Handler v1.1
curl https://example.com/api/articles/1,2 \
-H "X-API-Version: v1.1"
curl https://example.com/api/articles?autocomplete[string]=mystring
See the Consuming Your API document for more details.
Clients can access documentation about a resource by making an OPTIONS
HTTP
request to its root URL. The resource will respond with the field information
in the body, and the information about the available output formats and the
permitted HTTP methods will be contained in the headers.
If your resource is an entity, then it will be partially self-documented, without you needing to do anything else. This information is automatically derived from the Entity API and Field API.
Here is a snippet from a typical JSON response using only the automatic documentation:
{
"myfield": {
"info": {
"label": "My Field",
"description": "A field within my resource."
},
"data": {
"type": "string",
"read_only": false,
"cardinality": 1,
"required": false
},
"form_element": {
"type": "textfield",
"default_value": "",
"placeholder": "",
"size": 255,
"allowed_values": null
}
}
// { ... other fields would follow ... }
}
Each field you've defined in publicFieldsInfo
will output an object similar
to the one listed above.
In addition to the automatic documentation provided to you out of the box, you have the ability to manually document your resources. See the Documenting your API documentation for more details.
- Entity validator: Integrate with a robust entity validation