18

I'm designing an API Rest service that allows the user to upload a file to the server.

I'm thinking this is a PUT request and it would go to server/resource/ID and have the file as base64 in the json request body.

My question is regarding this ID. In my head, I'm passing the file to the server and the server should be in charge of storing that file and generating a unique ID to retrieve it later, and then return this ID to the client with an ok status.

So I'm thinking about doing that, sending it to server/resource, without the ID, but is this ok or is it bad design?

ekad
  • 14,436
  • 26
  • 44
  • 46
David
  • 3,364
  • 10
  • 41
  • 84
  • If you want to create a new image, you should use POST, in which case the server would return the object with ID, so you're correct, you don't have to use an ID, but the method is also wrong. – Douwe de Haan Apr 13 '17 at 11:35
  • I strongly disagree with the comment by @Douwe. If you use POST N times you would create N files on your server. If you want to allow to upload only one file (so your logic is "override"), then you are idempotent and hence PUT is the right HTTP method for you. You don't have to provide an ID neither for PUT nor for POST. If you use POST, the URI of the ressource must not change. – antidote Mar 04 '21 at 11:39
  • 1
    @antidote With PUT you have to now _what_ you are replacing / overriding. This is usually done with an ID. The question clearly states the server is in charge of storing the file and generating a unique ID (not retrieving, generating, which suggests a new file). Since it is a new file and the user wants to return the ID to the client to know which image it was, I would suggest using POST. – Douwe de Haan Mar 04 '21 at 12:04
  • @Douwe, sorry I think I've overinterpreted your answer. The HTTP method depends on whether it's an image, which is uploaded to an "album", that would be POST, or it is a "passport" of which you can only upload one, then it would be PUT – antidote Mar 05 '21 at 13:11
  • @antidote that's interesting! Never thought about it that way. Would you also use PUT when the resource isn't existing yet? Like the first time you would upload something? I can get behind the idea, just wondering how to implement it exactly :) – Douwe de Haan Mar 08 '21 at 11:19
  • 1
    @DouwedeHaan yes! It's perfectly correct to use PUT, when the ressource does not exist: PUT is "SET". POST is "ADD TO THE LIST" – antidote May 02 '21 at 21:59
  • @antidote two years later, building a new system and remembered our conversation. Had to Google for a bit but found it again. Thanks! :) – Douwe de Haan Jun 07 '23 at 12:21

3 Answers3

24

Regarding the actual title of the question I somehow disagree with the accepted answer given by @TatsuyukiIshi. PUTs semantics are: Replace the content currently obtainable at the given URI with the payload contained in the request. If a resource can be identified without an ID, i.e. there only ever may exist one of its kind, it IS possible to address an update without specifying an ID as the ID of the "singleton resource" is already implicitly given in the endpoint itself. Though, I have to admit that this is rarely the case.

Such a case may be a clipboard like resource where you can put arbitrary content to and retrieve it later on. Sure, you could also use POST, though the semantics of the body received with the POST request are less clear. Also POST is not idempotent in contrary to PUT operations.

Using something like PUT /api/messages, however, would usually mean replace all messages with the content sent with the request which might not be what you really want. Usually you only want to modify a single resource at once and hence use an accompanying ID that identifies that specific resource.

In regards to the actual content of the question, uploading a file via POST is the common practice. On a successful upload you will return a 201 Created response that contains a Location HTTP header that points to the generated resource. The behavior of a service processing content received via POST requests is totaly up to the service implementor. Therefore you could create a new resource, perform some backing task without any actual resource creation or something other (even updating is not forbidden by the specification).

Douwe de Haan
  • 6,247
  • 1
  • 30
  • 45
Roman Vottner
  • 12,213
  • 5
  • 46
  • 63
  • With good normalization, a through-table with a compound foreign-key would be a perfect example. I would like to PUT an association there and I know the two keys that form a relation so it should be easy. However, modern frameworks require you to add id's to a through-table and you're left having to make up endpoints or ids. – jbodily Jul 20 '20 at 16:49
  • 1
    @jbodily Modern frameworks usually follow their own take on REST, which is usually very close to traditional RPC style, unfortunately. REST is furthermore not just a layer for exposing DB models via HTTP/S to the outside, but serves the dedicated purpose of decoupling clients from servers which allows the latter to evolve freely in future without having to fear breaking clients due to these changes. What most APIs/frameworks however do is unfortunately just the opposite of that. As such, I am not aware of any frameworks that truly support a REST architecture out of the box. – Roman Vottner Jul 20 '20 at 17:09
  • It's a shame really. I suspect it's why developers get muddled in REST and have started to lean towards frameworks like GraphQL, which throws all the REST benefits out the door. – jbodily Jul 20 '20 at 17:15
4

No. PUT means "create or update", and should come with an explicit ID. POST is suitable for creating something new.

See also: PUT vs POST in REST

Community
  • 1
  • 1
Tatsuyuki Ishi
  • 3,883
  • 3
  • 29
  • 41
  • 8
    NO! `PUT` has the semantics of `replace` not necessarily create or update! It can be used to update or create a resource, though it does this by actually just replacing the current representation, which might not yet be available, with the one provided in the payload of the request. A server may moreover validate and adapt the payload to fit its expectations (i.e. by adding additional links, apply the payload to a an other representation format and similar stuff) – Roman Vottner Oct 08 '19 at 11:54
-2

Too late for you, but I was with this same question and found a lot of wrong information, so I will let here what a found.

There are 2 RFC that rules RESTful, the one about this question is RFC 7231, in that you will find:

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.

So you can't send a PUT without the ID.

A lot of RESTful API send a POST even on updates, that's wrong too by that same RFC, so you should always send the ID to create it with PUT, or should use POST to create and PUT to update, but remember that POST should always create, in another words, you will duplicate your file if you don't look for it first with GET.

For more information: https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3

Community
  • 1
  • 1
Sirius
  • 354
  • 5
  • 15
  • 2
    In neither way does the HTTP spec state that an ID is necessary for PUT as all it requires is an URI, and how this is built is not of importance to applications following a REST architectural model. So whether it includes an ID or not is some implementation detail, nothing more. Next, `POST` is an all-purpose operations which needs to be used if none of the other operations is expressive enough, i.e. partial update if `PATCH` is not supported. Its semantics are only defined by the implementor and thus `POST` does not necessarily have to create resources! – Roman Vottner Aug 31 '18 at 14:18