HTTP ALL THE THINGS
Simplifying Rich Applications by
Respecting the Rules of the Web
Me
Nate Abele
Former lead developer, CakePHP
Founder & current lead developer, Lithium
Member, AngularUI
@nateabele
History
1998: SOAP & XMLRPC
SOAP
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header></soap:Header...
Or...
XML-RPC
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>40</...
:-(
POST *
Invocaction details in body
Format lock-in
No relationships
No discoverability
2000: REST
REST Constraints
Client-Server
Stateless
Cacheable
Uniform Interface
Opaque Layering
Code-on-Demand
The 4 Levels
RPC over HTTP (i.e. SOAP)
Resources
Verbs
Hypermedia Controls
Now: Hypermedia /
HATEOAS
¿Hypermedia?
Content negotiation
State traversal
Content negotiation
application/json ...?
Content negotiation
application/json
FALE
Content negotiation
Better:
application/rss+xml
Content negotiation
application/vnd.twitter.stream+json
// I can decode this!
json_decode()

/**
* I can understand this
!...
State traversal
Client: “What's next?”
We already do this!
Browsers
<link rel="stylesheet" href="/css/app.css" />
<link rel="next" href="/next" />
<link
rel="alternate"
type="applic...
Users

(with the help of browsers)
<a href="/next" />Next</a>
<form></form>
Atom?
<link
rel="foo"
type="text/foo"
href="http://foo"
/>
JSON!
[{
title: "Finish the demo",
completed: false,
$links: {
self: { href: "http://my.app/tasks/1138" },
owner: { href: ...
Why?
AngularJS
Valid alternatives
EmberJS
KnockoutJS
Backbone (kind of, not really)
AngularJS
Higher level of abstraction
Simple, well-designed architecture
Ridiculously simple unit testing
Event binding
Event binding
jQuery

<input type="text" id="name" />
<h1>Hello!</h1>
<script type="text/javascript">
$(document).ready(fu...
Event binding
AngularJS

<input type="text" ng-model="name" />
<h1>Hello {{ name }}!</h1>

Hello !
Iteration
jQuery

<ul class="greetings"></ul>
<script type="text/javascript">
$(["Hello", "Hola", "Ciao"]).each(function(k...
Iteration
AngularJS

<ul>
<li ng-repeat="greet in ['Hello', 'Hola', 'Ciao']">
{{ greet }} World
</li>
</ul>

Hello World
H...
<ul>
<li ng-repeat="greet in ['Hello', 'Hola', 'Ciao']">
{{ greet }} World
</li>
</ul>

Hello World
Hola World
Ciao World
Organization
AngularJS

Item:

Qty: 0

Price: 0

Total: $0.00

Total: $0.00
Organization
AngularJS

<div ng-controller="CheckoutController">
<div ng-repeat="item in items">
Item: <input type="text" ...
Organization
AngularJS

function CheckoutController($scope) {
$scope.items = $scope.items || [{ price: 0, qty: 0 }];
$scop...
Organization
jQuery

¿Ummm...?
Organization
jQuery
*shrug*
Testability
AngularJS

describe("Shopping cart", function() {
describe("Checkout widget", function() {
it("should create a...
Testability
AngularJS

describe("Shopping cart", function() {
describe("Checkout widget", function() {
// ...
it("should c...
¿jQuery...?
AngularJS + HTTP
Resources
$resource()
var Task = $resource("http://my.api/tasks/:id", {
id: "@id"
});
var newTask = new Task({
title: "New Task",
description: "...
/* GET /tasks/5 */
var oneTask = Task.get({ id: 5 });
/* GET /tasks?completed=false&due=1381158984 */
var current = Task.q...
¡Muy mal!
¡No me gusta!
¡Eso es shinaniganos!
Tight coupling
Client-side URL templates
Excessive parameters
No links!
Intent
/tasks?
completed=false
&due=1381158984
No meaning
/tasks/current
/tasks/:id
$resource("/posts/:id", {id:
"@id"});
{
id: 5,
title: "Something New",
slug: "something-new"
}
/posts/something-new
...?
What to do?
uor/angular-model
(on GitHub) *

* Current code is old and broken, new release coming tomorrow
modelProvider.model("Tasks", {
$instance: {
finish: function() {
this.completed = true;
return this.$save();
},
isComplete...
Where's the URL?
3 options
Automatic: /tasks
<link
rel="resource"
name="Tasks"
href="<?=$this->url('Tasks'); ?>"
/>
GET /
Accept:
application/vnd.resource-def+json
{
"Tasks": "http://my.app/tasks",
"Users": "http://my.app/users"
}
OPTIONS /tasks
Accept:
application/vnd.resourceschema+json
{
"title": "string",
"completed": "boolean",
...
}
More HTTP goodies
...that you don't need to
reinvent
HTTP Range
GET /rickroll.mp4
Range: bytes=10099999
HEAD /posts HTTP/1.1
...
HTTP 200 OK
Accept-Ranges: posts
GET /posts HTTP/1.1
Range: posts=1-20
HTTP Auth

Always use protection!
Caching

Implement any invalidation
strategy you can imagine
PHP?
nateabele/li3_resour
ces
(on GitHub)
Automatic CRUD manipulation with verbs
Parameter mapping
Links from model relationships
Schemas with OPTIONS
Proxies for m...
Coming soon...
Range pagination
Smart search with ?q=...
...Tests (runs away)
Thanks!
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando las reglas de la Web
Upcoming SlideShare
Loading in …5
×

2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando las reglas de la Web

4,289 views

Published on

PHP Conference Argentina 2013

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
4,289
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando las reglas de la Web

  1. 1. HTTP ALL THE THINGS Simplifying Rich Applications by Respecting the Rules of the Web
  2. 2. Me Nate Abele Former lead developer, CakePHP Founder & current lead developer, Lithium Member, AngularUI @nateabele
  3. 3. History
  4. 4. 1998: SOAP & XMLRPC
  5. 5. SOAP <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Header></soap:Header> <soap:Body> <m:SomeCommand xmlns:m="..."> <m:BodyOfMessage>...</m:BodyOfMessage> </m:SomeCommand> </soap:Body> </soap:Envelope>
  6. 6. Or...
  7. 7. XML-RPC <?xml version="1.0"?> <methodCall> <methodName>examples.getStateName</methodName> <params> <param> <value><i4>40</i4></value> </param> </params> </methodCall>
  8. 8. :-( POST * Invocaction details in body Format lock-in No relationships No discoverability
  9. 9. 2000: REST
  10. 10. REST Constraints Client-Server Stateless Cacheable Uniform Interface Opaque Layering Code-on-Demand
  11. 11. The 4 Levels RPC over HTTP (i.e. SOAP) Resources Verbs Hypermedia Controls
  12. 12. Now: Hypermedia / HATEOAS
  13. 13. ¿Hypermedia? Content negotiation State traversal
  14. 14. Content negotiation application/json ...?
  15. 15. Content negotiation application/json FALE
  16. 16. Content negotiation Better: application/rss+xml
  17. 17. Content negotiation application/vnd.twitter.stream+json // I can decode this! json_decode() /** * I can understand this ! */ class Tweet { protected $username; protected $text; // ... }
  18. 18. State traversal
  19. 19. Client: “What's next?”
  20. 20. We already do this!
  21. 21. Browsers <link rel="stylesheet" href="/css/app.css" /> <link rel="next" href="/next" /> <link rel="alternate" type="application/rss+xml" href="/posts.rss" />
  22. 22. Users (with the help of browsers) <a href="/next" />Next</a> <form></form>
  23. 23. Atom? <link rel="foo" type="text/foo" href="http://foo" />
  24. 24. JSON! [{ title: "Finish the demo", completed: false, $links: { self: { href: "http://my.app/tasks/1138" }, owner: { href: "http://my.app/users/nate" }, subtasks: { href: "http://my.app/tasks/1138/subtasks"} } }]
  25. 25. Why?
  26. 26. AngularJS
  27. 27. Valid alternatives EmberJS KnockoutJS Backbone (kind of, not really)
  28. 28. AngularJS Higher level of abstraction Simple, well-designed architecture Ridiculously simple unit testing
  29. 29. Event binding
  30. 30. Event binding jQuery <input type="text" id="name" /> <h1>Hello!</h1> <script type="text/javascript"> $(document).ready(function() { $('#name').keydown(function(e) { $('h1').html("Hello " + e.target.value + "!") }); }); </script>
  31. 31. Event binding AngularJS <input type="text" ng-model="name" /> <h1>Hello {{ name }}!</h1> Hello !
  32. 32. Iteration jQuery <ul class="greetings"></ul> <script type="text/javascript"> $(["Hello", "Hola", "Ciao"]).each(function(k, v) { $(".greeting").append("<li>" + v + " World</li>" }); </script>
  33. 33. Iteration AngularJS <ul> <li ng-repeat="greet in ['Hello', 'Hola', 'Ciao']"> {{ greet }} World </li> </ul> Hello World Hola World Ciao World
  34. 34. <ul> <li ng-repeat="greet in ['Hello', 'Hola', 'Ciao']"> {{ greet }} World </li> </ul> Hello World Hola World Ciao World
  35. 35. Organization AngularJS Item: Qty: 0 Price: 0 Total: $0.00 Total: $0.00
  36. 36. Organization AngularJS <div ng-controller="CheckoutController"> <div ng-repeat="item in items"> Item: <input type="text" ng-model="item.name"> Qty: <input type="number" ng-model="item.qty"> Price: <input type="number" ng-model="item.price"> Total: <div class="total"> {{ item.qty * item.price | currency: "$" }} </div> </div> <hr> <div>Total: {{ total() | currency: "$" }}</div> </div>
  37. 37. Organization AngularJS function CheckoutController($scope) { $scope.items = $scope.items || [{ price: 0, qty: 0 }]; $scope.total = function() { if ($scope.items[$scope.items.length - 1].qty) { $scope.items.push({ price: 0, qty: 0 }); } return $scope.items.map(function(item) { return item.qty * item.price; }).reduce(function(a, b) { return a + b; }); }; }
  38. 38. Organization jQuery ¿Ummm...?
  39. 39. Organization jQuery *shrug*
  40. 40. Testability AngularJS describe("Shopping cart", function() { describe("Checkout widget", function() { it("should create a default element", function() { var scope = {}, controller = new CheckoutController(scope); expect(scope.items.length).toBe(1); expect(scope.items[0].qty).toBe(0); expect(scope.items[0].price).toBe(0); }); }); });
  41. 41. Testability AngularJS describe("Shopping cart", function() { describe("Checkout widget", function() { // ... it("should calculate order total", function() { var scope = { items: [ { price: 2, qty: 4 }, { price: 10, qty: 1 } ]}; var controller = new CheckoutController(scope); expect(scope.total()).toBe(18); }); }); });
  42. 42. ¿jQuery...?
  43. 43. AngularJS + HTTP Resources
  44. 44. $resource()
  45. 45. var Task = $resource("http://my.api/tasks/:id", { id: "@id" }); var newTask = new Task({ title: "New Task", description: "..." }); /* POST /tasks { "title": "New Task", ... } */ newPost.$save();
  46. 46. /* GET /tasks/5 */ var oneTask = Task.get({ id: 5 }); /* GET /tasks?completed=false&due=1381158984 */ var current = Task.query({ completed: false, description: "..." });
  47. 47. ¡Muy mal! ¡No me gusta! ¡Eso es shinaniganos!
  48. 48. Tight coupling Client-side URL templates Excessive parameters No links!
  49. 49. Intent
  50. 50. /tasks? completed=false &due=1381158984
  51. 51. No meaning
  52. 52. /tasks/current
  53. 53. /tasks/:id
  54. 54. $resource("/posts/:id", {id: "@id"}); { id: 5, title: "Something New", slug: "something-new" }
  55. 55. /posts/something-new ...?
  56. 56. What to do?
  57. 57. uor/angular-model (on GitHub) * * Current code is old and broken, new release coming tomorrow
  58. 58. modelProvider.model("Tasks", { $instance: { finish: function() { this.completed = true; return this.$save(); }, isCompleted: function() { return !!this.completed; } } });
  59. 59. Where's the URL?
  60. 60. 3 options
  61. 61. Automatic: /tasks
  62. 62. <link rel="resource" name="Tasks" href="<?=$this->url('Tasks'); ?>" />
  63. 63. GET / Accept: application/vnd.resource-def+json
  64. 64. { "Tasks": "http://my.app/tasks", "Users": "http://my.app/users" }
  65. 65. OPTIONS /tasks Accept: application/vnd.resourceschema+json
  66. 66. { "title": "string", "completed": "boolean", ... }
  67. 67. More HTTP goodies ...that you don't need to reinvent
  68. 68. HTTP Range GET /rickroll.mp4 Range: bytes=10099999
  69. 69. HEAD /posts HTTP/1.1 ... HTTP 200 OK Accept-Ranges: posts
  70. 70. GET /posts HTTP/1.1 Range: posts=1-20
  71. 71. HTTP Auth Always use protection!
  72. 72. Caching Implement any invalidation strategy you can imagine
  73. 73. PHP?
  74. 74. nateabele/li3_resour ces (on GitHub)
  75. 75. Automatic CRUD manipulation with verbs Parameter mapping Links from model relationships Schemas with OPTIONS Proxies for mapping database values
  76. 76. Coming soon... Range pagination Smart search with ?q=... ...Tests (runs away)
  77. 77. Thanks!

×