The never-ending REST API design debate -- Devoxx France 2016

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

Transcript of The never-ending REST API design debate -- Devoxx France 2016

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

Devoxx Promo Code: ctwdevoxxfrhttp://www.manning.com/koenig2/

GROOVY IN ACTION 2ND EDITION

We know about APIs!

http://restlet.com

We know about APIs!

http://restlet.com

ROY FIELDING

REST DISSERTATION

ROY FIELDING

REST DISSERTATION

Principled design of the modern

Web architecture

5

Representational State TransferArchitectural properties

• Performance • Scalability • Simplicity • Modifiability • Visibility • Portability • Reliability

Architectural constraints

• Client-server • Stateless • Cacheable • Layered system • Code on demand (optional) • Uniform interface

6

REST — Uniform interface• Identification of resources

• Manipulation of resources through representations

• Self-descriptive messages

• HATEOAS (Hypermedia As The Engine Of Application State)

6

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

6

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…

6

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…

6

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…

7

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 Update an individual car

Delete all the cars Delete an individual car

NOUNS

ARE GOOD

VERBS

ARE BAD

9

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

11

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’

Camel case?

Camel case?

Snake case!

13

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!

14

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

API PARAMETERS RULE OF THUMBS

16

API parameters — rule of thumbs• Path

• required, resource identifier • Query

• optional, query collections • Body

• resource specific logic • Header

• global, platform-wide

17

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

18

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 :-(

19

Common HTTP Status Codes — 1xx

20

Common HTTP Status Codes — 2xx

20

Common HTTP Status Codes — 2xx

20

Common HTTP Status Codes — 2xx

20

Common HTTP Status Codes — 2xx

20

Common HTTP Status Codes — 2xx

20

Common HTTP Status Codes — 2xx

NOT JUST 200

201

202

204

206

Anti-pattern: returns 200

for everything, even errors!

23

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

API navigation is important to make the API more discoverable

25

DHC by Restlet: API testing tool

26

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

27

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

28

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: <http://nasa.co/meteorites?page=1>; rel="first", <http://nasa.co/meteorites?page=3>; rel="prev", <http://nasa.co/meteorites?page=5>; rel="next", <http://nasa.co/meteorites?page=9>; rel="last"

...

29

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

Caching!

31

Last-Modified

GET /users/123 Modified-Since: Wed, 13 Apr 2016 02:13:11 GMT

HTTP/1.1 200 OK Last-Modified: Fri, 15 Apr 2016 04:58:08 GMT

32

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

PAGINATION

34

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

35

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

Wrapped CollectionS

37

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, ... } ]

38

Common HTTP Status Codes — 3xx

38

Common HTTP Status Codes — 3xx

38

Common HTTP Status Codes — 3xx

38

Common HTTP Status Codes — 3xx

38

Common HTTP Status Codes — 3xx

38

Common HTTP Status Codes — 3xx

39

Common HTTP Status Codes — 4xx

39

Common HTTP Status Codes — 4xx

39

Common HTTP Status Codes — 4xx

39

Common HTTP Status Codes — 4xx

39

Common HTTP Status Codes — 4xx

39

Common HTTP Status Codes — 4xx

40

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"] }

41

Common HTTP Status Codes — 5xx

41

Common HTTP Status Codes — 5xx

41

Common HTTP Status Codes — 5xx

41

Common HTTP Status Codes — 5xx

42

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

RATE LIMITATION

44

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

ONE SIZE FITS

ALL

Different payloads for different consumers

46

Selecting with query parameters• Only 5 stars Chinese restaurants

• GET https://api.co/restaurants?type=chinese&stars=5

FILTERING

48

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

49

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…

50

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 • …

• …

SORTING

52

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

SEARCHING

54

Searching• Combine various filtering fields

• Or provide a full-blown query language

55

Search / filter / sort…• Also have a look at other approaches

• Facebook’s GraphQL • Netflix’s Falcor

v1

57

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

hypermedia

59

Richardson maturity model

60

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

CHANGE IS

UNAVOID

ABLE

62

Lots of choice• HAL • JSON-LD • Collection+JSON • SIREN • …

• Which to chose from? • no real consensus yet • but HAL seems quite common

63

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]

64

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

HAL

I’m sorry Dave, I can do Hypermedia

66

HAL approachGET 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

Resources

68

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

Thanks for your attention

Questions & Answers