REST API DELETE valid call - api

I am in a middle of a discussion here. Imagine that you have I want to delete all records from a collection using REST to https://api.example.com/files.
Is DELETE https://api.example.com/files a valid call?

You can refer published guidance regarding REST.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
It appears to be a valid scenario.
Similar discussion here: Is an entity body allowed for an HTTP DELETE request?

Is DELETE https://api.example.com/files a valid call?
Semantically, DELETE /files is no different from DELETE /anythingElse; that's the promise of the uniform interface, that all resources understand the methods to mean the same thing.
In the case of DELETE, the semantics are currently defined by RFC 7231.
The DELETE method requests that the origin server remove the association between the target resource and its current functionality. In effect, this method is similar to the rm command in UNIX: it expresses a deletion operation on the URI mapping of the origin server rather than an expectation that the previously associated information be deleted.
If your server happens to delete a bunch of rows in its data store when handling this request? That's just a side effect - it's an implementation detail of no concern to anyone other than the server itself.
In general, it is assumed that the origin server will only allow DELETE on resources for which it has a prescribed mechanism for accomplishing the deletion.
Relatively few resources allow the DELETE method -- its primary use is for remote authoring environments, where the user has some direction regarding its effect.

Related

What HTTP method should I use for an endpoint that updates a status field of multiple entities

I like to use the correct HTTP methods when I'm creating an API. And usually it's very straightforward. POST for creating entities, PUT for updating them, GET for retrieving etc.
But I have a use-case here where I will create an endpoint that updates the status of multiple objects given 1 identifier.
e.g.:
/api/v1/entity/update-status
But note that I mentioned multiple objects. The initial thought of my team would be to use map it as POST, but it won't actually be creating anything, plus if you were to call the same endpoint multiple times with the same identifier, nothing would change after the first time. Making it idempotent.
With this in mind, my idea was to create it as a PUT or even PATCH endpoint.
What do you smart people think?
I imagine PATCH would be the most correct way. Although if you use a PUT it would also not be incorrect.
The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI. In a PUT request, the enclosed entity
is considered to be a modified version of the resource stored on the
origin server, and the client is requesting that the stored version be
replaced. With PATCH, however, the enclosed entity contains a set of
instructions describing how a resource currently residing on the
origin server should be modified to produce a new version. The PATCH
method affects the resource identified by the Request-URI, and it also
MAY have side effects on other resources; i.e., new resources may be
created, or existing ones modified, by the application of a PATCH.
Whilst it is a convention in REST APIs that POST is used to create a resource it doesn't necessarily have to be constrained to this purpose.
Referring back to the definition of POST in RFC 7231:
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics. For example, POST is used for the following functions (among others):
Providing a block of data, such as the fields entered into an HTMl form, to a data-handling process
Posting a message to a bulletin board, newsgroup, mailing list, blog, or similar group of articles;
*Creating a new resource that has yet to be identified by the origin server; and *
Appending data to a resource's existing representation(s).
Clearly creation is only one of those purposes and updating existing resources is also legitimate.
The PUT operation is not appropriate for your intended operation because again, per RFC, a PUT is supposed to replace the content of the target resource (URL). The same also applies to PATCH but, since it is intended for partial updates of the target resource you can target it to the URL of the collection.
So I think your viable options are:
POST /api/v1/entity/update-status
PATCH /api/v1/entity
Personally, I would choose to go with the PATCH as I find it semantically more pleasing but the POST is not wrong. Using PATCH doesn't gain you anything in terms of communicating an idempotency guarantee to a consumer. Per RFC 5789: "PATCH is neither safe nor idempotent" which is the same as POST.

what would be the best practice for http request in webapi project with softdelete

I am working on a webapi .Net5 project. I am using SQLserver and EF5 to store my entities. Each of my entities has a property called IsDeleted, which I use for remove(IsDeleted=true) and restore(IsDeleted=false).
I am a bit confused which http request method should I use for my remove/restore endpoints.
I am updating a partial part of my entity (isdeleted), so I was thinking about PATCH
I also don't want to show the client that I am doing soft delete, then for remove, I was thinking about DELETE but I really do not delete any entity from my resources
I was also thinking about PUT, but in both cases, I do not have any request body and therefore it is very rare that a PUT method has not have any body .
I saw in some StackOverflow question and answers that they recommend to use a POST method for restore and DELETE for remove when using the soft delete but did not really understand why.
Anybody knows what would be the correct way of doing that and why?
Using HTTP DELETE to update IsDeleted = true is up to you as the API designer. There's no law saying HTTP DELETE must hard-delete whatever it refers to.
If the client does not know you're soft-deleting the record it'd be entirely appropriate to use DELETE.
I work with a system which has soft-delete, but it is not hidden from the client app / user. So to soft-delete it is either a PUT request to api/some_endpoint/24601 with "status": "ARCHIVED" within the payload, or a POST request to api/some_endpoint/24601/actions with a similar payload. (PATCH may be more appropriate than PUT but the API designers have stuck with PUT throughout.)

PUT vs POST in an audit-table or revision history situation

Let's say I have a REST method to update a record. That would obviously be a POST because it's updating a resource. However in the same motion, a new record in an audit or revision history table needs to be created.
Is there a standard or best practice here, of whether to use POST or PUT?
Does the REST method come from what is happening on the user side, or does it come from what happens in the database?
One possibility is to call just one method, which updates a record in one table and creates a new record in another table.
Another possibility would be to force that the POST only updates one table, and would require an additional method to do a PUT in the audit table. This forces the use of 2 methods and puts the responsibility on the developer, which I'm not too keen on.
PUT is actually recommended for the replacement (update) of an existing record.
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.
There is also some information about the difference between POST and PUT:
The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource.
See here.
To me it sounds like you should use a PUT request to update the resource. Auditing is a side-effect of doing that, and so it should be handled as part of PUTting the new resource.

What URI should I expect HTTP DELETEs at?

This is more of a conceptual integrity question for something that's been bothering me.
HTTP's DELETE method is supposed to be idempotent, and REST's URIs are supposed to actually represent things. But it seems to be only defined in the reverse direction: each resource must have one URI, but a given URI doesn't seem to need a resource. More charitably I guess URIs could be defined to point at empty/null resources.
The only time this seems actually relevant is in a DELETE request. Where is the best place to put it? example.com/users/ with the content identifying the resource to be deleted, or is example.com/users/USERNAME better?
Content in DELETE seems fine in HTTP and REST. (Conceptually: according to other SO questions various frameworks will silently drop content from DELETE requests before you can process it.)
So here's my thinking: every example seems to use the latter scheme--where you're deleting a resource at its URI, not deleting a resource from its parent collection URI--but the resource should stop existing after a successful DELETE. In which case the URI should fail loudly, imho. But that would negate the idempotence of DELETE, leading me to think that DELETE should operate on collections, with the content specifying the actual resource to be deleted.
Obviously everybody just does the thing that I don't like and I should probably go along with it for the sanity of my users, but is there anywhere where this is clearly spelled out, or obvious things that I'm missing that make me wrong?
According to the HTTP standard "The DELETE method requests that the origin server delete the resource identified by the Request-URI." - there's nothing about any sort of request body.
In which case the URI should fail loudly, imho. But that would negate the idempotence of DELETE
Just return a 404. The point of idempotence is, submitting the same DELETE request twice doesn't cause the server state to end up any different from having submitted it once. Failing doesn't cause a problem for that (unless the server shuts down or something)
A DELETE request should only apply to the URI of the resource you would like deleted. For deleting something via a collection, a POST or PUT to that collection would be more appropriate.
You can implement a response to the DELETE request by checking for the resource and deleting it if it exists and return 2xx, otherwise just return 2xx (e.g., in case duplicate requests were sent). The point of making the method idempotent is that it won't "fail loudly"—it isn't considered a failure at all. Just like how PUT doesn't differentiate between "create" and "update".

Confused about Http verbs

I get confused when and why should you use specific verbs in REST?
I know basic things like:
Get -> for retrieval
Post -> adding new entity
PUT -> updating
Delete -> for deleting
These attributes are to be used as per the operation I wrote above but I don't understand why?
What will happen if inside Get method in REST I add a new entity or inside POST I update an entity? or may be inside DELETE I add an entity. I know this may be a noob question but I need to understand it. It sounds very confusing to me.
#archil has an excellent explanation of the pitfalls of misusing the verbs, but I would point out that the rules are not quite as rigid as what you've described (at least as far as the protocol is concerned).
GET MUST be safe. That means that a GET request must not change the server state in any substantial way. (The server could do some extra work like logging the request, but will not update any data.)
PUT and DELETE MUST be idempotent. That means that multiple calls to the same URI will have the same effect as one call. So for example, if you want to change a person's name from "Jon" to "Jack" and you do it with a PUT request, that's OK because you could do it one time or 100 times and the person's name would still have been updated to "Jack".
POST makes no guarantees about safety or idempotency. That means you can technically do whatever you want with a POST request. However, you will lose any advantage that clients can take of those assumptions. For example, you could use POST to do a search, which is semantically more of a GET request. There won't be any problems, but browsers (or proxies or other agents) would never cache the results of that search because it can't assume that nothing changed as a result of the request. Further, web crawlers would never perform a POST request because it could not assume the operation was safe.
The entire HTML version of the world wide web gets along pretty well without PUT or DELETE and it's perfectly fine to do deletes or updates with POST, but if you can support PUT and DELETE for updates and deletes (and other idempotent operations) it's just a little better because agents can assume that the operation is idempotent.
See the official W3C documentation for the real nitty gritty on safety and idempotency.
Protocol is protocol. It is meant to define every rule related to it. Http is protocol too. All of above rules (including http verb rules) are defined by http protocol, and the usage is defined by http protocol. If you do not follow these rules, only you will understand what happens inside your service. It will not follow rules of the protocol and will be confusing for other users. There was an example, one time, about famous photo site (does not matter which) that did delete pictures with GET request. Once the user of that site installed the google desktop search program, that archieves the pages locally. As that program knew that GET operations are only used to get data, and should not affect anything, it made GET requests to every available url (including those GET-delete urls). As the user was logged in and the cookie was in browser, there were no authorization problems. And the result - all of the user photos were deleted on server, because of incorrect usage of http protocol and GET verb. That's why you should always follow the rules of protocol you are using. Although technically possible, it is not right to override defined rules.
Using GET to delete a resource would be like having a function named and documented to add something to an array that deletes something from the array under the hood. REST has only a few well defined methods (the HTTP verbs). Users of your service will expect that your service stick to these definition otherwise it's not a RESTful web service.
If you do so, you cannot claim that your interface is RESTful. The REST principle mandates that the specified verbs perform the actions that you have mentioned. If they don't, then it can't be called a RESTful interface.