pox to hateoas: our company's journey building a hypermedia api

Post on 11-May-2015

6.828 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

We started FoxyCart.com in 2007 and soon after slapped together some XML and called it an API. As our customer base grew and third-party integrations emerged, the need for a true REST API became a priority. Beginning in 2012, we started researching best practices for modern API development. This talk will tell the story of that research and 10-months of development that followed. You'll get a look at the HAL hypermedia format along with some best practices we came up with for our problem domain of exposing our entire admin interface. We'll cover a lot. You may need a seat belt.

TRANSCRIPT

From POX to HATEOASOur Company's Journey Building a Hypermedia API

Who...Luke StokesCo-Founder, Developer of FoxyCartluke.stokes@foxycart.com@lukestokeshttp://bestoked.blogspot.com

What...FoxyCart● ecommerce shopping cart system● Started by Brett Florio and myself in

2005/2006, incorporated in 2007.● SaaS (soon to be PaaS)● Built to integrate using your css/html (we're

not a CMS)● No duplication of data

Why...No duplication? Expose our data!POX: Plain Old XML● Confusing API actions

○ transaction_get, transaction_list, attribute_save, attribute_delete, transaction_modify, store_includes_get, etc

● Confusing request/response model● Tight coupling between the client and server

APIs and the Internet● Middleware ($$$)● RPC● SOAP● WSDL● Web Services (the WS-* stack)

Tight Coupling!

Does your browser do this?

REST to the rescueCRUD can be standardized via HTTP methods:

POST/PUT = createGET = readPATCH/PUT = updateDELETE = delete

(goodbye *_list, *_save, *_modify, etc methods)

REST to the rescueAgreed upon response codes● 1xx: Informational● 2xx: Success● 3xx: Redirection● 4xx: Client Error (You Screwed Up)● 5xx: Server Error (We Screwed Up)

http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

But... where do we start?

What's a perfect example of a REST API?

What is REST anyway?Six Constraints:● Client-server● Stateless● Cacheable● Layered system● Code on demand (optional)● Uniform interface

○ Identification of resources○ Manipulation of resources through these representations○ Self-descriptive messages○ Hypermedia as the engine of application state

REST Client Need-to-Know● Homepage● Hypermedia Format● Rel tags● Known media types (and possibly versions) ● Bonus stuff:

○ ?limit=5&offset=10○ ?order=<field> desc (or asc)○ ?fields=<field>,<field>,<field>○ ?<field>=<value>○ ?<field>=<some * partial value>

What's a media type?Examples:

application/jsonapplication/xmlapplication/hal+json

Originally defined as MIME types (RFC 2046)Also referred to as Content-Types

Platform = Will Not BreakEcommerce site broken at 4am and you changed nothing?

No one wants that phone call.

Flexible Versioning● FOXYCART-API-VERSION header

Flexible Versioning● FOXYCART-API-VERSION header● Per-resource vendor specific media type:

application/vnd.foxycart.com.store.v1+json

See: http://www.foxycart.com/blog/the-hypermedia-debate

Flexible Versioning● FOXYCART-API-VERSION header● Per-resource vendor specific media type:

application/vnd.foxycart.com.store.v1+json● Hypermedia allows us to version via the link

relation we code to.

Flexible Versioning● FOXYCART-API-VERSION header● Per-resource vendor specific media type:

application/vnd.foxycart.com.store.v1+json● Hypermedia allows us to version via the link

relation we code to.link: <https://example.com/users/2>;rel="https://example.com/rels/user"

Flexible Versioning● FOXYCART-API-VERSION header● Per-resource vendor specific media type:

application/vnd.foxycart.com.store.v1+json● Hypermedia allows us to version via the link

relation we code to.link: <https://example.com/users/2>;rel="https://example.com/rels/user"link: <https://example.com/customers/2>;rel="https://example.com/rels/customer"

Flexible VersioningHeader: FOXYCART-API-VERSION: 1Add "awesome_sauce" field:... "store_name":"My Store", "awesome_sauce":"pixie dust", "store_domain":"example",...Additions? No problem!

Flexible VersioningHeader: FOXYCART-API-VERSION: 1Remove "awesome_sauce" field...

Uh Oh.

Option 1: rel="https://example.com/store_v2"Option 2: FOXYCART-API-VERSION: 2

HEADERS: Array( [0] => Accept: application/hal+xml [1] => FOXYCART-API-VERSION: 1)

curl -X GET -H "Accept: application/hal+xml" -H "FOXYCART-API-VERSION: 1" https://api-sandbox.foxycart.com/

XML Accepts Header

Next...?<link rel="self" href="https://api-sandbox.foxycart.com/" title="Your API starting point."/><link rel="https://api.foxycart.com/rels/create_client" href="https://api-sandbox.foxycart.com/clients" title="Create a client via POST."/>

HATEOAS:Hypermedia as the Engine of Application State

Next...? OPTIONScurl -i -X OPTIONS

-H "Authorization: Bearer cae3c0c261fc71512428d612c1d2fd2a"-H "FOXYCART-API-VERSION: 1"-H "Accept: application/hal+xml"

"https://api-sandbox.foxycart.com/stores/2"

HTTP/1.1 200 OK..Allow: HEAD,GET,PUT,PATCH,DELETE...

Next...? POST: /clientsHEADERS: Array( [0] => Accept: application/hal+xml [1] => FOXYCART-API-VERSION: 1)

curl -X POST -H "Accept: application/hal+xml" -H "FOXYCART-API-VERSION: 1" https://api-sandbox.foxycart.com/clients

Error HandlingHTTP/1.1 400 Bad RequestDate: Fri, 30 Mar 2012 21:39:50 GMTConnection: closecache-control: private, must-revalidateContent-Type: application/vnd.error+xmlContent-Length: 546

https://github.com/blongden/vnd.error

Error Handling<errors xml:lang="en"> <error logref=42> <message>Validation failed</message> <link rel='help' href='http://...' title='Error information'/> <link rel='describes' href='http://...' title='Error description'/> </error></errors>

Let's take a look at the HAL Browser!

Hal Talk:http://haltalk.herokuapp.com/explorer/hal_browser.html#/

Foxy Cart:http://wiki.foxycart.com/v/0.0.0/hypermedia_apihttps://api-sandbox.foxycart.com/hal-browser/hal_browser.html#/https://api-sandbox.foxycart.com/hal-browser/

Examples!

What's all this token stuff?

* image credit: http://www.ibm.com/developerworks/library/x-androidfacebookapi/

OAuth 2.0 - Why Bother?Remember: Platform as a service!

● Hosted solutions● Hosted CMS● Self-hosted on a development platform

Simplify where we can:● If you created it, you get full access to it and

we can skip the OAuth Dance

Client Code$resp = $client->get(

$api_home_page,null,$display->getHeaders()

);$display->displayResult('Home Page',$client);$useful_links['create_client'] = $client->getLink('create_client');$resp = $client->post(

$useful_links['create_client'],$data,$display->getHeaders()

);

REST is easy, right? (Nope)● Should every resource have a custom media

type?● How should Hypermedia be represented in

JSON (Collection+JSON, HAL, Siren, etc)?● Link header exclusively or links as part of the

body?● To embedded sub resources?● PATCH/PUT or POST? (X-HTTP-Method-

Override)● Where to put the version number?

REST is easy, right? (Nope)● Include the full resource response when

creating or use a 204?● How do you avoid one PATCH stomping

another?○ ETags and Preconditions

○ "If-None-Match: W/\"9f55f4d0f19b152a6e7c6ddeb4107e486fd7727c\""

○ "If-Modified-Since: Wed, 15 Feb 2012 12:53:52 -0800"

● How do you make hypermedia useful to the client and end user?

● Forms?

YOU NEED TESTS!Functional tests are critical● Ensures your changes haven't broken

anything old or new● Speeds up prototyping

Tests are NOT a substitute for your eyeballs

The FutureReliable platformsConsistent functionalityKnown, shared resources

Notes:http://bestoked.blogspot.com/2012/02/restful-resources-required-reading.htmlhttp://wiki.foxycart.com/v/0.0.0/hypermedia_api

top related