REST bulk endpoint for fetching data - api

We(producer for the API) have an endpoint
/users/:{id}/name
which is used to retrieve name for the user 'id'
Now as a consumer I want to display the list of names for users like:
user1: id1, name1
uder2: id2, name2
where I have the ids in input.
In such a case should I make 2(here the list is dependent on UI pagination example 50) separate calls to the API to fetch information or else create/ask the producer to create a bulk endpoint like:
POST /users/name
body: { ids: []}
If later, then am I not loosing the REST principle here to fetch information using POST but not GET? If former, then I am not putting too much network overhead in the system?
Also since this seems to be a very common usecase, if we choose the POST method is there really a need of the GET endpoint since the POST endpoint can handle a single user as well?
Which approach should be chosen?

A GET API call should be used for fetching data. Since browser knows GET calls are idempotent, it can handle some situations on its own, like make another call if previous fails.
Since REST calls are lightweight, we tend to overuse API call repeatedly. In your case, since you want all name v/s id mapping at once, one call is sufficient. Or have a Aggregator endpoint in backend API gateway to reduce network traffic and make repeated calls nearer to actual service.
Keeping GET /users/:{id}/name , is also not a bad idea alongside this. It helps to abstract business functionality. A particular scenario can only allow single fetch.
Also using GET /users/name with pagination and returning list of names is complex for single use so keeping both are fine.

Related

How to define REST API with to Parameter

I am currently working on a REST API for a project. In the process I should search for events. I would like to make an endpoint for searching events in a period. That is, specify two parameters with from - to.
For the search you normally take a GET operation. My question is now it makes sense to specify two parameters in the path or should I rather fall back to a POST operation for something like that.
Example for the path /Events{From}{To}
Is this even feasible with multiple parameters?
If you are not making a change on the resource, you should use GET operation.
More detailed explanation:
If you were writing a plain old RPC API call, they could technically interchangeable as long as the processing server side were no different between both calls. However, in order for the call to be RESTful, calling the endpoint via the GET method should have a distinct functionality (which is to get resource(s)) from the POST method (which is to create new resources).
GET request with multiple parameters: /events?param1=value1&param2=value2
GET request with an array as parameter: /events?param=value1,value2,value3

Ember change normalizeResponse based on queried model

I'm using a second datastore with my Ember app, so I can communicate with a separate external API. I have no control over this API.
With a DS.JSONSerializer I can add some missing properties like id:
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
if (requestType == 'query') {
payload.forEach(function(el, index) {
payload[index].id = index
})
}
Now I can do some different tricks for each different requestType. But every response is parsed. Now sometimes a response from one request needs to be parsed differently.
So what I am trying to do is change the normalizeResponse functionality for each different request path (mapped to a fake model using pathForType in an adapter for this store). But the argument store is always the same (obviously) and the argument promaryModelClass is always "unknown mixin" - not sure if this can be any help.
How can I find what model was requested? With this information I could do a switch() in normalizeResponse.
Is there a different way to achieve my goal that does not require me to make a separate adapter for every path/model?
There are over a dozen normalize functions available. Something should work for what I am trying to achieve.
I think this is a great example of a use case of not using ember data.
Assuming that you have models A,B,C that are all working great with ember data, leave those alone.
I'd create a separate service and make raw requests to that different endpoint. So you'd replace this.store.query('thing', {args}) with a separate service that uses ember-ajax (or ember-fetch or whatever). If you need, you can use that service to hold the data that you need (Ember-data is just a service anyway) or you can create models and push them into the store manually.
Without knowing more about your exact situation, hard to give a specific code/advice, but I'd just avoid this problem and write your own custom service.
You can use primaryModelClass.modelName.

Which resource should I use to keep my API RESTFul?

I'm building an API to allow the client of the API to send notifications to remind a user to update an Order status. So far, there are two notifications:
when the user hasn't marked the order as received;
when the user hasn't marked the order as done.
I want to build this API to make it simple to extend to other notifications related to the order, but keep a simple URI for the clients of this API.
How can I define my resources in order to keep my API RESTFul?
I was thinking about having one of these structures:
Option 1:
POST: /api/ordernotification/receive/{id}
POST: /api/ordernotification/complete/{id}
Option 2 (omit the status from the resource and post it instead):
POST: /api/ordernotification/?id={id}&statusID={statusID}
EDIT
Option 2.1 (keeping an articulated URI, as suggested by #Jazimov):
POST: /api/ordernotification/{statusID}/{id}.
Which option is more appropriate? Is there any advantage that one option has over the other? Or are there any other option I haven't thought of?
I would go with something along these lines
POST /api/order/1234/notifications/not-received
POST /api/order/1234/notifications/not-completed
Which can later be accessed via
GET /api/order/1234/notifications/not-received
GET /api/order/1234/notifications/not-completed
Or
GET /api/order/1234/notification/8899
There's no real limitation on how semantically rich a URI can be, so you might as well take advantage of that and be explicit.
If I understand you correctly, you have two types of ordernotifications: those for notifying receive and those for notifying complete. If those are two separate data models then I think nesting them is a good idea (i.e. a table called ReceiveOrderNotification and CompleteOrderNotification). If that's the case then you may want to expose two different endpoints entirely, such as POST /api/receiveordernotification and POST /api/completeordernotification.
But I don't think that's the best you can do, given so many overlapping similarities there probably are between order notifications. Now, option 2 is more like a GET, since you're using query parameters, so with your first option let's collapse them into this:
POST: /api/ordernotification/
and then pass it some JSON data to create the notifications
{
"orderId": "orderId",
"userId": "userId",
"prompt": "not marked received/not marked done"
}
I also removed the /{id} because when you POST you create a brand new thing and the id has not been created yet, usually. Even if the client is creating an id and sending it to the API it is a good practice to leave it open so your API can handle creating a new, unique resource in its own way.
This is RESTful is because a POST creates a resource ordernotification with certain data points. Your first option made actions a resource in themselves but that's probably not represented in any data model in your backend. To be as RESTful as possible, your API endpoints should represent the database domains (tables, collections, etc). Then you let your controllers choose what service methods to use given the data sent in the request. Otherwise REST endpoints expose all the logic up front and get to be a long list of unmaintainable endpoints.
I think, to update status of already inserted records, your endpoint should be PUT instead of POST.
You can use
PUT: /api/ordernotification/:id/status/
with clients json data
{
"status": "your_status"
}
according to request data, endpoint should update the record.

How to design a RESTful API that queries info about a verb (e.g. a potential POST request)?

I'm learning how to design a RESTful API and I've come across a quandary.
Say I have a POST endpoint to perform an action. The action has a certain cost associated with it. The cost depends on what the action is, particularly, on the body of the POST. For example, given these two requests:
POST /flooblinate
{"intensity": 50, "colorful": true, "blargs": [{"norg": 43}]}
POST /flooblinate
{"intensity": 100, "colorful": false, "blargs": []}
Say the first one costs 500 and the second one costs 740.
I want to create a method which will tell me what the cost of posting the action will be. Since I am not creating or updating anything, it seems that GET is the most appropriate verb. However, a request body with GET should not have any meaning. This means that I'd have to put the data in the query string, say by URL encoding the request body to be passed to the POST:
GET /flooblinate/getCost?body=%7B%22intensity%22%3A+50%2C+%22colorful%22%3A+true%2C+%22blargs%22%3A+%5B%7B%22norg%22%3A+43%7D%5D%7D
This seems less than ideal since it's two data formats for the same thing. But the following:
POST /flooblinate/getCost
{"intensity": 50, "colorful": true, "blargs": [{"norg": 43}]}
This also seems less than ideal since it's abusing the POST verb to query information, instead of to create or update something.
What's the correct choice to make, here? Is there any third alternative? Is there a way to rethink this design fundamentally which will obviate the need to make this choice?
Personally I'm not for adding dryRyn flags. I try to avoid boolean flags in general unless they're really required.
I've two ideas to cover this scenario:
One is to introduce state on the backend site, e.g. STARTED, FINISHED. When given resource action is submitted it has STARTED state and calculated cost which cam be viewed via GET method. Such resource may be modified with PUT and PATCH methods and is submitted when given method changes its state to FINISHED. Resources that didn't change its state for given amount of time are removed are their state is changed to other terminal value.
Second idea is to introduce a new endpoint called e.g. /calculations. If you need to calculate the cost of given action you just send the same payload (via POST) to this endpoint and in return a cost is given. Then resource send may be kept on server for some established TTL or kept forever.
In all the scenarios given (including yours) there's a need to make at least two requests.
The nicest choice here seems to be to have the endpoints return the info that need querying, and add a dryRun parameter to those endpoints. Thus:
POST /flooblinate?dryRun=true
{"intensity": 50, "colorful": true, "blargs": [{"norg": 43}]}
Returns:
{"cost": 500, /* whatever else */
And then posting with dryRun=false actually commits the action.

mvc4 passing data between paging action and views

i have an action which will invoke a service (not database)to get some data for display,and i want to do paging on these data.however,every time a second page is clicked,it will invoke this action and of course invoke the service again,actually when i click the first page link,it already generate the whole data including what the second page needs. i just want to invoke the service once and get all the data,and later when paging,i don't need to invoke the service again,how can i deal with that?hope someone could give me a hint~
There are several ways to address this. If it's practical and a limited amount of data, it's ok to return the entire data set in the first request.
If that's your case I would consider returning a pure JSON object when you load the page initially. You can then deserialize this into a JS object variable on the web page that you can perform your paging operations against. This is an example of client side paging where all the data exists client side.
Another approach is to do Ajax based paging where you request the data for the next page as needed. I would still recommend returning JSON in this scenario as well.
The two approaches differ in that the first one returns all the data upfront, whereas the second one only returns what you need to render any given page.