0

So, I'm building out a PHP-based CMS application that is grounded in RESTful principles (though it certainly veers from them), and I've run into a bit of a dilemma:

What is the proper HTTP status to return when POSTing a form that uploads multiple files and some uploads succeed while others fail due to filename conflict? "409 Conflict" seems to make sense for each individual failed upload, but for the overall POST, which comprises an array of successful and failed uploads, it doesn't seem so clear cut.

My confusion is predicated on my perception that a multifile upload constitutes a single POST request, not one POST request for each file being uploaded. Is that correct?

Eric Fuller
  • 159
  • 1
  • 8
  • In what ways do you think it veers from them? – Jonathan W Oct 21 '13 at 01:48
  • I use session variables to enable persistent authentication instead of re-authenticating on each request. It's also possible to call the login form by adding /login to the end of any URI. Regarding my main question, maybe I should think of this in terms of the submission results page instead of the file uploads. In a sense , the request to the server is to post multiple files, so I suppose it makes sense for a successful response to bundle the results of each upload attempt, which is what happens. But, it just seems strange to return a '200 OK' when errors have occurred. – Eric Fuller Oct 21 '13 at 01:58
  • Session variables and server state nothing to do with REST. But that's a whole other discussion. :) Think about what would happen if you were to PUT the collection resource after a successful POST. You should get the same result no matter how many times you PUT. – Jonathan W Oct 21 '13 at 02:05
  • My understanding is that REST requires total statelessness, but yes, another discussion indeed ;). Anyway, I'm not quite sure I follow what you're suggesting. Are you suggesting chained requests (the initial POST followed by a PUT for each file) or just a way of looking at it so that "200 OK" makes more sense to me? Either way, PUT and DELETE aren't in play (another deviation from REST) as the host server doesn't support them. I have considered chained requests if I really can't come to terms with "200 OK" for a POST with file upload errors. – Eric Fuller Oct 21 '13 at 02:26
  • I think the dilemma you're dealing with stems from you not treating the collection of uploaded files as an in-tact unit. Rather, you're treating it as a way to batch up a bunch of file uploads together. If the collection doesn't have a semantic meaning to your application, why don't you just send separate POSTs? – Jonathan W Oct 21 '13 at 02:35
  • The group of files does have semantic meaning at the application level. If, for example, the collection resource is designated as a "Gallery", then only images or videos may be added. I'm looking at the target collection as the cohesive unit and the batched files being uploaded as a set of individual resources to be added to it. – Eric Fuller Oct 21 '13 at 03:48

1 Answers1

4

You are correct. If you are POSTing a collection, the collection itself is the resource. So if the collection resource was created, you'd return a 201. If it was accepted but not fully processed, you'd return a 202.

If you are implementing parts of the resource on the server with multiple files and there are already existing files that get in the way of a successful POST, you'd return a 409 and not create the collection resource and fail the whole operation. From the REST perspective, it's an atomic operation.

If, on the other hand, you were to support a PUT operation for this resource, you have to support idempotency. So one behavior might be to simply replace any files that were existing as part of the resource with what's being included with the PUT body. You could consider doing this as well for a POST, but that will only work if the existing file names belong to at most one collection resource. Otherwise you might end up trashing someone else's collection.

Jonathan W
  • 3,759
  • 19
  • 20
  • Wow, what great insight, thanks! The third paragraph kind of blew my mind ;). [This thread](http://stackoverflow.com/questions/107390/whats-the-difference-between-a-post-and-a-put-http-request) really helped me understand better. I think a POST that reels off a series of PUTs is highly applicable to my scenario, as the form is specifically for adding resources the collection from which the form is accessed (I'm pretty sure this form is also not RESTful; simply adding /add to any URI calls it up). If the PUTs encountered conflict I think I would abort the POST w/409 and give the user options. – Eric Fuller Oct 21 '13 at 03:00
  • A POST can't reel off a series of PUTs. Rather, what happens is a POST can be implemented by updating a series of files on your server. If any one of those fail, abort the POST with 409. Try to avoid racking your brain on what parts of what you're doing are or are not RESTful. REST is an architectural style characterized by 6 constraints (1 of which is optional). Confine the architecture to those 6, and it's RESTful. REST, therefore, is not applicable to a form by itself, or anything really to do with a URL (other than using it for resource identification). – Jonathan W Oct 21 '13 at 03:28
  • Well, fwiw, my goal really isn't to ensure the application is perfectly RESTful, although admittedly the further I go down this path the further I am called down this path, and I do tend to over think things ;). As for a POST reeling off PUTs, the link I included suggests a POST points to a resource that processes enclosed resource data, whereas a PUT references the enclosed resource itself. I interpret that to mean a POST resource could process a collection of resources by creating a PUT request for each one. Whether or not that thread and/or my interpretation is accurate is another matter ;) – Eric Fuller Oct 21 '13 at 03:58