0

I'm working on a server developing REST API.

The structure by now (at least what is needed to know for this question) is that I have a products collection retrievable via GET /products, GET /products/:id. I want to be able to edit these products, but I want to be able also to make drafts. This will be useful for save the edits but apply them only when done and make a history of the edits.

I thought that a possible way could be develop this endpoints:

GET /products/:id/drafts
 this will retrieve all the drafts made for this product

GET /products/:id/draft
 this will retrieve the last non applied draft, if any

POST /products/:id/draft/apply
 this will apply the last non applied draft, if any

To this point, all seems fine, but I am struggling finding a good way for handling the creation of the drafts. I thought that it could be POST /products/:id/drafts but, because of there can be only one draft a time, should this response with 409 Conflict if is there any non applied draft yet?

So I thought that it could be PATCH /products/:id, so if there is yet a non applied draft, then it will be edited else it will be created. Could it be done?

Can the PATCH /products/:id return a representation of the draft (created or edited)?

Is it better the POST approach described before?

Is there another way that I can't think of?

1 Answers1

0

You seem to be trying to change the semantics of PATCH, which is not a good idea.

HTTP includes methods that support remote authoring use cases; for instance, if I wanted to change the title of the home page on my web site, the sequence of steps might look like

GET /home.html
200 OK
Content-Type: text/html

<html>...

(make local changes)

PUT /home.html
Content-Type: text/html

<html>...
200 OK

Now, if home.html were very big (relative to the size of the standard HTTP headers) and the changes we were making were very small, then we might instead want to send a patch document instead of sending the entire mostly unchanged file.

PATCH /home.html
Content-Type: text/prs.patch

????
200 OK

If we wanted to create a draft, using the general purpose remote authoring interface, then our sequence of requests would look something like

GET /documents/123
PUT /drafts/456

and publish would look something like

GET /drafts/456
PUT /documents/123

What it sounds like you want is to achieve this without sending the documents over the wire, allowing the server to manage the process. The usual way to do that is with POST

POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”

POST /documents/123

???
201 Created
Location: /drafts/456
POST /drafts/456

???
200 OK

The server would use the payload of the POST requests to resolve any ambiguity that might be introduced by having multiple "not worth standardizing" actions.

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • Thank you. I written `/products/:id/drafts` because I want to keep the drafts collection linked to the product resource. If I understood what you are saying, I could use `POST /products/:id/drafts` to create a new draft or edit the last non applied one and in the header include the location to that draft resource. Then use all the other endpoints as I described in the question. Should this work so? – Giuliano Collacchioni May 28 '20 at 17:13