Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building RESTful APIs

Building RESTful APIs

Discussion of how to design, test, and implement CRUD (commonly referred to as RESTful) APIs and how HATEOAS transforms a CRUD API into a REST API. Tips/tricks for sticky areas like versioning, URI extensions, and partial updates. Talk given at the 10/27/2011 San Francisco Ruby on Rails Meetup.

Joseph Ruscio

October 28, 2011

More Decks by Joseph Ruscio

Other Decks in Programming


  1. 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
  2. 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
  3. metrics.librato.com CRUD: Resources Anything we expose to the Web Resources

    have representations JSON,XML,PNG Services exchange representations Friday, October 28, 2011
  4. 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
  5. metrics.librato.com Design Constraints JSON input/output x-form-urlencoded input for a bonus

    Basic HTTP Authentication over SSL Friday, October 28, 2011
  6. 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
  7. metrics.librato.com Test Driven Dev. Simulate requests against the API Assert

    expectations about the response test-unit + rack-test Friday, October 28, 2011
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. metrics.librato.com CRUD Pagination { "query":{ "total":128, "found":128, "offset":0, "length":100 },

    "gauges":[ { "name":"gauge1" }, { "name":"gauge2" }, ... ] } Friday, October 28, 2011
  14. 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
  15. 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
  16. 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
  17. metrics.librato.com “be conservative in what you do, be liberal in

    what you accept from others” - Postel’s Law Friday, October 28, 2011