Slide 1

Slide 1 text

Building RESTful APIs Friday, October 28, 2011

Slide 2

Slide 2 text

metrics.librato.com Consumes arbitrary time series data Store it, visualize it, analyze it Query it back out from API Rich client interface Librato Metrics Friday, October 28, 2011

Slide 3

Slide 3 text

metrics.librato.com Friday, October 28, 2011

Slide 4

Slide 4 text

metrics.librato.com Friday, October 28, 2011

Slide 5

Slide 5 text

metrics.librato.com “[hypertext constraint is] most often violated within so-called REST APIs ... adhere to them or choose some other buzzword for your API.” - Roy Fielding Friday, October 28, 2011

Slide 6

Slide 6 text

metrics.librato.com CRUD API Resources identified/addressed by URI URI Templates HTTP-based interactions Friday, October 28, 2011

Slide 7

Slide 7 text

metrics.librato.com CRUD: Resources Anything we expose to the Web Resources have representations JSON,XML,PNG Services exchange representations Friday, October 28, 2011

Slide 8

Slide 8 text

metrics.librato.com CRUD: HTTP Verbs POST /res Unsafe GET /res/:id Safe PUT /res/:id Idempotent DELETE /res/:id Idempotent Friday, October 28, 2011

Slide 9

Slide 9 text

metrics.librato.com Design Constraints JSON input/output x-form-urlencoded input for a bonus Basic HTTP Authentication over SSL Friday, October 28, 2011

Slide 10

Slide 10 text

metrics.librato.com Doc. Driven Design URI template Markdown file per-resource URI, parameters, examples Production ready before a single LOC! Friday, October 28, 2011

Slide 11

Slide 11 text

metrics.librato.com Friday, October 28, 2011

Slide 12

Slide 12 text

metrics.librato.com Test Driven Dev. Simulate requests against the API Assert expectations about the response test-unit + rack-test Friday, October 28, 2011

Slide 13

Slide 13 text

metrics.librato.com Test Driven Dev. def test_create_gauge params = {} params[:name] = "my_gauge" post "/gauges", params assert_equal 201, last_response.status assert last_response.original_headers["Location"] =~ /^\/v1\/gauges\/#{params[:name]}$/ end Friday, October 28, 2011

Slide 14

Slide 14 text

metrics.librato.com rack-test-rest def test_crud name = "my_gauge" and period = 60 #CREATE create_resource(:name => name, :description => desc) #READ gauge = read_resource(:id => name) assert_equal(name, gauge['name']) #UPDATE update_resource(:name => name, :period => 300) #DELETE delete_resource(:id => name) read_resource(:code => 404, :id => name) end Friday, October 28, 2011

Slide 15

Slide 15 text

metrics.librato.com rack-test-rest Friday, October 28, 2011

Slide 16

Slide 16 text

metrics.librato.com Implementation Thin layer over your models Sinatra + Sequel Resource per file Friday, October 28, 2011

Slide 17

Slide 17 text

metrics.librato.com Implementation Friday, October 28, 2011

Slide 18

Slide 18 text

metrics.librato.com Implementation post "/gauges" do unless params[:name] abort_params({:name => ["Must specify gauge name"]}) end if find_gauge(params[:name]) abort_unique({:name => ["Gauge name must be unique"]}) end gauge = create_gauge() halt_created("/gauges/#{gauge.name}") end Friday, October 28, 2011

Slide 19

Slide 19 text

metrics.librato.com Friday, October 28, 2011

Slide 20

Slide 20 text

metrics.librato.com URI Extensions URI should not imply representation Legacy from mapping URI’s to files Use content negotiation http://example.org/resource/123 Friday, October 28, 2011

Slide 21

Slide 21 text

metrics.librato.com API Versioning http://v1.example.org/resource/123 http://example.org/v1/resource/123 http://example.org/resource/123 ?v=1 Accept: application/json;version=1 Friday, October 28, 2011

Slide 22

Slide 22 text

metrics.librato.com Partial Updates PUT,POST,PATCH? PATCH - RFC5789 PATCH /resource/:id Friday, October 28, 2011

Slide 23

Slide 23 text

metrics.librato.com HATEOAS CRUD is great except when it isn’t Hypermedia models state transitions Inclusion of links in representation Friday, October 28, 2011

Slide 24

Slide 24 text

metrics.librato.com CRUD Pagination { "query":{ "total":128, "found":128, "offset":0, "length":100 }, "gauges":[ { "name":"gauge1" }, { "name":"gauge2" }, ... ] } Friday, October 28, 2011

Slide 25

Slide 25 text

metrics.librato.com REST Pagination { "next":{ "uri":"http://api.librato.com/gauges?offset=100”, "rel":"http://relations.librato.com/paginate", "media_type":"application/vnd.librato+json" }, "gauges":[ { "name":"gauge1" }, { "name":"gauge2" }, ... ] } Friday, October 28, 2011

Slide 26

Slide 26 text

metrics.librato.com Link Elements uri attribute describes resource rel attribute contains semantic markup link elements can be added/removed from representations Friday, October 28, 2011

Slide 27

Slide 27 text

metrics.librato.com GLory of REST Single bookmarked URI Next states are discovered inline Series of representation exchanges transforms application state No URI templates/versioning Friday, October 28, 2011

Slide 28

Slide 28 text

metrics.librato.com Have an API and build it first At least use CRUD Docs > Tests > Code Make it DRY Dogfood it Learn more about REST Friday, October 28, 2011

Slide 29

Slide 29 text

metrics.librato.com Friday, October 28, 2011

Slide 30

Slide 30 text

metrics.librato.com Friday, October 28, 2011

Slide 31

Slide 31 text

metrics.librato.com Friday, October 28, 2011

Slide 32

Slide 32 text

metrics.librato.com “be conservative in what you do, be liberal in what you accept from others” - Postel’s Law Friday, October 28, 2011