Headless Drupal 8 #HeadlessDrupal
Ruben Teijeiro @rteijeiro
A little bit of history
Drupal 7 Front-end Sucks!
DIVITIS
Contrib Helps
"The front-end moves faster than Drupal, whether Drupal likes it or not" @eatings
Mobile Web/Apps
Browserless Devices
Internet of Things
Drupal8
Loosely Coupled Architecture
Drupal 8 Front-end is @mortendk Certified
I love Twig!! WTF!!
Big Pipe
Accessibility
Translations
Security
Solution
Monolithic Application
Microservices
Decoupling
Fully Decoupled Vs Progressively Decoupled
Headless Drupal The Cake is a Lie! @thefubhy
@thefubhy No, I don't have a better profile picture
Headless Drupal 8
We don't need contrib anymoar!!
Headless Drupal 8 REST modules are in Core
Don't forget the permissions
CRUD Create Read Update Delete
Sample Create Request curl --include --request POST --user user:password --header 'Content-type: application/hal+json' http://localhost/drupal8/entity/node --data-binary '{"_links":{"type": {"href":"http://localhost/drupal8/rest/type/nod e/page"}}, "title":[{"value":"node created using curl"}], "body": [{"value":"this is the body of the node created using curl"}]}'
Sample Create Response HTTP/1.1 201 Created Date: Fri, 24 Oct 2014 10:26:50 GMT Server: Apache/2.2.22 (Debian) X-Powered-By: PHP/5.4.33-1~dotdeb.1 Location: http://localhost/drupal8/entity/node/2
CRUD Create Read Update Delete
Sample Read Request curl -H "Accept:application/hal+json" --request GET http://localhost/drupal8/node/1? _format=hal_json
Sample Read Response {"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/node\/2"},"type": {"href":"http:\/\/localhost\/drupal8\/rest\/type\/node\/page"},"http:\/\/local host\/drupal8\/rest\/relation\/node\/page\/uid": [{"href":"http:\/\/localhost\/drupal8\/user\/1","lang":"en"}],"http:\/\/localh ost\/drupal8\/rest\/relation\/node\/page\/revision_uid": [{"href":"http:\/\/localhost\/drupal8\/user\/1"}]},"uuid":[{"value":"f89b04b9b2b2-4230-8e5c-92fb3856213d"}],"type":[{"target_id":"page"}],"langcode": [{"value":"en"}],"title":[{"value":"node updated using curl","lang":"en"}],"_embedded": {"http:\/\/localhost\/drupal8\/rest\/relation\/node\/page\/uid":[{"_links": {"self":{"href":"http:\/\/localhost\/drupal8\/user\/1"},"type": {"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid": [{"value":"b3e6e828-03fa-4a19-a7066bba6f47edc4"}],"lang":"en"}],"http:\/\/localhost\/drupal8\/rest\/relation\/no de\/page\/revision_uid":[{"_links":{"self": {"href":"http:\/\/localhost\/drupal8\/user\/1"},"type": {"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid": [{"value":"b3e6e828-03fa-4a19-a706-6bba6f47edc4"}]}]},"status": [{"value":"1","lang":"en"}],"created": [{"value":"1414146410","lang":"en"}],"changed": [{"value":"1414147433","lang":"en"}],"promote": [{"value":"0","lang":"en"}],"sticky": [{"value":"0","lang":"en"}],"revision_timestamp": [{"value":"1414146410"}],"body":[{"value":"this is the body of the node updated using curl","format":null,"summary":null,"lang":"en"}]}
CRUD Create Read Update Delete
Sample Update Request curl --include --request PATCH --user user:password --header 'Content-type: application/hal+json' http://localhost/drupal8/node/2 --data-binary '{"_links":{"type": {"href":"http://localhost/drupal8/rest/type/nod e/page"}}, "title":[{"value":"node updated using curl"}], "body": [{"value":"this is the body of the node updated using curl"}]}'
Sample Update Response HTTP/1.1 204 No Content Date: Fri, 24 Oct 2014 10:43:53 GMT Server: Apache/2.2.22 (Debian) X-Powered-By: PHP/5.4.33-1~dotdeb.1
CRUD Create Read Update Delete
Sample Delete Request curl --include --request DELETE --user user:password --header 'Content-type: application/hal+json' http://localhost/drupal8/node/2
Sample Delete Response HTTP/1.1 204 No Content Date: Fri, 24 Oct 2014 10:51:04 GMT Server: Apache/2.2.22 (Debian) X-Powered-By: PHP/5.4.33-1~dotdeb.1
Views are in Core too!!
Thanks @pfrenssen for https://www.drupal.org/node/2317085
REST export
REST export settings
Sample Request curl -H "Accept:application/hal+json" --request GET http://localhost/drupal8/node/rest
Sample Response [{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/node\/1"},"type": {"href":"http:\/\/localhost\/drupal8\/rest\/type\/node\/article"},"http:\/\/localhost\/drupal8 \/rest\/relation\/node\/article\/uid": [{"href":"http:\/\/localhost\/drupal8\/user\/1","lang":"en"}],"http:\/\/localhost\/drupal8\/re st\/relation\/node\/article\/revision_uid": [{"href":"http:\/\/localhost\/drupal8\/user\/1"}]},"uuid":[{"value":"5fad49bf-5c70-475d-933351c25caf62d5"}],"type":[{"target_id":"article"}],"langcode":[{"value":"en"}],"title": [{"value":"you don't get sick, I do","lang":"en"}],"_embedded": {"http:\/\/localhost\/drupal8\/rest\/relation\/node\/article\/uid":[{"_links":{"self": {"href":"http:\/\/localhost\/drupal8\/user\/1"},"type": {"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid":[{"value":"b3e6e82803fa-4a19-a7066bba6f47edc4"}],"lang":"en"}],"http:\/\/localhost\/drupal8\/rest\/relation\/node\/article\/rev ision_uid":[{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/user\/1"},"type": {"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid":[{"value":"b3e6e82803fa-4a19-a706-6bba6f47edc4"}]}]},"status":[{"value":"1","lang":"en"}],"created": [{"value":"1413657929","lang":"en"}],"changed":[{"value":"1413657957","lang":"en"}],"promote": [{"value":"1","lang":"en"}],"sticky":[{"value":"0","lang":"en"}],"revision_timestamp": [{"value":"1413657929"}],"revision_log":[{"value":"","lang":"en"}],"body":[{"value":"<p>your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.<\/p>\r\n","format":"basic_html","summary":"","lang":"en"}],"comment": [{"status":"2","cid":"0","last_comment_timestamp":"1413657957","last_comment_name":null,"last_ comment_uid":"1","comment_count":"0","lang":"en"}]}]
vs HAL JSON
Use HAL if you care about API definition { "_links": { "self": { "href": "/your-api-links" } }, "_embedded": { "items": [ Array of serialized items ] } }
Use JSON if you only care about the content [ { "title": This is your content title, "body": This is your content body. } ]
How to enable JSON requests
core/modules/rest/config/install/rest.settings.yml resources: entity:node: GET: supported_formats: - hal_json supported_auth: - basic_auth POST: supported_formats: - hal_json supported_auth: - basic_auth PATCH: supported_formats: - hal_json supported_auth: - basic_auth DELETE: supported_formats: - hal_json supported_auth: - basic_auth
Configuration Management Single Import
https://www.drupal.org/project/restui
Sample JSON Request curl -H "Accept: application/json" --request GET http://localhost/drupal8/node/rest
Sample JSON Response [{"nid":[{"value":"1"}],"uuid":[{"value":"5fad49bf-5c70-475d-933351c25caf62d5"}],"vid":[{"value":"1"}],"type": [{"target_id":"article"}],"langcode":[{"value":"en"}],"title": [{"value":"you don't get sick, I do"}],"uid": [{"target_id":"1"}],"status":[{"value":"1"}],"created": [{"value":"1413657929"}],"changed":[{"value":"1413657957"}],"promote": [{"value":"1"}],"sticky":[{"value":"0"}],"revision_timestamp": [{"value":"1413657929"}],"revision_uid": [{"target_id":"1"}],"revision_log":[{"value":""}],"path": [{"alias":null,"pid":null}],"body":[{"value":"<p>your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.<\/p>\r\n","format":"basic_html","summary":""}],"comment": [{"status":"2","cid":"0","last_comment_timestamp":"1413657957","last_com ment_name":null,"last_comment_uid":"1","comment_count":"0"}],"field_imag e": [{"target_id":null,"display":null,"description":null,"alt":null,"title": null,"width":null,"height":null}],"field_tags":[{"target_id":null}]}]
BEWARE!! hal_json is the only format supported for POST and PATCH methods It needs work: https://www.drupal.org/node/1964034
Getting a cleaner JSON response
Use Fields in View
Fields Raw Format
Clean JSON Response [ { "title":"you don't get sick, I do", "body":"<p>your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.<\/p>" } ]
Resources https://github.com/gizra/generator-hedley https://github.com/restful-drupal/restful https://github.com/amitaibu/restful-blessed https://groups.drupal.org/headless-drupal http://blog.loadimpact.com/blog/headless-drupal-8-retrieving-contentusing-backbone-js/ http://blog.loadimpact.com/blog/first-steps-with-crud-using-backbonejs-and-drupal-8/
Don't miss
Want to contribute? [meta] REST et al How to POST a comment and other relational entities Add special handling for collections in REST Support ConfigEntity via REST File needs CRUD permissions to make REST work on entity/file/{id} Serialize file content (base64) to support REST GET/POST/PATCH on file entity
Join the Code Sprints!!
? Questions?
Thanks!