I'm writing an HTTP based API, and I have a situation where the user specifies a resource, and if that resource doesn't yet exist the server creates it. It's basically built on top of Django's get_or_create
method.
What would be the most idiomatic/correct HTTP method to use in this situation?
I'm suspecting that POST
would be proper. However, I'm not entirety sure. Though it seems that GET
would be incorrect seeing as it's not supposed to have any side-effects.
POST is the only RESTful API HTTP method that primarily operates on resource collections. When creating a subordinate resource in a collection, applying POST to the parent resource prompts it to create a new resource, associate it with the proper hierarchy and return a dedicated URL for later reference.
The HTTP GET method is used to **read** (or retrieve) a representation of a resource. In the “happy” (or non-error) path, GET returns a representation in XML or JSON and an HTTP response code of 200 (OK).
Can I use GET request instead of PUT to create resources? You can, but the only way to pass data in a GET request is by the URL itself.
The primary or most commonly-used HTTP methods are POST, GET, PUT, PATCH, and DELETE. These methods correspond to create, read, update, and delete (or CRUD) operations, respectively. There are a number of other methods, too, but they are utilized less frequently.
I would use GET
for this. Repeated calls to this end point will return the same resource, so it's still Idempotent.
A GET
request expresses the user's intent to not have any side effects. Naturally, there will always be side effects on the server like log entries for example, but the important distinction here is whether the user had asked for a side effect or not.
Another reason to stay away from GET
surfaces if you respond with the recommended 201 Created
response for a request where the resource is being created on the server. The next request would result in a different response with status 200 OK
and thus it cannot be cached as is usually the case with GET
requests.
Instead, I would suggest to use PUT
, which is defined as
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem.
In the above form, it should be considered a "create or update" action.
To implement pure "get or create" you could respond with 409 Conflict
in case an update would result in a different state.
However, especially if you are looking for idempotence, you might find that "create or update" semantics could actually be a better fit than "get or create". This depends heavily on the use case though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With