Skip to content

1.2. Defining a resource plugin (2.x)

jeff-h edited this page Oct 3, 2016 · 11 revisions

For a video tutorial covering the basics, see 4. Writing the first resource on Youtube.

From here down we assume you have viewed the above and understand the basics. Also, we'll assume you now have a new class file with the appropriate filename and location in your filesystem.

Note: You will need to flush caches once or twice after defining your plugin before Drupal will fully recognise it.

Annotations

The resource definition introduces something that may be new to the Drupal 7 developer—the Drupal 8/Symfony-style "annotation". This is essentially a bunch of comments preceding the class, which are actually read by the plugin system (in this case the plug.module) in order to learn all about the class.

Example Annotation:

e.g.

/**
  * Class Articles
  * @package Drupal\restful\Plugin\resource
  *
  * @Resource(
  *   name = "articles:1.1",
  *   resource = "articles",
  *   label = "Articles",
  *   description = "Export the article content type.",
  *   authenticationOptional = TRUE,
  *   dataProvider = {
  *     "entityType": "node",
  *     "bundles": {
  *       "article"
  *     },
  *   },
  *   majorVersion = 1,
  *   minorVersion = 1
  * )
  */

A note about version numbers.

In general a good rule of thumb is that if you are inheriting from an old resource, you bump up the minor version. If you are not, then bump up the major version.

If you're extending a resource that RESTful provides out-of-the-box (e.g. users) but you haven't incremented your version number, RESTful may not see your resource, instead using the default one. e.g. if you're extending RESTful's users v1.0, be sure to call yours users v1.1 or higher.

Full Example

In the file /casa_rest/src/Plugin/resource/pictures/v0_1/Pictures__0_1.php:

<?php
/**
 * @file
 * Contains \Drupal\casa_rest\Plugin\resource\pictures\v0_1\Pictures__0_1.
 */

namespace Drupal\casa_rest\Plugin\resource\pictures\v0_1;

use Drupal\restful\Plugin\resource\ResourceInterface;
use Drupal\restful\Plugin\resource\ResourceNode;

/**
 * Class Pictures
 * @package Drupal\casa_rest\Plugin\resource\pictures\v0_1
 *
 * @Resource(
 *   name = "pictures:0.1",
 *   resource = "pictures",
 *   label = "Pictures",
 *   description = "A RESTful service resource exposing pictures.",
 *   authenticationTypes = {
 *     "token"
 *   },
 *   authenticationOptional = TRUE,
 *   dataProvider = {
 *     "entityType": "node",
 *     "bundles": {
 *       "picture"
 *     },
 *   },
 *   majorVersion = 0,
 *   minorVersion = 1
 * )
 */
class Pictures__0_1 extends ResourceNode implements ResourceInterface {

  /**
   * Overrides ResourceEntity::publicFieldsInfo().
   */
  protected function publicFields() {
    $fields = parent::publicFields();

    $fields['owner'] => array(
      'property' => 'author',
      'sub_property' => 'uid',
    );

    return $fields;
  }
}

Plugin definition properties

See Resource plugin definition properties (for 2.x).

Note the new plugin definition property for 2.x: menuItem: Defines the endpoint path, similar to an alias. Eg. menuItem = "session/token"

Authentication

If you need your endpoint to be protected by authentication, you must specify the authentication_types key. Either specify an array of auth types, or TRUE for any.

 *   authentication_types => TRUE, // Try to authenticate users with all available authentication types.

or

 *   authenticationTypes = {
 *     "token"
 *   },

A word of caution

If you want to use one specific authentication type, don't use authentication_types => TRUE. Under certain circumstances the browser may end up sending a cookie with the request, and if you're not intentionally using cookie auth, you are likely not providing the CSRF token that cookie auth requires for write operations.

Example scenarios where this problem could arise:

  • when the client is a Javascript app served from the same domain as the Drupal REST server; in this scenario, if the user ever logs into the Drupal instance, they will gain an auth cookie which will be sent by the browser with every RESTful request your client app makes.
  • when the client is a Javascript app served from a different domain to the Drupal REST server but you are using a CORS alternative such as XDomain; in this case, your client app's requests appear to Drupal as though they originated via the Drupal instance's domain, and if there's a Drupal cookie for that domain it will be sent with the request.

If a Drupal auth cookie is inadvertently sent with the request it will either fail to authenticate, in which case RESTful will move onto any other provided auth mechanisms, or it may succeed. If it succeeds, you may end up with a BadRequestException No CSRF token passed in the HTTP header. because although the cookie auth succeeded, you need to send a CSRF token if you intend to use cookie auth (for write OPs).

Clone this wiki locally