HTTP ALL THE THINGS – Me – History



HTTP ALL THE THINGS – Me – History

0 0


http-talk

Talk: HTTP ALL THE THINGS: Simplifying Rich Applications by Respecting the Rules of the Web

On Github nateabele / http-talk

HTTP ALL THE THINGS

Simplifying Rich Applications by
Respecting the Rules of the Web

Or:

You're Still Doing HTTP Rong

Me

  • Nate Abele
  • Former lead developer, CakePHP
  • Founder & current lead developer, Lithium
  • Member, AngularUI
  • @nateabele
Thanks for having me, it's an honor to be here.

Thanks!

  • Amazingly, I get paid for this stuff
  • OS is magical because of people
  • I'm not a peasant

Life Lessons

  • Be humble
  • Don't be afraid to feel stupid
  • The night is young

History

1998: SOAP & XML-RPC

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>

Or...

XML-RPC

<?xml version="1.0"?>
<methodCall>
  <methodName>examples.getStateName</methodName>
  <params>
    <param>
        <value><i4>40</i4></value>
    </param>
  </params>
</methodCall>

:-(

  • POST *
  • Invocaction details in body
  • Format lock-in
  • No relationships
  • No discoverability
Oh hey, these are some notes. They'll be hidden in your presentation, but you can see them if you open the speaker notes window (hit 's' on your keyboard).

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
You've probably heard of the Richardson Maturity model or '4 levels of REST' 'Hypermedia' is the one everyone falls down on -- no one understood it well

Now: Hypermedia / HATEOAS

This brings us to today. When we refer to a system that follows all of these constraints, we generally use the term 'hypermedia' Two reasons: (1) as I said, almost nobody was doing this (2) it emphasizes the importance: this is the part that makes REST awesome

Hypermedia?

  • Content negotiation
  • State traversal
But what does this actually mean? Basically, a proper hypermedia app is a content-negotiated state-machine

Content negotiation

application/json ...?

 

Content negotiation

application/json

FALE

Content negotiation

Better:

application/rss+xml

Content negotiation

Better:

application/rss+xml

Content negotiation

application/vnd.twitter.stream+json

// I can decode this!json_decode()
/**
 * I can understand this!
 */
class Tweet {
   protected $username;
   protected $text;
   // ...
}

State traversal

Your API structure is a static definition of a state machine. It uses HTTP messages to perform operations and communicate state to your API client

Client: “What's next?”

- Where else can I get from here? - What's related?

We already do this!

Browsers

<link rel="stylesheet" href="/css/app.css" />
<link rel="next" href="/next" />
<link
   rel="alternate"
   type="application/rss+xml"
   href="/posts.rss"
/>

Users

(with the help of browsers)

<a href="/next" />Next</a>
<form></form>

Atom?

<link
  rel="foo"
  type="text/foo"
  href="http://foo"
/>
So what's the solution? Atom? A great standard, but... you're using XML :-P

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"}
  }
}]
With a simple JSON structure, we can get the same benefits of named and annotated links

Why?

So, why is this stuff important? To answer that question, we're going to switch to something completely different

AngularJS

AngularJS is a very popular JavaScript framework, that's part of a new wave of JavaScript frameworks

Valid alternatives

  • EmberJS
  • KnockoutJS
  • Backbone (kind of, not really)
That's not to say Backbone is bad, it's just not in the same class: it's an organizing framework for jQuery

AngularJS

  • Higher level of abstraction
  • Simple, well-designed architecture
  • Ridiculously simple unit testing
AngularJS is a very popular JavaScript framework, that's part of a new wave of JavaScript frameworks

Event binding

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>

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, v) {
    $(".greeting").append("<li>" + v + " World</li>");
  });
</script>

Iteration

AngularJS

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

Organization

AngularJS

Item: Qty: Price: Total:
$0.00
Total: $0.00

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>

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;
    });
  };
}

Organization

jQuery

Organization

jQuery

Ummm...?

Organization

jQuery

*shrug*

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);
    });
  });
});

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);
    });
  });
});

jQuery...?

Let's not even go there.

AngularJS + HTTP Resources

$resource()

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();
/* GET /tasks/5 */
var oneTask = Task.get({ id: 5 });

/* GET /tasks?completed=false&due=1381158984 */
var current = Task.query({
  completed: false,
  description: "..."
});

¡No me gusta!

This allows and even encourages bad API design

Tight coupling

  • Client-side URL templates
  • Excessive parameters
  • No links!
- Clients should never ever ever have to generate URLs client-side(Yes, I know there's an RFC around URL templates, I'm not a huge fan because it feels hacky and I think it's a symptom of bad design) - Mitigate lots of parameters by anticipating user intent - As we saw earlier, links allow clients to discover other things they can do with your system

Intent

What does your user (or API client) want to do?

/tasks?completed=false&due=1381158984

- What does this do? - What does that mean?

No meaning

/tasks/current

- These are the tasks that are due next week - These are the things I need to focus on - This is an important aspect of the design of APIs, but especially HTTP APIs - Providing an HTTP interface to do CRUD operations on your database is bad design! - Less brittle: you can change implementation details without breaking the interface

/tasks/:id

- So what about client-side URL templates? Why are they a problem? - Let's take a look at a different example
$resource("/posts/:id", {id: "@id"});
{
  id: 5,
  title: "Something New",
  slug: "something-new"
}

/posts/something-new

...? - But what if something in your routing or URL structure changes?

What to do?

So, what do we do about this?

uor/angular-model

(on GitHub)

- Write a new project of course! - Why? Because everyone else is doing it wrong! :-)
modelProvider.model("Tasks", {
  $instance: {
    finish: function() {
      this.completed = true;
      return this.$save();
    },
    isCompleted: function() {
      return !!this.completed;
    }
  }
});
So, does it do? - A simple way to attach business logic to resource endpoints - Leverage HTTP as it was meant to be used - All URLs come from the server

Where's the URL?

3 options

Automatic: /tasks

<link
  rel="resource"
  name="Tasks"
  href="<?=$this->url('Tasks'); ?>"
/>

GET /

Accept: application/vnd.resource-def+json (Re: content type) I just made that up!
{
  "Tasks": "http://my.app/tasks",
  "Users": "http://my.app/users"
}

OPTIONS /tasks

(Deprecated)

Accept: application/vnd.resource-schema+json (Re: content type) I just made that up!
{
  "title": "string",
  "completed": "boolean",
  ...
}

Buzzword Detour: "Service Oriented Architecture"

Good Ideas Apply Fractally

UI === App

URLs as Medium of Communication

More HTTP goodies

...that you don't need to reinvent

HTTP Range

GET /rickroll.mp4 Range: bytes=100-99999

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

JSONSpec.org

PHP?

So, what about the PHP code we use for this?

nateabele/li3_resources

(on GitHub)

- Experimental library
  • Automatic CRUD manipulation with verbs
  • Parameter mapping
  • Links from model relationships
  • Schemas with OPTIONS
  • Proxies for mapping database values

Coming soon...

  • Range pagination
  • Smart search with ?q=...
  • ...Tests (runs away)

koriym/BEAR.Sunday

Questions?

Thanks/Contact