Restful way to delete a write-protected resource - rest

In my API, resources can be write-protected. Trying to DELETE such a resource will return a 409 (Conflict) response.
For users that are allowed to change the protected state of a resource, I want to introduce the option to delete protected resources with one request. How should this option be passed?
Possible solutions:
Request body -- should not be used with delete requests
Query parameter -- changes the URI, so technically refers to a different resource
Custom header -- generally discouraged
Standard header -- none apply
Two requests -- not atomic, things could happen in-between (eg another user modifying the resource)
Alternative endpoint -- not restful?
Related Questions
In REST API, can DELETE methods have parameters?
Answer says yes to query parameters, but asks about deleting a subset of a collection
REST, HTTP DELETE and parameters
Asks about a confirmation flag, answers say it should be handled in UI instead of API
Also says it violates the uniform interface principle, but doesn't explain why and how
Also argues that using query parameters would violate URI principle
RESTful Alternatives to DELETE Request Body
Accepted answer says to use the body, but many commenters report technical issues
Query parameters are suggested as alternative, concern about URI principle is raised
Is an entity body allowed for an HTTP DELETE request?
Says not to use the request body, even if technically allowed
Whats the best way to design DELETE for a restful resource
Says to use query parameters, but again in a subset context

For users that are allowed to change the protected state of a resource, I want to introduce the option to delete protected resources with one request. How should this option be passed?
If the meaning of the request message is consistent with HTTP DELETE, then you should probably just use HTTP DELETE, rather than trying to invent a dialect that allows you to discriminate between DELETE and no-no-I-really-mean-it-DELETE.
Are your message semantics consistent with HTTP DELETE? You may want to consider this observation in RFC 9110
Relatively few resources allow the DELETE method -- its primary use is for remote authoring environments, where the user has some direction regarding its effect.
DELETE is the method token we send to a web server when we want that server to stop sharing representations of a resource. It's semantics are rooted in the transfer of documents over a network domain.
On the other hand, if the message isn't consistent with HTTP DELETE, then you should consider using HTTP POST.
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009
Here's a way of thinking about the distinction: our goal in creating a "REST API" is to create a facade that disguises our domain service as an HTTP-aware document store.
If what the client is really doing is marking a document as hidden in the store; and as a side effect of that we may make a bunch of changes in our domain service, then DELETE is appropriate.
On the other hand, if what the client is really doing is sending information to our domain service, and as a side effect some documents are going to be hidden, then POST is appropriate.

Related

Are PUT and DELETE HTTP methods indispensable just because of their idempotency property?

I have a REST API and I want to handle all HTTP requests via POST request.
Is there any performance or other kind of issue in using just POST to perform all CRUD operations requested by a user, which sends a JSON containing some data and the operation to be performed?
Technically, the HTML used in the Web only supports GET and POST and this is more or less the reference implementation of a REST architecture.
So, while this is possible I wouldn't advocate for something like that as the idempotency property of PUT and DELETE provide some other benefits in case of network issues where a client can automatically resend the request regardless whether the initial request, whose response might have just got lost mid-way, actually performed its task or not. The result should always be an updated/created resource or a removed URI mapping to the actual resource (or even a removal of the actual resource) as DELETE technically just removes the URI mapping.
In regards to put some operations in the payload, it depends. This actually sounds very RPCy to me, similar to SOAP i.e. If the operation however is defined by a well-defined media-type, like in the JSON Patch case, I guess this is not wrong. Similar to the Web, however, a server should use some resource that is able to teach a client on how to build up a request, like HTML does with forms. This will not only teach the client on what fields the server supports for the target resource but also where to send the request to as well as the media-type and HTTP operation to use, which might be fixed to POST as in the HTML case.

Should I use a POST request to send a retrieval request to my server for a large array of ids?

I read the following posts; however, I still haven't found a conclusive answer to my question.
When do you use POST and when do you use GET?
How should I choose between GET and POST methods in HTML forms?
So why should we use POST instead of GET for posting data? [duplicate]
I want to make a HTTP request to my server to retrieve some data based on an array of ids that I will pass to the server. Since each id will have a length of 23 characters, sending 100 of these ids as query parameters of a GET request will exceed the character length limit of some browsers. Since a standard GET request is not feasible due to URL limits, I have been considering my other options.
Option 1: Use request body of HTTP GET request (not advisable according to following SO thread)
HTTP GET with request body
Option 2: Use body of HTTP POST request to send the array of Ids. This is the method that Dropbox appear to have used for their public-facing API.
I know that POST requests should be reserved for requests that are not idempotent and in my case, I should be using a GET request because the query is idempotent. I also know that REST is purely a guideline and since this API will only be consumed by me, I can do whatever I like; however, I thought I'd get a second opinion on the matter before I commit to any decision.
So, what should I do in my situation? Are there better alternatives that I have yet to discover and is there anything I should consider if I do use a POST request?
So, what should I do in my situation?
First step is to review the HTTP Method Registry, which is defined within RFC 7231
Additional methods, outside the scope of this specification, have been standardized for use in HTTP. All such methods ought to be registered within the "Hypertext Transfer Protocol (HTTP) Method Registry" maintained by IANA
The registry is currently here: https://www.iana.org/assignments/http-methods/http-methods.xhtml
So you can review methods that have already been standardized, to see if any of them have matching semantics.
In your case, you are trying to communicate a query with a message-body. As a rule, queries are not merely idempotent but also safe.
A quick skim of the registry might lead you to consider SEARCH
SEARCH is a safe method; it does not have any significance other than executing a query and returning a query result
That looks like a good option, until you read through the specification carefully, and notice the constraints relating the message body. In short, WebDAV probably isn't what you want.
But maybe something else is a fit.
A second option is to consider your search idiom to be a protocol. You POST (or PUT, or PATCH) the ids to the server to create a resource, and then GET a representation of that resource when you want the results.
By itself, that's not quite the single call and response that you want. What it does do is set you up to be thinking about how to be returning a representation of query result resource. In particular, you can use Content-Location to communicate to intermediaries that the response body is in fact the representation of a resource.
I know that POST requests should be reserved for requests that are not idempotent
That's not quite right. When making requests that align with the semantics of another method, we prefer using that other method so that intermediate components can take advantage of the semantics: an idempotent request can be tried, a safe request can be pre-fetched, and so on. Because POST doesn't offer those guarantees, clients cannot take advantage of them even if they happen to apply.
Depending on how you need to manage the origin servers URI namespace, you could use PUT -- conceptually, the query and the results are dual to one another, so can be thought of as two different representations of the same thing. You might manage this with media types - one for the request, a different one for the response.
That gets you back idempotent, but it doesn't get you safe.
I suspect safe requests with payloads are always going to be a problem; the Vary header in HTTP doesn't have an affordance to allow the server to announce that the returned representation depends on the request body (in part because GET isn't supposed to have a request body), so it's going to be difficult for an intermediate component to understand the caching implications of the request body.
I did come across another alternative method from another SO thread, which was to tunnel a GET request using POST/PUT method by adding the X-HTTP-Method-Override request header. Do you think its a legitimate solution to my question?
No, I don't think it solves your problem at all. X-HTTP-Method-Override (and its variant spellings) are for method tunneling, not method-override-the-specification-ing. X-HTTP-Method-Override: GET tells the server that the payload has no defined semantics, which puts you back into the same boat as just using a GET request.

RESTful Web Api chain Do I use POST or GET?

If I am calling a Web APi service and that service makes various other calls to other services, do I use POST or GET?
To elaborate further, let's say I call Web Api Service One saying 'Do the thing'. Web Api One's job when requested thus, is to GET data from Service Two and POST data to Service Three. Perhaps Service One will then update Service Two. Service One will then respond to caller with any success/failure.
My question again is should I the caller, use POST or GET to Service One?
It's all about the semantics of the request. From the RFC 7231:
The request method token is the primary source of request semantics;
it indicates the purpose for which the client has made this request
and what is expected by the client as a successful result.
Here's a brief description of some HTTP methods defined in the RFC RFC 7231 (click the links to check the full method definition):
GET: Transfer a current representation of the target resource.
HEAD: Same as GET, but only transfer the status line and header section.
POST: Perform resource-specific processing on the request payload.
PUT: Replace all current representations of the target resource with the request payload.
DELETE: Remove all current representations of the target resource
In addition to the methods listed above, the RFC 5789 standardized the PATCH HTTP method for performing partial updates to a resource.
POST is commonly seen as a "catch all" method, once the target resource process the request payload according to the resource's own specific semantics.
HTTP methods can be classified as safe and/or idempotent and it must be taken into account when designing an API with on the top of HTTP.
Typically I would only use a variety of HTTP verbs (GET, POST, PUT, DELETE etc) when using a REST API. Then the endpoints are resources in their own right. For example:
/car
So the verbs make sense (are you getting a car? creating one? updating one? removing one?)
But when I am not using a REST API the HTTP verbs tend to have less meaning and I generally only use HTTP POST. Otherwise you hit logical problems like you're experiencing here.
eg
/rentacar
This API models an RPC that may cause many resources to change in many ways. It is not a REST API and so the HTTP Verbs don't really relate.
But in honesty, for RPC (remote procedure calls), people choose between GET and POST by either:
GET for operations that don’t modify anything and POST for other cases.
GET for operations that don’t need too much parameters and POST for other cases.
GET and POST on a random basis or always use POST.
Purists prefer 1. But sometimes you don't know when modifications are going to occur. So, take your pick!

How should "weak" resources be handled in a RESTful website?

In RESTful websites, each resource should be identified by an URI. But how should I handle what are called "weak entities" in relational databases, aka, ressources that only make sense when related to another resource? Should these have specific URIs pointing to them too?
To give an example: Say I have a website for showing events going on in a city. Each event can have comments posted by users.
An event is a resource, with corresponding URI (/events/:id).
But should each comment have an URI, too? Like /events/:eventid/comments/:commentid ? Comments only make sense when they're associated with the corresponding event, so having a page just to represent one message seems weird/unnecessary. I only want the comments to appear on the page of the event.
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
An event is a resource, with corresponding URI (/events/:id).
But should each comment have an URI, too? Like /events/:eventid/comments/:commentid ?
If comment is a resource, it must have an identifier, but it doesn't mean that you have to support all operations for such resource. The server can return a response with the 405 status code if a method is not supported by the target resource:
6.5.5. 405 Method Not Allowed
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. [...]
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
Return a representation of the comment with the given identifier.
In RESTful websites, each resource should be identified by an URI. But how should I handle what are called "weak entities" in relational databases, aka, ressources that only make sense when related to another resource? Should these have specific URIs pointing to them too?
It depends. An important thing to recognize is that resources and entities are not one to one. You are allowed to have many resources (web pages) that include information from the same entity.
Jim Webber described the distinction this way
The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation.
Domain Driven Design for Restful Systems
I guess the /events/:eventid/comments/:commentid URI could be used for a DELETE request, but what should it return to a GET request?
As noted by Cassio, 405 Method Not Allowed is the correct status code to use if the client erroneously sends a request with an unsupported method. OPTIONS is the appropriate mechanism for informing a client of which methods are currently supported by a resource.
You could also have it respond by redirecting the client to the /events/:eventId resource; it might even make sense to take advantage of URI Fragment support, and redirect the client to /events/:eventid#:commentid - allowing the client to use its own fragment discovery to identify the specific comment within the representation of the event.
Or, if there are useful integrations that you want to support, you could simply have this resource return a representation that exposes the integrations.
It really depends on how the client wants to work with the domain. Would an app want to get a list of all the comments for an event? Are users allowed to update their commments? Or are they anonymous comments?
If you plan to only ever use the same page to display the backend information of events and comments, then you prolly don't need a separate comments api. If you want to open the dataset to app vendors (perhaps you might want to develop an app in future) a comments api would be handy. i.e. get all comments for an event.

How to deal with per verb permission in Rest on a client?

Lets assume we have a resource on an URL like so: foo.com/api/bar
And lets say that a user might be allowed to GET that resource, but not allowed to POST to that resource.
I can easily solve that by specifying different permissions per verb.
But how should the client know on beforhand if it is allowed to perform the POST?
Lets say we have a "save" button on a page, that should not be enabled if the user lacks the rights to do a POST.
I know about HATEOAS/Hypermedia constraint, and that I can pass a list of links for different actions together with the resource.
But AFAIK, that doesn't carry information on what verbs to use, only URL's for different actions.
Are there other variations where the verb is included?
Are there other approaches if you don't want to clutter the resource with all sorts of metadata?
This has been asked a lot on the HAL discuss forums https://groups.google.com/forum/#!forum/hal-discuss
The fact that verbs aren't returned is a decision of the hypermedia format you're using, which i'm guessing is HAL (or maybe collection+json). Some formats DO include verb information.
HAL actually allows you to include custom fields on your link objects if you wish, but i would discourage this because any standard client won't know how to interpret this.
But also i've found the verb to be worthless in the end.
First off in human 2 machine the user is going to read documentation. HAL has all of it's links dereference (via CURIE's as they are currently naemd) to human readable documentation that should describe the effects of requesting that link with different parameters, verbs, headers, etc.
Next off is that for your Application to be truly RESTful you should respond to all verbs...you might just not respond that the verb was OK. For an HTTP based app returning a 405 is VERY appropriate. Returning a 404 is not! A 500 would be worse!. Your 405 should include what methods are available for the requested resource.
Next in the case of machine 2 machine (and a bit of h2m) your application when accessed via HTTP (i try to avoid http in my answers as RESTful applications aren't necessarily HTTP..although i'd say 101% of them are) should use the OPTIONS method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) against the resource URL in order to get a description of what's possible.
Here's where i see a lot of people getting tripped up, what should the response of OPTIONS be? well what people forget is content type negotiation! The requester should say what format for option information they expect. Accept: some-machine-language/xml or application/language+json. Some RFC or standards define these content types and your API can identify what formats it supports. I would suggest you include support for text/html so that you can return human readable documentation as well about what verbs are supported. This covers the h2m scenario nicely.
The same content type negotiation can be useful when returning info about a method not being supported. The server can send a content-type that the client can understand that describes semantically what methods are allowed.
The final thing i like to point out is that methods imply client intent. i want to PUT this resource or DELETE that resource. The server should accept requests and return responses indicated what state transitions occurred because of that request. Thus it's a little silly to have the API identify possible intents of the client with every request. The client knows what it wants to do, it should try, and if it can't then it should deal with that.
HTTP Verbs are pure transport protocol verbs. Those might not be the right verbs to do application functions, precisely because of the issues you mentioned in the question. So let us see if we can approach this differently without using http verbs. Doing http verbs to do appliction actions might limit us tommorrow as we might have need to move from http to another protocol.
LEt us take an example to illustrate. Let us say we are talking about Update Delete application using HATEOAS. So in this case, if the there are two products, represented by the URL www.abc.com/product/001 and www.abc.com/product/002. In a true HATEOAS situation, If the response of the two products product/001 and product/002 has to be looked at show the client screens.
So if the response to product/001 has a response product/001/delete,product/001/change and product/002 has the response product/002/Change then the client will show delete for only product/001 and change for the other two products.
So in response to your question. By appropriately identifying actions with product now it is possible to do role based actions.
I hope i have answered your question.