POST or PUT instead of DELETE when delete is blocked at web server - api

We have an crud API developed with POST, PUT, DELETE and GET methods supported. We have since discovered that DELETE is blocked at web server level in our organization so any requests to the API for DELETE via browser are blocked. We were informed to update our API to a POST for supporting DELETE. In the delete request Our API then calls another API with a DELETE request which is supported.
So the flow is
browser -> PUT/POST -> ourAPI -> DELETE -> anotherAPI
The old URI was DELETE /{entity}/{code}
I am updating to /{entity}/{code}/delete - but unsure if it makes more sense as a PUT or POST, I know POST isn't idempotent but the DELETE request to second API will be.
Thanks

Whether to use POST or PUT could depend on how attempting to delete a non-existent entity should be handled.
If the request should succeed silently as if the entity existed, the action is idempotent - so PUT seems appropriate.
If the request should trigger an error (404 or at least server-side logging), POST seems appropriate.

It doesn't really matter as long as it's clear to the users.
Here's and example of a POST delete from this very site: https://api.stackexchange.com/docs/delete-answer.

Related

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.)

REST API DELETE valid call

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.

what should be HTTP status code if resource is not available for requested action?

I am developing a RESTful API. I am confused about setting HTTP status code in this particular scenario. I am not sure what status code should I (server) return.
Let's say my app has a follow user functionality, if I am already following a user and again I send follow request for the same user id then in this case what should be the HTTP status code from server. The status code will be followed by an error message saying something like: "already following the user."
Similar scenario can be considered for unfollow user functionality, if I am not following an user "A", still I send request to unfollow user "A", then what HTTP status code should server return with error message something like "not following user to unfollow"
Certainly 200 response code doesn't seem to be appropriate to me here? or does it?
Please forgive me if I have posted the question at wrong stack exchange site, I posted it in stackoverflow site just because it is related to REST APIs.
EDIT
From client side user needs to send POST request to the URL:
http://www.myserver.com/api/follow/10
along with other necessary parameters ( like API keys, proper headers, etc) which are used for authentication before serving the requests at server side.
similar URL for unfollow action is:
http://www.myserver.com/api/unfollow/10
Right now, I am sending HTTP status code 200 in response if the client sends follow request, let's say, for user id 10 even if he/she is already following the user with id 10. In this case,along with status code (200) I am sending message similar to "already following the user"
Somehow I feel this is not convincing as no resource is created/updated it should return the error message with proper status code something other than 200, may be one from 4XX, not sure.
422 Unprocessable Entity
422 seems to be the proper HTTP status code in this use case.
The description of 422 says:
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions.
The answer depends on your API. You're describing the API in terms of "follow user X" or "unfollow user Y". That makes me think you might be approaching your API design in an RPC style rather than focusing on resources.
If your API uses REST including the HATEOAS principle, then error codes from the 4xx range may be appropriate (but I would recommend against it in this case, see below). In very short: HATEOAS means that your resources provide links to possible "actions". You can read more about it here: http://restcookbook.com/Basics/hateoas/
Apart from that, it seems a good idea to design your API "fault tolerant", i.e. expect the same request sent multiple times (e.g. because users are impatient and click again and again, or the browser crashed and is restarted and reopens all previous tabs, or...).
My personal opinion and recommendation is the following:
follow user X: Your implementation should check if it needs to add the new follower or not. Regardless, if the user is already following or not, send back HTTP status 201 (created) and add the "Location" HTTP header pointing at the resource.
unfollow user X: Your implementation should check if it needs to delete the follower or not. Regardless, if the user is already removed from the followers or not, send back HTTP status 200 (OK).
The general idea is, if a client requests something to be a certain way and that is already the case, the server has two options: Either it responds to the client "The result you wish is already in place. Therefore your request is invalid." or the server can respond "The result you wish is already in place. You have everything you need.".
Going for the second option makes the API more tolerant and helps with idempotency (see http://restcookbook.com/HTTP%20Methods/idempotency/).
I think djlauk's answer covers a lot, but I want to give a little different approach and add some information:
Do not use verbs in the URI
I would not use POST on /follow/ respectively /unfollow/ URIs because this is not very RESTful see this SO question: Why does including an action verb in the URI in a REST implementation violate the protocol? and escpacially this SO answer: How to create REST URLs without verbs?
Do use the correct HTTP verbs for the actions
What you want to do is a creation of an entity ("follow") so for that you can use the HTTP verbs POST or PUT and afterwards the deletion of that entity ("unfollow") where DELETE would be the right fit.
My approach for your API:
I would do the following:
(The first two examples are just for explaining the structure, you don't have to implement them if you don't need them.)
This does get you the user "robert":
GET http://www.myserver.com/api/users/robert/
response: #200
This does get you the users "robert" is following:
GET http://www.myserver.com/api/users/robert/following/
response: #200
And this is how you let "robert" follow "rahul":
PUT http://www.myserver.com/api/users/robert/following/rahul
response: #200
If you send this request again you get the same response:#200 because PUT is idempotent and this is how it should behave (see (2))
When you now want to let "robert" unfollow "rahul" you send:
DELETE http://www.myserver.com/api/users/robert/following/rahul
response: #200
If you send the DELETE request again you get a little different response a #404 , but this is HTTP standard and the clients should understand this.
For the regular answer codes of HTTP methods I can also recommend this source: restapitutorial.com
I would use some of the following:
System.Net.HttpStatusCode.ServiceUnavailable;
System.Net.HttpStatusCode.MethodNotAllowed;
System.Net.HttpStatusCode.BadRequest;
Better if it is one of the first two.
Certainly 200 response code will not work in this situation.
following are the groups in HTTP Status Code:
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error
Certainly you need to use 4xx.
I think for the condition that you have described here, you can use any of the following:
405 Method Not Allowed
A request was made of a resource using a request method not supported by that resource; for example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource.
400 Bad Request
The server cannot or will not process the request due to something that is perceived to be a client error
409 Conflict
Indicates that the request could not be processed because of conflict in the request, such as an edit conflict in the case of multiple updates.
More details are available here:
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

In HTTP, does PUT and POST send data differently?

From what I know you can send JSON data via POST, but should PUT be specifically sending information in the URI or can you do both?
Thanks!
Both POST and PUT can be used for create and update operations in different situations. So what exactly is the difference between PUT and POST?
In a nutshell: use PUT if and only if you know both the URL where the resource will live, and the entirety of the contents of the resource. Otherwise, use POST.
POST is an incredibly general verb. Because it promises neither safety nor idempotence, and it has a relatively loosely-worded description in the RFC, you can use it for pretty much anything. In fact, you could make all of your requests POST requests because POST makes very few promises; it can behave like a GET, a PUT, or a DELETE if it wants to. It also can do some things that no other verb can do - it can create a new resource at a URL different from the URL in the HTTP request; and it can modify part of a resource without changing the whole thing (although the proposed but not widely-accepted PATCH method can do something similar).
PUT is a much more restrictive verb. It takes a complete resource and stores it at the given URL. If there was a resource there previously, it is replaced; if not, a new one is created. These properties support idempotence, which a naive create or update operation might not. I suspect this may be why PUT is defined the way it is; it's an idempotent operation which allows the client to send information to the server.
References:
RFC 2616 - HTTP 1.1
RFC 5789 - PATCH method for HTTP
Martin Fowler, the Richardson Maturity Model
From HTTP's point of view, the request format is the same.
You can send the request body the same way, it is just handled differently by your application code...
The POST verb is traditionally used to create a resource
The PUT verb is traditionally used to update a resource
PUT uploads a new resource on the server. If the resource already exists and is different, it is replaced; if it doesn't exist, it is created.
POST triggers an action on the server. It has side-effects and can be used to trigger an order, modify a database, post a message in a forum, or other actions.

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".