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

The never ending REST API design debate

The never ending REST API design debate

What should a good REST API look like? Should you use verbs or nouns in your resource paths? How do you handle versioning of APIs? How to deal with partial responses and pagination? Which status codes should I make use of? What about sorting, filtering, and searching? Have you thought about content negotiation, and hypermedia?

Guillaume will got through all these topics, offering advice on the best approaches to those questions, and opening up the debate on the various options available, so as to make your Web API at REST, as clean and elegant as possible.

Guillaume Laforge

November 12, 2015
Tweet

More Decks by Guillaume Laforge

Other Decks in Technology

Transcript

  1. The never-ending REST
    API design debate
    Guillaume Laforge
    Restlet — the Web API platform
    Chair of the Apache Groovy PMC
    @glaforge

    View Slide

  2. We know
    about
    APIs!
    http://restlet.com

    View Slide

  3. We know
    about
    APIs!
    http://restlet.com

    View Slide

  4. ROY FIELDING
    REST
    DISSERTATION

    View Slide

  5. ROY FIELDING
    REST
    DISSERTATION
    Principled design
    of the modern
    Web architecture

    View Slide

  6. 4
    Representational State Transfer
    Architectural properties
    • Performance
    • Scalability
    • Simplicity
    • Modifiability
    • Visibility
    • Portability
    • Reliability
    Architectural constraints
    • Client-server
    • Stateless
    • Cacheable
    • Layered system
    • Code on demand (optional)
    • Uniform interface

    View Slide

  7. 5
    REST — Uniform interface
    • Identification of resources
    • Manipulation of resources 

    through representations
    • Self-descriptive messages
    • HATEOAS 

    (Hypermedia As The Engine 

    Of Application State)

    View Slide

  8. 5
    REST — Uniform interface
    • Identification of resources
    • Manipulation of resources 

    through representations
    • Self-descriptive messages
    • HATEOAS 

    (Hypermedia As The Engine 

    Of Application State)
    Resource as URIs
    http://api.co/cars/123

    View Slide

  9. 5
    REST — Uniform interface
    • Identification of resources
    • Manipulation of resources 

    through representations
    • Self-descriptive messages
    • HATEOAS 

    (Hypermedia As The Engine 

    Of Application State)
    Resource as URIs
    http://api.co/cars/123
    JSON, XML…

    View Slide

  10. 5
    REST — Uniform interface
    • Identification of resources
    • Manipulation of resources 

    through representations
    • Self-descriptive messages
    • HATEOAS 

    (Hypermedia As The Engine 

    Of Application State)
    Resource as URIs
    http://api.co/cars/123
    JSON, XML…
    HTTP GET, POST, PUT, DELETE
    media types, cacheability…

    View Slide

  11. 5
    REST — Uniform interface
    • Identification of resources
    • Manipulation of resources 

    through representations
    • Self-descriptive messages
    • HATEOAS 

    (Hypermedia As The Engine 

    Of Application State)
    Resource as URIs
    http://api.co/cars/123
    JSON, XML…
    HTTP GET, POST, PUT, DELETE
    media types, cacheability…
    Hypermedia APIs
    HAL, JSON-LD, Siren…

    View Slide

  12. 6
    HTTP methods / URIs for collection/item
    GET
    POST
    PUT
    DELETE
    http://api.co/v2/cars/ http://api.co/v2/cars/1234
    List all the cars Retrieve an individual car
    Create a new car Error
    Replace the entire collection
    with a whole new list of cars
    Replace or create
    an individual car
    Delete all the cars Delete an individual car

    View Slide

  13. NOUNS
    ARE GOOD
    VERBS
    ARE BAD

    View Slide

  14. 8
    Nouns are good, verbs are bad!
    • Prefer nouns to verbs
    • nouns refer to resources
    • resources are handled with HTTP verbs
    • Verbs can be used for actions or calculations
    • /login, /logout
    • /convertTemperature
    • /repositories/123/star

    View Slide

  15. View Slide

  16. 10
    Singular or plural resources?
    • Prefer plural forms
    • /tickets/234 vs /ticket/234
    • Avoid confusing odd singular vs plural forms
    • /person vs /people, or /goose vs /geese
    • Easier for URL routing (same prefix)
    • Think of it as: 

    ‘This is the 234th item of the tickets collection’

    View Slide

  17. Camel
    case?

    View Slide

  18. Camel
    case?
    Snake
    case!

    View Slide

  19. 12
    Different casing in the wild
    • UpperCamelCase or lowerCamelCase
    • snake_case or dashed-snake-case
    • Prefer lowercase
    • Prefer snake_case
    • Underscores seem more common in APIs
    • But chose one casing and be consistent!

    View Slide

  20. 13
    Dealing with relations in your URLs
    • /tickets/123/messages/4
    • a ticket could be a group of messages
    • /usergroups/234/users/67
    • a user could belong to different usergroups
    • user should have a URL of its own, referenced from the
    usergroup payload

    View Slide

  21. API PARAMETERS
    RULE OF THUMBS

    View Slide

  22. 15
    API parameters — rule of thumbs
    • Path
    • required, resource identifier
    • Query
    • optional, query collections
    • Body
    • resource specific logic
    • Header
    • global, platform-wide

    View Slide

  23. 16
    HTTP Status Code Map http://bit.ly/stcode

    View Slide

  24. 17
    Common HTTP status codes
    • Use appropriate HTTP status codes when answering
    requests:
    • 1xx: Hold on…
    • 2xx: Here you go!
    • 3xx: Go away!
    • 4xx: You fucked up :-D
    • 5xx: I fucked up :-(

    View Slide

  25. 18
    Common HTTP Status Codes — 1xx

    View Slide

  26. 19
    Common HTTP Status Codes — 2xx

    View Slide

  27. 19
    Common HTTP Status Codes — 2xx

    View Slide

  28. 19
    Common HTTP Status Codes — 2xx

    View Slide

  29. 19
    Common HTTP Status Codes — 2xx

    View Slide

  30. 19
    Common HTTP Status Codes — 2xx

    View Slide

  31. 19
    Common HTTP Status Codes — 2xx

    View Slide

  32. NOT
    JUST
    200
    201
    202
    204
    206

    View Slide

  33. Anti-pattern:
    returns 200
    for everything,
    even errors!

    View Slide

  34. 22
    Not just 200 OK! — 201 Created
    • Specify a Location header, pointing at the location of the
    newly created resource
    POST /cars ...
    HTTP/1.1 201 Created
    Location: http://cars.co/v2/cars/5959

    View Slide

  35. API navigation is
    important to make the
    API more discoverable

    View Slide

  36. 24
    DHC by Restlet: API testing tool

    View Slide

  37. 25
    Not just 200 OK! — 202 Accepted
    • Request accepted but will be handled asynchronously
    • a job might be running later and yield a result later on
    POST /jobs ...
    HTTP/1.1 202 Accepted
    No payload
    returned

    View Slide

  38. 26
    Not just 200 OK! — 204 No content
    • The resource was deleted and no payload is returned
    • but could return 200 OK 

    & provide the payload of the deleted element
    DELETE /tickets/654
    HTTP/1.1 204 No content

    View Slide

  39. 27
    Not just 200 OK! — 206 Partial content
    • A partial list of meteorites is returned, using pagination
    • add a Link header to facilitate navigation
    GET /meteorites?page=4
    HTTP/1.1 206 Partial content
    Link: ; rel="first", 

    ; rel="prev",
    ; rel="next", 

    ; rel="last"
    ...

    View Slide

  40. 28
    Not just 200 OK! — 304 Not modified
    • When HTTP caching headers are in play
    • the client should have a version in cache already
    GET /meteorites/654
    HTTP/1.1 304 Not modified

    View Slide

  41. Caching!

    View Slide

  42. 30
    Last-Modified
    GET /users/123
    Modified-Since: Fri, 13 Nov 2015 02:13:11 GMT
    HTTP/1.1 200 OK
    Last-Modified: Sun, 15 Nov 2015 04:58:08 GMT

    View Slide

  43. 31
    ETag
    GET /users/123
    If-None-Match: a456ef544eeb7333af
    HTTP/1.1 200 OK
    ETag: 686897696a7c876b7e
    GET /users/123
    If-None-Match: 686897696a7c876b7e
    HTTP/1.1 304 Not modified

    View Slide

  44. PAGINATION

    View Slide

  45. 33
    Pagination with query parameters
    • With a page number: ?page=23
    • can also specify a page size
    • might get odd results when insertions happen
    • With a cursor: ?cursor=34ea3fd6
    • insertion-friendly
    • With a semantic parameter: ?page=A
    • interesting when limited / discrete number of pages

    View Slide

  46. 34
    Pagination with accept range header
    • Accept range header not just for bytes
    GET /users
    HTTP/1.1 206 Partial content
    Accept-Ranges: users
    Content-Range: users 0-9/200
    GET /users
    Range: users=0-9

    View Slide

  47. Wrapped
    CollectionS

    View Slide

  48. 36
    Wrapped collections
    • Prefer unwrapped collections
    • unless there’s specific collection payload metadata

    (example: photo album details)
    • pagination are better in HTTP headers
    GET /tickets
    Content-Type: application/json
    {
    data: [
    { id: 1, ... },
    { id: 2, ... }
    ]
    }
    GET /tickets
    Content-Type: application/json
    [
    { id: 1, ... },
    { id: 2, ... }
    ]

    View Slide

  49. 37
    Common HTTP Status Codes — 3xx

    View Slide

  50. 37
    Common HTTP Status Codes — 3xx

    View Slide

  51. 37
    Common HTTP Status Codes — 3xx

    View Slide

  52. 37
    Common HTTP Status Codes — 3xx

    View Slide

  53. 37
    Common HTTP Status Codes — 3xx

    View Slide

  54. 37
    Common HTTP Status Codes — 3xx

    View Slide

  55. 38
    Common HTTP Status Codes — 4xx

    View Slide

  56. 38
    Common HTTP Status Codes — 4xx

    View Slide

  57. 38
    Common HTTP Status Codes — 4xx

    View Slide

  58. 38
    Common HTTP Status Codes — 4xx

    View Slide

  59. 38
    Common HTTP Status Codes — 4xx

    View Slide

  60. 38
    Common HTTP Status Codes — 4xx

    View Slide

  61. 39
    Provide helpful error payloads
    • No definitive standard yet
    • http problem proposal and vnd-error mime type
    HTTP/1.1 403 Forbidden
    Content-Type: application/problem+json
    Content-Language: en
    {
    "type": "https://example.com/probs/out-of-credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345", "/account/67890"]
    }

    View Slide

  62. 40
    Common HTTP Status Codes — 5xx

    View Slide

  63. 40
    Common HTTP Status Codes — 5xx

    View Slide

  64. 40
    Common HTTP Status Codes — 5xx

    View Slide

  65. 40
    Common HTTP Status Codes — 5xx

    View Slide

  66. 41
    Treating unknown status codes
    • An unknown status code should be treated 

    as the first one of the family
    • 4xx — 400 generic client error
    • 5xx — 500 generic server error

    View Slide

  67. RATE
    LIMITATION

    View Slide

  68. 43
    Rate limitation
    HTTP/1.1 200 OK
    Date: Mon, 01 Jul 2013 17:27:06 GMT
    Status: 200 OK
    X-RateLimit-Limit: 60
    X-RateLimit-Remaining: 56
    X-RateLimit-Reset: 1372700873
    Total number of
    requests allowed
    Number of
    requests left
    remaining window before
    the rate limit resets in UTC
    epoch seconds

    View Slide

  69. ONE
    SIZE
    FITS
    ALL
    Different payloads
    for different
    consumers

    View Slide

  70. 45
    Selecting with query parameters
    • Only 5 stars Chinese restaurants
    • GET https://api.co/restaurants?type=chinese&stars=5

    View Slide

  71. FIL
    TERING

    View Slide

  72. 47
    Filtering
    • Specify fields you’re interested in:
    • GET https://api.co/users/123?fields=firstname,lastname,age
    • Specify excluded fields:
    • GET https://api.co/users/123?exclude=biography,resume
    • Specify a « style »:
    • GET https://api.co/users/123?style=compact

    View Slide

  73. 48
    Prefer… the prefer header
    GET /users/123 HTTP/1.1
    Content-Type: application/json
    Prefer: return=minimal
    Vary: Prefer,Accept,Accept-Encoding
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    Vary: Prefer,Accept,Accept-Encoding
    Preference-Applied: return=minimal
    Define different
    profiles: minimal,
    mobile, full…

    View Slide

  74. 49
    Expanding referenced resources
    • Use the dot notation to explicit you want sub-resources
    • GET https://api.co/users/123?fields=address.zip
    • user
    • name
    • address
    • zip
    • country
    • …
    • …

    View Slide

  75. SORTING

    View Slide

  76. 51
    Sorting
    • SQL-style
    • GET https://api.co/books?sort=title+DESC
    • GET https://api.co/books?sort=title+DESC,author+ASC
    • Sort + asc/desc combo
    • GET https://api.co/books?sort=title&desc=title
    • GET https://api.co/books?
    sort=title,author&desc=title&asc=author

    View Slide

  77. SEARCHING

    View Slide

  78. 53
    Searching
    • Combien various filtering fields
    • Or provide a full-blown query language

    View Slide

  79. v1

    View Slide

  80. 55
    Different approaches for API versioning
    • Most frequent, in the URL:
    • https://api.com/v2/restaurants/1234
    • Custom header:
    • X-API-Version: 2
    • Less frequent, with an accept header
    • clients don’t have to change endpoint, but update headers
    GET /restaurants
    Accept: application/vnd.restaurants.v2+json

    View Slide

  81. hypermedia

    View Slide

  82. 57
    Richardson maturity model

    View Slide

  83. 58
    Pros & Cons of hypermedia
    • Pros
    • more generic clients
    • can palliate the need for API versioning
    • Cons
    • heavier payload (think mobile devices w/ bad connectivity)
    • clients still need to understand what links are about and
    how to represent them in their UI

    View Slide

  84. C
    H
    A
    N
    G
    E
    IS
    U
    N
    A
    V
    O
    ID
    A
    B
    L
    E

    View Slide

  85. 60
    Lots of choice
    • HAL
    • JSON-LD
    • Collection+JSON
    • SIREN
    • …
    • Which to chose from?
    • no real consensus yet
    • but HAL seems quite common

    View Slide

  86. 61
    A word about IDs for linked resources
    • If you’re tempted to go your own way for hypermedia…
    • Be sure to define direct links to resources
    • photos: [http://news.co/articles/123/photos/654,

    http://news.co/articles/123/photos/659]
    • Not mere IDs for which API clients need to figure out the
    exact resource location (error-prone)
    • photos: [654, 659]

    View Slide

  87. 62
    Another word about IDs
    • Usually avoid counter-type IDs: 1, 2, 3, 4…
    • Prefer UUIDs
    • makes it harder for malignant users 

    to scan & discover existing resources
    • auto-incrementing IDs might not be unique 

    in distributed systems

    View Slide

  88. HAL
    I’m sorry Dave, I
    can do Hypermedia

    View Slide

  89. 64
    HAL approach
    GET https://api.com/player/1234567890
    HTTP/1.1 200 OK
    {
    "_links": {
    "self": { "href": "https://api.com/player/1234567890" },
    "friends": { "href": "https://api.com/player/1234567890/friends" }
    },
    "playerId": "1234567890",
    "name": "Kevin Sookocheff",
    "alternateName": "soofaloofa",
    "image": "https://api.com/player/1234567890/avatar.png"
    }
    Special _links property

    View Slide

  90. Resources

    View Slide

  91. 66
    API design resources
    • http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
    • https://github.com/paypal/api-standards/blob/master/api-style-guide.md
    • http://blog.octo.com/en/design-a-rest-api/
    • https://github.com/interagent/http-api-design/blob/master/SUMMARY.md
    • http://sookocheff.com/post/api/on-choosing-a-hypermedia-format/
    • http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html

    View Slide

  92. Thanks for your attention

    View Slide

  93. Questions & Answers

    View Slide