Primary users/customers are developers of all levels.
- Scalability (Not performance, but extensible)
- Latency (Caching)
HATEOAS -> Hypermdedia As The Engine Of Application State
For clients, REST is easy. But for providers, REST is freaking hard.
And REST can be easy if following guidelines.
- Nouns, not verbs, not actions
- Coarse Grained, not Fine Grained
- Architectural style for use-case scalability
Give custome resources, let customers define the actual use cases.
Don’t add behaviors/actions to the end URL!
Keep it simple, fundamentally two types of resources:
- Collection resource:
- Instance resource:
DELETE are not equivalent to Create, Read, Update, Delete! At least it is not guaranteed.
GET is for read and
DELETE is for deletion.
POST can both be used for create and update.
PUT /application/clientSpecifiedId, all data need to be there for
PUTfor update: (Full replacement)
PUTcan not be used for partial update
POST as Create: Create on a parent resource:
POST as Update
POST is the only NOT idempotent operation, it can be used for partial update, or anything.
- Format Specification + Parsing Rules
When writing REST clients, always put
Accepted header so the server knows to return json to you.
Prefer the first one since it is concise and easy to understand
Rest Client vs Browser? No redirection.
http://api.foo.com/v1 vs Media-Type
URL is hard for API developers, Media-Type is hard for API users. URL scheme is more preferred.
Use coarse version numbers in URL scheme.
- Use camelCase as
- Date/Time/Timestamp: Use ISO 8601. And use UTC!
- Every accessible Resource has a unique URL
- Replaces IDs (IDs exist, but are opaque)
HREF is critical for linking.
POST? Return the representation in the response when feasible. And override
- Header values comma delimited in order of preference
- Hypermedia is paramount
- Linking is fundamental to scalability
- Tricky in JSON (XML has XLink, JSON doesn’t) How do we do it?
This is a separate resource from REST’s perspective
GET /accounts/x7y8z9?fields=givenName,surname,directory(name) to restrict the response data
Collection Resource supports query params:
e.g. Group to Account
- A group can have many accounts
- An account can be in many groups
- Each mapping is a resource:
- As descriptive as possible
- As much information as possible (security information should not be exposed!)
- Developers are your customers
- Avoid sessions when possible
- Authenticate every request if necessary
- Authorize based on resource content, NOT URL!
- Use existing protocal:
- Oauth 1.0a, Oauth2, Basic over SSL only
- Custom Authentication Scheme:
- Only if you provide client code/SDK
- Only if you really, really now what you’re doing
- Use API Keys instead of username/password combos
- 401 “Unauthorized” really means unauthenticated: You need valid credentials!
- 403 “Forbidden” really means unauthorized: You are not allowed!
- Server response to issue challenge:
WWW-Authenticate:<scheme name> realm="Application Name"
- Client request to submit credentials:
- Entropy (takes much longer time to brute force attack)
- Password Reset
- Speed (Bcrypt is more reliable than SHA1 and MD5)
- Limited Exposure
- IDs should be opaque
- Should be globally unique
- Avoid sequential numbers (contention, fucking)
- Good candidates: UUIDs,
- Server (initial response):
- ETag: “1234567890”
- Client (later request):
- If-None-Match: “1234567890”
- Server (later response):
304 Not Modified
- Use HTTP Redirects
- Create abstraction layer / endpoints when migrating
- Use well defined custom Media Types