简体   繁体   中英

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:

  1. One is to introduce state on the backend site, eg 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.
  2. Second idea is to introduce a new endpoint called eg /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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM