5

This may be easiest to explain with an example use case.

Let's say I have an e-commerce site where users can add items to their shopping cart. When adding items to the cart, users can type in the quantity that they want to add, and then click an Add button. Clicking Add will send a request to the server. The server will first validate that the current inventory has enough of the item to meet the requested quantity, if there are enough it adds the item to the cart and returns a successful response, otherwise it returns an error response.

To enhance the user experience, it would be nice to validate the quantity the user entered before they even click Add. This would require sending a request to the server which will check if clicking Add would result in an error, but it will not commit any changes to the cart if there is no error.

A coworker of mine suggested adding a query parameter ?intent=validate to any endpoints that require this kind of functionality. This sounds like a good idea because I will not have to create extra endpoints.

Are there any common conventions for REST APIs to handle this kind of "validate but don't commit anything" request? Does the ?intent=validate approach raise any red flags?


UPDATE:

Thanks for the feedback, but I should probably clarify some things.

  1. I am not really working on an e-commerce site, I just used that for an easy to explain example. Really I am working with a document management platform.
  2. Users may be requesting bulk actions like moving 100 documents and folders to a folder. There are many things that need to be validated for any such request, like the user's rights over the documents and folders, name collisions, not moving a folder into itself, etc. So I really want to validate every time a user checks a checkbox in a list of documents to move.
  3. The API will still validate when a user clicks Submit to commit their changes, because there are other users performing actions at the same time. The point is to give users early feedback, so they don't spend time checking 100 boxes only to find out that they need to rename 2 of the documents before committing.
  4. There are many other bulk requests in this system that need to be treated the same way, such as modifying user rights over objects, bulk deletes, assigning multiple users to user groups, etc. So it would be nice if each type of request did not require separate validate and commit endpoints.
  • 2
    Your validation will not be valid until actual purchase time. Consider making a "intended order", valid for e.g. 15 minutes, similar to many event ticket-selling webshops. This will keep requested amount of your stock unavailable for purchase for the specified time, and if the stock runs out you can show an appropriate message to your users like "temporarily out of stock, check back in x minutes". – Lauri Laanti Sep 23 '17 at 19:59
4

With a REST API, is there a convention for clients validate a request without committing any changes?

Not really, not in the way that you mean. REST doesn't care what spelling you are using for your identifiers; in REST, URI are opaque. The client just follows the links that are provided.

So you could send the validate the data to /c255ed19-d6b0-4666-b9cc-abc48d4246ae and the actual "do it" request to fbb43bdf-0016-4aa1-9f55-28b884238d40 and as far as REST is concerned, those spellings are fine.

So changing the resource identifier to include an intent=validate parameter in the URI is fine. If you instead decided to distinguish the intent by using a different spelling in the path segments, that's also fine. REST doesn't care; any meaning encoded into URI is done at the discretion of the server and for its own exclusive use.

Of course, if the spelling of the URI is opaque, then that spelling doesn't communicate any useful semantics. There must be an extra layer of indirection somewhere; in REST, that somewhere is a link -- the relation type is the out of band information that the client and server agree upon in advance. In an ideal case, the relation that you need is already standardized; you can check in the link relations registry to see if the information you need is there. If not, you can create a bespoke extention relation type, and assign it a meaning.

<link rel="http://example.org/relations/validateOrder" target="/c255ed19-d6b0-4666-b9cc-abc48d4246ae" />
<link rel="http://example.org/relations/placeOrder" target="/fbb43bdf-0016-4aa1-9f55-28b884238d40" />

You can mint your own identifiers to define these relations, or you can look for matches among the schemas that already exist

<link rel="http://schema.org/CheckAction" target="/c255ed19-d6b0-4666-b9cc-abc48d4246ae" />
<link rel="http://schema.org/OrderAction" target="/fbb43bdf-0016-4aa1-9f55-28b884238d40" />
2

For GET requests you can use HEAD verb as this is more or less what it is intended for (e.g. should give you a server status code). For POST you COULD try to roll OPTIONS.

However, i believe largely these are semantics. Because specific to a given use case you actually need two distinct APIs - /validate and /order, both taking POST requests. This expresses the intent in the most clear way.

1

The trouble with your validate message is that it will be immediately out of date.

Usually e-commerce sites will accept your order regardless of stock levels as they can always order more stock in, delay your delivery or as a last resort just email an apology.

If you do need to implement it, I would have a separate 'request stock level' message.

-2

Answer for document management problem.

You should validate client side with js logic, send the request, validate server side, throw a validation error if there is a problem.

You can skip the client side validation, but it makes the return message from the server complicated as you will want a list of the validation failures.

Its much cleaner to just throw on the first fail and return a single error. But obviously this leads to a bad user experience of correct, submit, correct, submit...

Client side validation allows you to have the expectation that your submission will succeed and only fail in the hopefully rare cases where something has changed on the server since you got the logic and data required for the client side verification.

Obviously in order to do this validation the client needs extra information, say the list of files in the target directory. It will have to get this info via a separate request.

But you could consider using websockets to update the client when that list changes on the server. This would keep the client up to date with changes and minimise the chance of a server side error with the minimum number of messages exchanged

  • The validation must be done server side because the client doesn't necessarily know about all the files already in the target folder, or all the relevant permissions information, etc. – JamesFaix Sep 25 '17 at 13:08
  • "Obviously in order to do this validation the client needs extra information, say the list of files in the target directory. It will have to get this info via a separate request" – Ewan Sep 25 '17 at 13:17
  • plz read before voting – Ewan Sep 25 '17 at 13:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.