All we know that REST services are almost everywhere now and nearly all new projects use it.
But do we really know how to design proper interfaces? What are pitfalls and how to avoid them?
I did many REST service designs and have a bunch of tips and tricks you definitely would like to use.
It will save you and your team a lot of time in future.
2. I am:
• Solution Architect in EPAM
• Java developer with 10+ years of experience
(also .NET, PHP)
• Kharkiv JUG Program Committee Head
• Bar owner
Who am I?
3. What do we need tests for?
1. Why it matters and what we won't talk about
2. Quick tips - one page you can easily find in Internet
3. What is hard to find in Internet
4. What is nearly impossible to find and what nobody likes to talk about
5. Tools, tools, tools
6. Modern approaches for communication between backend and frontend
Agenda
4. What do we need tests for?
• HATEOAS – never seen
• Management solutions – different focus
• Implementation details – takes to much time
Not today
5. •API (Application Programming Interface) is a
traditional and well known integration method.
An approach to represent Business or IT assets and enable
and enable programmatic access to them
•Recently, the term “API” often implies Web API:
“Web APIs are the defined interfaces through which
interactions happen between an enterprise and applications
applications that use its assets” - Wikipedia
•In business context APIs are seen as one of the pillars
of digital business: they help in building the
automated business ecosystems also known as
WHAT IS AN API?
GET statuses/mentions_timeline
GET statuses/user_timeline
GET statuses/retweets_of_me
GET statuses/retweets/:id
GET statuses/show/:id
POST statuses/destroy/:id
POST statuses/update
POST statuses/retweet/:id
01001
10110 CORE
BUSINESS
6. WHAT?
HOW?
API CLASSIFICATIONS: WHAT TYPES OF APIs EXIST?
▶ Data
▶ Processes
▶ Things
ASSETS
▶ Private
▶ Partner
▶ Public
SCOPE
▶ Free
▶ Developer pays
▶ Developer gets paid
▶ Indirect
BUSINESS
MODEL
▶ Based on specification or standard (e.g.
FHIR, OData)
▶ Unique, non-standard
STANDAR
DS
▶ SOAP
WEB
SERVICES
▶ Hypermedia
▶ Pragmatic REST
REST
▶ Websockets
▶ Comet
▶ Web hooks
EVENT-
DRIVEN
TECHNOL
OGY
7. Simple task:
Implement 3 tier application for saved search service:
• User submits a query
• System generates search results – saved search
• User can view submitted queries and then view
results
• User can archive or delete saved search
Three teams:
• Frontend
• Backend
• DevOps
Workshop
What could go wrong?
• Paths, methods
• Data models
• Input parameters
• Actions
• Security
Efforts:
• 1 hour for discussing happy-path scenarios
• 1 hour for discussing exceptional cases
9. 1. Nouns
GET /requests
GET /requests/new
GET /getRequests
2. GET and state
GET /users/123/activate -> activate
3. Plural nouns
GET /users
GET /user
4. Subresources
GET /users/123/activities
What you can find easily on the Internet?
5. Headers
Content-Type: application/json
Accept: appication/json, application/xml
6. Sorting and filtering
GET /cars?color=red
GET /cars?sort=+name,-age
7. Select fields
GET /cars?fields=name,color
8. Paging
GET /cars?limit=0&offset=10
10. What else?
10. Field names
Use camelCase that is a standard for JSON
11. Use error codes
2xx – ok
3xx – redirection
4xx – client error
5xx – server error
12. Versioning
/v1/cars
13. Shortcuts
/requests/closed
/notifications/last
14. Use or not use wrappers
{
count: 10,
list: [..]
}
15. Defaults for pagination and filtering
16. Authentication
12. What must be considered during design:
• How simple is to understand and ”Clean” design
• How to secure URI
• Usage scenarios and domain
• Caching
• Overlapping with other URIs
• REST requirements
Scenarios:
• View my requests
• View my requests (Support team)
• View requests from my department (Manager)
URI Structures
GET /requests
GET /requests?user_id={user_id}
GET /{user_id}/requests
GET /users/{user_id}/requests
GET /requests
X-User-Identifier: {user_id}
GET /support/requests
GET /requests/my
Cache-Control: private
GET /me/requests
Cache-Control: private
13. GET /requests/1234
--------------------
HTTP/1.1 200 OK
{
id: “1234”,
subject: “Password expired”,
categoryId: “22”,
created: …,
status: “APPROVED”,
assignee: {
id: “4321”,
name: “Amit Kumar”
}
}
Data models
POST /requests
{
subject: “Password expired”,
categoryId: “22”
}
--------------------
HTTP/1.1 201 Created
Location:
http://example.org/requests/1234
{
id: “1234”,
…
}
15. Prefer header
Applicable for:
• Different content schemas for GET requests
• return-minimal
• return-full
• Different return objects
• return-content
• return-status
• return-no-content
• Versioning
• Free format responses
Data models #3
HTTP/1.1 201 Created
Location: http://example.org/requests/1234
{
id: “1234”,
…
}
HTTP/1.1 201 Created
Location: http://example.org/requests/1234
{
status: ”ok”
}
HTTP/1.1 204 No Content
Location: http://example.org/requests/1234
16. Take into account:
• Caching must be proxy aware
• Aggressive caching might happen
• Header that might affect response content
Additional directives:
• max-age=<seconds> – overrides Expires header
• must-revalidate – forces resources validation
Examples:
Cache-Control: no-cache, no-store, must-revalidate
Cache-Control: public, max-age=31536000
What is eligible for:
• GET and HEAD
• 200, 203, 206, 300, 301, 410
Caching API Calls
Cache-
Control
Local
cache
Cache
anywhere
Revalidati
on
no-store no no n/a
private yes no no
no-cache yes yes yes
public yes yes no
If-Modified-Since != Last-Modified = 200
If-Modified-Since == Last-Modified = 304
If-None-Match != Etag = 200
If-None-Match == Etag = 304
HTTP/1.1 200 OK
Etag: “1234-1”
Last-Modified: Sat, 27 Jun 2015 11:03:32 GMT
17. Authentication methods:
• Basic
Authorization: Basic ZnJlZDpmcmVk
• API Key
X-API-Key: abcdef12345
• OAuth
Authorization: Bearer
pwwbkvv7abqzonnvztpea91ich7vprwdorbt4w4m
• OAuth JWT tokens
• OAuth scopes: granularity for permissions
• 54 scopes used by Slack API
• users.profile:read,
• users.profile:write
Security
18. Code Description
400 Bad
Request
Request cannot be processed. Used when
request contains unsupported parameters.
Also, used for validation errors or wrong
input format indication.
401
Unauthorized
Request requires authentication.
403 Forbidden
Access is not allowed to a requested
resource or operation.
404 Not Found Resource was not found.
500 Internal
Server Error
Error happened on server side. Default
handlers that provides such details as a
stack trace in response MUST be avoided.
Error design (including validation)
{
code: 1234,
message: “Validation failed”,
errors: [
{
field: “referenceEntityId”,
errorMessage: “Not found”
},
{
field: “name”,
errorMessage: “Name is required”
}
]
}
Use Content-Type for different schemas:
• application/json;profile=NoBodyError
• application/json;profile=NoParameterError
• application/json;profile=ValidationError
What else can be included:
• Link to documentation
• Error description
20. Take care of:
• All possible workflows
• Linked resources
• Actors
• Domain model
Design tips:
• Try treating actions as resources
• Use PATCH with complex payloads
• Use headers for meta information
Complex actions
Context: IT support system
Use cases:
1 Re-assign request
2 Enrich extra request information
3 Clone request
4 Grant permission to view requests
5 Transfer to another system
6 Merge requests
7 Lock/unlcok request
8 Change status
9 skip
21. 1 Re-assign request
2 Enrich extra request information
3 Clone request
Complex actions #2
1. PATCH /requests/{request_id}
{
assigneeId: <new_id>,
}
2. PUT /requests/{request_id}/environment {
{
osVersion: "MAC OS X...",
hardware: {…},
destination: "EXTERNAL NETWORK",
...
}
3. POST /requests
Content-Type: application/reference
X-Reference-Id: <requst_id>
X-Clone-Parameters: copy-attachments
22. 4 Grant permission to view
requests
5 Transfer to another system
Complex actions #3
4. PATCH /requests/{request_id}/acl
{ userId: <user_id>, permissions: "view,edit” }
5. POST /legacy_support/transfers
{ requestId: “1234” }
201 Created
{
transferId: "321",
status: "TRANSFERED",
originalRequestId: "1234",
legacyRequestId: "90189",
legacyLink: "http://old.support.company.net/requests/ID-
90189"
}
GET /legacy_support/requests/90189
301 Moved Permanently
Location: http://old.support.company.net/requests/ID-90189
27. 1.Control and monitoring
• Control what you publish
• Throttling
• Control changes
2.Versioning
• Use hard versioning by including API version to requests
• Use soft versioning: change responses by manipulating
headers
Development
32. type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
type Post {
id: Int!
title: String
author: Author
votes: Int
}
type Query {
author(id: Int!): Author
}
GraphQL
query PostsForAuthor {
author(id: 1) {
firstName
posts {
title
votes
}}}
--------------------
{
"data": {
"author": {
"firstName": "Tom",
"posts": [
{ "title": "Introduction to GraphQL",
"votes": 2 }
]
}
}}
33. What next?
Workshop (1 day):
• Define business case
• Go through iterative process and design API
• 10 steps
• From scratch to comprehensive design
• Implement according to specification
• Code generation
• Spring adaptation
• Deployment and access
What next?