I'm trying to find some opinions on best practice for returning different types of data for the "same" endpoint. Surprisingly, I can't find much on this subject.
Basically, I am building an API for our website, which is a single-page app. The client uses caching to store data across pages and this data is updated as necessary by the server (using websockets). There are several routes that return a list of data. Each item in the list can potentially be quite large and the list itself can contain many items.
Since the frontend already uses caching, we want to reduce the amount of unnecessary data resent to the client where possible. One option to accomplish this is to provide a way for the frontend to obtain a list of the IDs of resources for a particular request. Based on this list, the client could then request the data it needs (i.e. if a cache miss occurs).
This approach is interesting, but it raises several questions.
- What if the frontend already knows it doesn't have any of the resources? Instead of requesting a list of IDs, it should be able to request the data directly.
- What is the best approach? Possible approaches and their (dis)advantages appear below.
Is there an approach not listed below that seems appropriate? Is there an approach I missed that might be better? Does this seem like overkill?
Just send the data - Nuclear option #1.
- Return type is consistent
- The client may already have much of the data, wasting bandwidth
Use the same route and declare a query param that determines the type of data to return - While not the worse option, it does seem dirty returning different types of data from the same endpoint (yes, I know you can specify
Content-Typein requests, but this header is telling the server what representation of the data is desired, not really what type of data to return).
- The client can determine when it wants the data or just the IDs
- Return type depends on the value of the query param
- Added conditional logic
Allow for field selection. - This approach follows Suggestion 7 on this blog.
- Added unnecessary complexity - Field selection doesn't make sense for our app. Therefore, the only valid value for this param would be the ID field
- The format of the data depends on the query param - while the data type is technically still the same, its structure is different in each request. Not something I really like.
Prepend the original route with
/ids- Clients would be able to send a GET request to the same path they would for the actual data prepended by
/ids. For example, instead of
/cars, the request would be sent to
- Seems more semantically meaningful than just using a query param
- GET would be the only logical request that would ever be sent to these endpoints
- DRY or added conditional logic - Either a new endpoint has to be added that basically duplicates the original endpoint or the same endpoint is used with the same conditional logic necessary for point 2
Use a value for
Content-Typeheaders similar to
application/json+id- This is an approach similar to the one used by LTI. The advantages and disadvantages (as far as I know) are the same as point 2.
Always send just the ID - Nuclear option #2.
- Return type is consistent
- Potentially results in less data being sent to the client
- Since the number of resources available could be high, this could result in many GET requests (200+) if the cache is (almost) empty, ultimately defeating the purpose of this approach
- Semantically less meaningful - I'm making a request for the resources, not their IDs!