Muhammad Bin Zafar
Posted on August 18, 2022
REST stands for "Representational State Transfer". This is an architectural style. A web API conforming to this style is a REST API.
REST stands on 6 guiding principles, important among them are:
- Client-server: separate backend and frontend.
- Stateless: each http request contains enough data (e.g. auth, session, user data) to understand it without knowing what the previous request was.
- Cacheable
- GET: always
- POST: using http headers
expire
,cache-control
,etag
,last-modified
- PUT, DELETE: never
π§ Concepts
The following are some important, concise, and simplified REST concepts a good backend dev must be familiarized with.
Resource
REST APIs are modeled as a resource hierarchy - where each node is either a collection, or a single resource. A single resource has some state, or sub-resources.
Example of a stateful resource is the following, where a user resource has data/states:
POST /users/:id
{
id: 4e7d418a70f,
name: 'muhammad',
country: 'earth',
verified: true
}
Example of a resource with sub-resources is the following, where a user has multiple projects, each of which are a resource.
GET /users/:id/projects
content-type: application/json
[
{
id: 'postman cli',
desc: 'postman implemented in command-line'
url: 'github.com/midnqp/postman-cli'
},
{
id: 'typescript',
desc: 'typescript is a superset of javascript',
url: 'github.com/microsoft/typescript'
}
]
Idempotency
API Idempotency means "a client can make a request multiple times, returning same response - without having any side-effect".
Making the following requests multiple times produces the same result, and has no further side-effect - thus are "idempotent" APIs:
-
GET /users/:id
- just retrieving same user data -
PUT /users
- just updating same json data -
DELETE /users/:id
- just deleteing the same user
A non-idempotent API:
-
POST /users/:id
- because a new user will be created everytime this request is made
π¨ Designs
Some constraints in REST API naming ensures a design of scalable API endpoints:
- Use plural nouns, e.g. users, orders, categories.
- Use hyphen, not underscores. Use lowercase, never camel-case, e.g.
GET /food-categories
, notGET /foodCategories
. -
Never use CRUD function names, e.g.
GET /users/list
orPOST /users/create
.
Some perfect API endpoints:
-
GET /users
- get a collection/list of users. -
GET /users/:id
- get a single user. -
POST /users/:id
- create a single user. -
PUT /users/:id
- update a single user. -
DELETE /users/:id
- delete a single user.
For sub-resources:
-
GET /users/:id/projects
- get projects of given user -
DELETE /users/:id/projects/:id
- remove a project of given user
Adding some features:
-
GET /users?country=earth&verified=true
- search users bycountry
andverified
-
GET /users?$fields=name,country
- list users, but return only 2 data attributes:name
andcountry
-
GET /users?$sort=name&$order=asc
- list users and sort byname
in ascending order -
GET /users/$page=1&$limit=10
- list users and paginate withpage
andlimit
π« Errors
Most Google APIs use resource-oriented API design. Instead of defining different NOT_FOUND
errors, the server uses one standard NOT_FOUND
status code, and tells the client which specific resource was not found.
The smaller error space has advantages:
- reduces the complexity of documentation
- better mapping
- reduces client logic complexity
Model
type Error = {
code: number
message: string
details: any[]
}
-
Error.code
: simple code, easily handled by client -
Error.message
: Developer-facing human-readable error -
Error.details
: Additional error information for client, such as retry info, help link, etc.
Code
- Individual APIs must avoid defining additional error codes.
- Developers must use canonical error codes.
- Standard error codes for Google APIs:
-
200 OK
, not an error; returned on success. -
500 UNKNOWN
, internal server error; unexpected and insufficient info -
400 INVALID_ARGUMENT
, invalid/problematic user data -
404 NOT_FOUND
, something doesn't exist globally, for everyone -
409 ALREADY_EXISTS
, something already exists -
403 PERMISSION_DENIED
, access denied for a user; relevant people have access -
401 UNAUTHENTICATED
, no bearer token; no valid auth creds -
429 RESOURCE_EXHAUSTED
, too many requests; rate-limit exceeded -
400 FAILED_PRECONDITION
, the operation was rejected; business logic unmet -
400 UNAVAILABLE
, the operation was rejected; user should retry
-
Message
Error messages should help users understand & resolve API errors easily.
- Do not assume the user to an expert user of the API.
- Do not assume user knows anything about service implementation.
- Should be constructed such that technical users can respond, and correct it.
- Keep the message brief. If needed, provide a link to more info, questions, feedback. Otherwise, use "details" field.
Posted on August 18, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.