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
Tweet

More Decks by Joseph Ruscio

Other Decks in Programming

Transcript

  1. Building RESTful APIs
    Friday, October 28, 2011

    View Slide

  2. 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

    View Slide

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

    View Slide

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

    View Slide

  5. 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

    View Slide

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

    View Slide

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

    View Slide

  8. 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

    View Slide

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

    View Slide

  10. 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

    View Slide

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

    View Slide

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

    View Slide

  13. 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

    View Slide

  14. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. 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

    View Slide

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

    View Slide

  20. 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

    View Slide

  21. 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

    View Slide

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

    View Slide

  23. 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

    View Slide

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

    View Slide

  25. 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

    View Slide

  26. 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

    View Slide

  27. 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

    View Slide

  28. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide