JavaScript and Drupal 8 RESTful Web Services

Last updated on
24 April 2017

This page aims to outline how to use JavaScript to communicate with Drupal 8's RESTful services. It is broken into sections per entity type.

It outlines:

  1. which HTTP method to use (GET, POST, PATCH, or DELETE) on which URL
  2. which headers to send
  3. what data to send, if any
  4. what response can be expected from the server

For the following entity types:

Getting started

See Getting started: REST configuration & REST request fundamentals. Please read that first!

Users

Login

POST: https://example.com/user/login?_format=json
Content-type: application/json

{
"name": "admin",
"pass": "password"
}

200 OK

Logout

  1. GET http://example.com/user/logout
  2. Content-type: text/html
  3. 200 - OK

Retrieve

  1. GET http://example.com/user/1?_format=json
  2. None
  3. 200 - OK

Register

POST: https://example.com/user/register?_format=json
Content-type: application/json

{
"name": { "value": "fooBar" },
"mail": { "value": "foo@bar.com" },
"pass": { "value": "secretSauce" }
}

200 OK

Nodes

Create

POST: http://example.com/entity/node
Content-type: application/json

{
  "type":[{"target_id":"article"}],
  "title":[{"value":"Hello World"}],
  "body":[{"value":"How are you?"}]
}

201 - Created

For setting the value of an entity reference field referencing another entity type, all you need is it's uuid:

"_embedded": {
"https://example.com/rest/relation/node/article/my_entity_reference_field":
  [{ 
  "uuid":[{"value":"yourUUID-xxx-xxxx-xxxx-xxxxxxxxx"}]
  }]
}

Retrieve

GET: http://example.com/node/123?_format=json
Content-type: *
Accept: application/json
200 - OK

Update

PATCH: http://example.com/node/123
Content-type: application/json

{
  "nid":[{"value":"123"}],
  "type":[{"target_id":"article"}],
  "title":[{"value":"Goodbye World"}]
}

204 - No Content

Delete

DELETE: http://example.com/node/123
Content-type: *
{"type":[{"target_id":"article"}]}
204 - No Content

Comments

Create

POST: http://example.com/entity/comment
Content-type: application/json

{
  "entity_id":[{"target_id":123}],
  "entity_type":[{"value":"node"}],
  "comment_type":[{"target_id":"comment"}],
  "field_name":[{"value":"comment"}],
  "subject":[{"value":"Goodbye World"}],
  "comment_body":[
    {"value":"<p>See you later!</p>","format":"basic_html"}
  ]
}

201 - Created

Retrieve

GET: http://example.com/comment/456?_format=json
200 - OK

Update

#2631774: Impossible to update Comment entity with REST (HTTP PATCH): bundle field not allowed to be updated, but EntityNormalizer::denormalize() requires it

Delete

DELETE: http://example.com/comment/456
Content-type: *
{"comment_type":[{"target_id":"comment"}]}
204 - No Content

Vocabularies

In D8, vocabularies are "Configuration Entities" and are not yet supported by core's REST. For starters, some folks are working towards GET as a minimum: #2300677: Create/Update/Delete (POST/PATCH/DELETE) ConfigEntity via REST

Taxonomy Terms

Code Examples: RESTful Drupal 8 CRUD Example using jQuery and core REST module

CREATE Item

var package = {}
package.title = [{'value':'t1'}]
package.body = [{'value':'b1'}]
package._links = {"type":{"href":"http://local.drupal8.org/rest/type/node/page"}}

$.ajax({
  url: "http://example.com/entity/node",
  method: "POST",
  data: JSON.stringify(package),
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/hal+json"
  },
  success: function(data, status, xhr) {
    debugger
  }
})

GET Item

$.ajax({
  url: "http://example.com/node/3?_format=hal_json",
  method: "GET",
  headers: {
    "Content-Type": "application/hal+json"
  },
  success: function(data, status, xhr) {
    debugger
  }
})

GET an Item and then UPDATE Item

$.ajax({
  url: "http://example.com/node/3?_format=hal_json",
  method: "GET",
  headers: {
    "Content-Type": "application/hal+json"
  },
  success: function(data, status, xhr) {
    var package = {}
    package.title = data.title
    package.body = data.body
    package.title[0].value = 'yar'
    package._links = {"type":{"href":"http://example.com/rest/type/node/page"}}
    debugger

    $.ajax({
      url: "http://example.com/node/3",
      method: "PATCH",
      data: JSON.stringify(package),
      headers: {
        "X-CSRF-Token": "niCxgd5ZZG25YepbYtckCy7Q2_GL2SvMUY5PINxRAHw",
        "Accept": "application/json",
        "Content-Type": "application/hal+json"
      },
      success: function(data, status, xhr) {
        debugger
      }
    })

  }
})

DELETE Item

$.ajax({
  url: "http://example.com/node/3",
  method: "DELETE",
  headers: {
    "Accept": "application/json",
    "Content-Type": "application/hal+json"
  },
  success: function(data, status, xhr) {
    debugger
  }
})

Results are Automatically Cached from GET Requests

While developing, it's important to understand that when you make a GET request to D8 Rest, Drupal will cache the result so subsequent requests receive a speedy response. You can either clear all of Drupal's caches to get the new results, or append a timestamp to the URL query string:

node/123?_format=json&time=123456789

Or if you've created a custom resource, use addCacheableDependency() on the ResourceResponse:

$response = new ResourceResponse(array('hello' => 'world'));
$response->addCacheableDependency($account);
return $response;

Resources and Modules