Upload
restlet
View
1.234
Download
2
Embed Size (px)
Citation preview
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
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
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’
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
16
API parameters — rule of thumbs• Path
• required, resource identifier • Query
• optional, query collections • Body
• resource specific logic • Header
• global, platform-wide
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 :-(
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
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
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
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
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, ... } ]
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"] }
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
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
46
Selecting with query parameters• Only 5 stars Chinese restaurants
• GET https://api.co/restaurants?type=chinese&stars=5
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 • …
• …
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
55
Search / filter / sort…• Also have a look at other approaches
• Facebook’s GraphQL • Netflix’s Falcor
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
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
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
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
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