6

I am developing a REST service, and one of my server-side operations manipulates the DB in a way that may take a while, but once the operation has started, the DB cannot be recovered (this is a constraint that comes from the system we are using on our server. I might be able to change it in later versions, but for now we are stuck with this constraint). The result is that I need an "ok/cancel" dialog with a warning, before allowing the operation to run.

At first I wanted to put the logic of creating the dialog on the client-side, but that seems to violate HATEOAS (for example, if I do change the framework on my server side, the dialog won't be needed, but I won't want to change the client if my API stays the same). My next solution was returning a response with the warning, and an ok that links to a different POST operation, but I am unsure on when to send my parameters. Do I send the parameters in the first POST? If so, how do they get to the second POST (without holding application state, of course)? Sending the parameters only to the second POST isn't an option since only HATEOAS will determine if the second one is needed.

I have found a similar question here: REST, HTTP DELETE and parameters But this has 2 problems:

  1. It doesn't solve our problem (because he only adds a parameter on the second try, but I need to carry my parameters with me from the first).
  2. DELETE has to conform to "Uniform Interface". He does make a valid point that not all clients necessarily need confirmation, but putting the whole dialog in UI brings me back to our problem of what happens if I improve my server-side app.

I would be happy to hear your thoughts on the matter.

P.S: This is my first post on stackoverflow.com (after years of using it to find answers for questions that were asked before me), so please forgive me if the format of the question isn't quite right (you are welcome to correct me, of course).

Community
  • 1
  • 1
  • You could generate a token to "confirm" or authorize the DELETE. For example, `POST /confirmations` returns a 201 with the confirmation entity. Then said entity is passed to `DELETE /users/1` via HTTP headers. – jchook Oct 25 '16 at 20:10
  • you could first make a request to get a token and when you send that token on second request the action happens. – The Fool Aug 14 '21 at 16:30

3 Answers3

1

One of your server-side operations needs confirmation before it can be executed. The way I see it this means two different calls, which may for example mean to first check that you need the confirmation and then doing the actual action.

For example, you may request that the client first does a GET to see if a confirmation is required and retrieve the message to display, then do the actual POST with the action. If you don't have a GET request first, the POST may return a 4xx (maybe 412?) error.

BUT, keep in mind that no matter what you do, you need cooperation from the client. Even if the server does receive a GET request, the client may receive the response, not show the confirmation and doing the post anyway, it's not something you can solve 100% server side.

ChatterOne
  • 3,381
  • 1
  • 18
  • 24
0

I would not modify the semantics of DELETE, like one of the solutions in the linked article (returning a 4xx to force a new request). It would surprise most people to have the DELETE not work, and surprises should be avoided when possible.

My first idea was, that you could solve it similarly to what confirmation dialogs do in HTML. That is put some code into the links, or maybe some flags to indicate that it needs confirmation to be deleted:

<a rel="something" onDelete="confirm" href="..."/>
<a rel="something" onDelete="showConfirmation()" href="..."/>

This seems OK at first, but is that really a property of the links? Well, reading your description of the problem it seems that you are defining some capability of the POST operation itself to be either present or not. This capability is recoverability or rollbackability? So if the client needs to detect some capability of an operation, it could use an OPTIONS request like this:

OPTIONS /something/abc HTTP/1.1
...

200 OK
Allow: GET,HEAD,POST,OPTIONS,TRACE
...
<body describing confirmation dialogs, messages, etc>

So basically you could announce the capability through a custom representation for OPTIONS. The specification explicitly allows this (https://www.rfc-editor.org/rfc/rfc7231#section-4.3.7):

A server generating a successful response to OPTIONS SHOULD send any header fields that might indicate optional features implemented by the server and applicable to the target resource (e.g., Allow), including potential extensions not defined by this specification.

Community
  • 1
  • 1
Robert Bräutigam
  • 7,514
  • 1
  • 20
  • 38
0

How about requiring a one time server side generated token for the critical operation? So the client would always need to first fire another, non-critical request, to acquire the token. The critical call can only be made using that token. So in that case acquiring the token is the act of the initiation and sending the token to the critical endpoint is the confirmation.

All the details required for the operations should be sent with the first request, so the token would only confirm that particular set of parameters. In the second request only the token is needed, any other parameters required for the operation must have been sent already and encoded or identified in/by the token.

This way the client cannot accidentally call the critical request or use another token to confirm an unrelated operation, without explicitly requesting it first, which is in one sense a confirmation, as a single "mistake" cannot lead to an unexpected outcome.

Surely, the client may still decide to perform both rounds without prompting the user, but that is not much we can do about.

Bence Szalai
  • 768
  • 8
  • 20