Design Decisions API Developers need to take for effective REST API.
Convenience Things can have irregular plural names. Sometimes they don't have one. But Singular names are always there
/order/12/orderdetail/4
is more readable and logical than /orders/12/orderdetails/4
Database Table A resource represents an entity like a database table. It should have a logical singular name. Here's the answer over table names.
Class Mapping Classes are always singular. ORM tools generate tables with same names as class names. As more and more tools are being used, singular names are becoming a standard.
When requesting a collection resource, a bulk GET request will fetch all the records by default. So the request is broken down into pages i.e. pagination. To achieve pagination what you need to tell the server is,
Sending the page size with page number will make the server do the following calculation.
page_start = (total_records/page_size)*(page_no-1)
The server needs to query the database and first figure out the total number of records (total_records). That's the concern in this approach.
Another approach is to use query parameters.
The client can simply keep updating the offset as follows for the next page.
offset = offset + limit
For the previous page, update the offset and keep the limit same.
offset = offset - limit
SQL already has rownum and limit variables that can be used along with existing query to fetch the page records. So this method is more efficient.
The information passed in the header DOES NOT uniquely identify a resource or a subset of it. Let's say an auth resource is used to authenticate a user. I cannot share this link with my friend if it contains my login information. The login information needs to be passed as a header or a POST request. The same goes for response type. There are already standard headers following this.
So where to place the pagination parameter? It cannot be placed in the URI since URI is used to identify resources. A page is not a resource, but a subset of the resource collection. Since pagination is generally a GET request, query parameters are best suited for pagination. This helps save the URL.
Most websites POST for login request, since it doesn't show the password in the URL. This is due structual difference between GET and POST requests. But if we look from the REST perspective, it doesn't seem to fit in its architectural style.
Let's have a resource called login. A POST request is not idempotent and it should create a record. But it doesn't in case of login resource. It only gives back information about the user, which is consistent after each POST request i.e idempotent.
What are we doing wrong here? Firstly let's change the name from login to auth and get a token back for the response. So each time a POST request is made a new auth token is generated. This is known as token-based authentication. And REST APIs use it since they are stateless and need this token in each subsequent request.
While sending a response back to the app, the REST API developer needs to include a status code. The status code helps the app to identify and process the response better. There are many standard status codes which are understood by the browser (1XX to 5XX). And many APIs have used their own conventions and extended the usage as per their needs. 4XX erros most important to tell the rest client about its errors.
Here is a whole list of status codes a rest api can use.
The use of the nested resource is well known for POST call. To create a record of child resource using the parent id as the foreign key.
POST /order/32/coffee
But for a GET request, when you can access a resource from /coffee/256, then what is the purpose of a nested resource call?
GET /order/32/coffee/256
If coffee is dependent on order, then in the database coffee should have a foreign key for the order number. coffee number and order number are both primary keys. The SQL query written to process this request can
Check foreign key constraint
which a coffee resource call alone cannot achieve.
The API should not work on contextual information and maintain session on the server. The API should request the user to send all the paramters along with authentication keys in header and payload. All the information required for processing must be passed in each of the request.
Log all the errors with their request information. This helps to simulate the error with user request data and trace the error. The aim of logging request is to help those debugging the error.
Do not log all the requests and responses, unless you want do intrusion detection and your API is the entry point. It will be an overhead for the server. Usually servers are placed in front of API server for access logs for detecting intrusion.