Rest API Developer's Dilemma
Resource Name: Singular or Plural
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
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.
Requesting the next page
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,
- page number you are looking for
- page size
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.
- offset: for an index of the item in the collection.
- limit: for the count of items.
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.
Query Parameter or Header
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.
GET or POST for login
Most use POST for login request, since it doesn't show the password in the URL. 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.
The Right Status Code
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.
The need for nested resource
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.
But for a GET request, when you can access a resource from /coffee/256, then what is the purpose of a nested resource call?
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
- Fetch required information about the order associated with coffee.
which a coffee resource call alone cannot achieve.