Usage of 405 Method Not Allowed

118 views
Skip to first unread message

Mark Derricutt

unread,
Sep 1, 2014, 1:23:24 AM9/1/14
to api-...@googlegroups.com
Hey all,

A question came up in the office today about handling resources that can
move into a read-only state. For example, we have a resource say

/api/customer/32

which can get GET/PUT/DELETE'd, once we DELETE the resource it's removed
from active service and can no longer be modified, and any sub-resources
related to it are also deactivated, but a read-only view of the resource
can still get GET'd, the question is whether subsequent PUT/DELETE calls
against the resource should return a '405 METHOD NOT ALLOWED' after the
first DELETE is successful.

This initial arose from discussions around the idempotency of DELETEs
and should subsequent DELETEs trigger errors or no-ops - we settled on
errors but questioned what the expected error should be. It's not a 410
or a 404, since it still responds to a GET request, but changing the
list of allowed methods over time isn't something I've seen in any
existing APIs, or something that's kinda exposed in my HTTP/REST
libraries in anyway that suggests it being "normal".

APIs like Jax-RS seemed to automatically define that list based on
methods being annotated with @Get etc., Restlet (which I'm using) does
however separate these out to having 'allowDelete' and 'allowPut' style
methods, and I see the latest version actually changed to 'Set<Method>
getAllowedMethods()' so that almost answers my question itself...

But I thought I'd ask you great minds for your thoughts...

Cheers
Mark

Dmitry Pavlov

unread,
Sep 1, 2014, 1:39:41 AM9/1/14
to api-...@googlegroups.com
If DELETE does not actually deletes, maybe change the way of interacting with resource? Let's say instead of sending DELETE you PUT or PATCH with a field like "readOnly" or smth. to "true" thus making your object transition to a new state in which you can read it, but not delete.
To me if we want to preserve idempotent behaviour here it's better to always return 202 ACCEPTED whether it's the first time when you make actions to make object readOnly or latter times when it's already there. This behaviour looks more consistent to me.



Mark

--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+unsubscribe@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft.
For more options, visit https://groups.google.com/d/optout.



--
С уважением,
Дмитрий Павлов

Philippe Mougin

unread,
Sep 1, 2014, 5:43:44 AM9/1/14
to api-...@googlegroups.com
Hi Mark,

Dynamically changing the list of allowed methods on a resource is fine; it is even described as a possibility in the HTTP spec.
However your usage of DELETE as a mean to turn a resource into read-only state is not compliant with HTTP semantics.

Philippe
> --
> You received this message because you are subscribed to the Google Groups "API Craft" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.

Owen Rubel

unread,
Sep 1, 2014, 12:11:50 PM9/1/14
to api-...@googlegroups.com
Disagree. DELETE does not always 'delete'; sometimes it is a status change as poster is suggesting.

The way I have handled this in the past is with roles. ADMINS can see resource in any STATUS so upon delete, AMIN ROLE can still GET resource but USER ROLE cannot. This makes it so upon a request, ADMIN can change resource status or look it up.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.

mca

unread,
Sep 1, 2014, 12:24:54 PM9/1/14
to api-...@googlegroups.com
Mark:

<snip>
should subsequent DELETEs trigger errors or no-ops
</snip>
this is totally a _design_ decision, not a protocol one. T-SQL handles repeated DELETEs of the same item as a no-op. Most file systems handle it as an error.

<snip>
 we settled on errors but questioned what the expected error should be
</snip>
again, a design decision and you proly want to balance security w/ visibility. returning 405s for select operations may provide attackers w/ some encouragement while returning 404s may not. returning 404 for an attempt to DELETE/PUT/POST and 200k w/ body for GET is proly pretty confusing for client-side devs, tho ;) one design model i've seen is using DELETE to invalidate the resource URL permanently (404) while, at the same time, publishing the same resource at a new "read-only" archive URL (/archives/users/123). this helps cut down on client dev confusion on what DELETE really does for that system.

finally, method availability varies quite a bit at runtime in systems i design. usually due to security context (e.g. guests can't execute DELETEs, registered users can), location (admins get 404s for financial data when they are outside the VPN), or availability (everyone gets 405 when attempting to post a batch to the server during our 1hr "close-the-books" period each night).

hope this helps.



Mark

--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+unsubscribe@googlegroups.com.

Irakli Nadareishvili

unread,
Sep 1, 2014, 2:12:01 PM9/1/14
to api-...@googlegroups.com
They way you have defined the semantics of DELETE on that resource, it is still idempotent.

Your definition says: "issuing a DELETE on /object/object_id makes the object read-only". Do subsequent requests make the object non-read-only or have any other side-effects? No. So the operation is read-only regardless of what return status code is first time vs. next time. That is irrelevant for idempotency.

As for: whether you should be u sing DELETE for what you are doing. Well, the previous edition of HTTP 1.1 (RFC2616) was pretty clear about it: "no", since this is what RFC2616 said: 

"The DELETE method requests that the origin server delete the resource identified by the Request-URI"

You are not deleting the resource, hence you were violating HTTP/1.1. However, HTTP 1.1 has been revised and re-documented, making HTTP DELETE a little  bit less strict http://tools.ietf.org/html/rfc7231#section-4.3.5 

"The DELETE method requests that the origin server remove the association between the target resource and its current functionality. "

I don't think the way you use DELETE violates the words of the new definition. It is still an odd usage, considering the "spirit" of the definition. Most importantly: it is confusing. Many API clients have well-established understanding of what HTTP DELETE should do in an API, and you are not doing that.

I would replace the usage of DELETE with an HTTP PUT, to avoid confusion, if nothing else.

– Irakli
http://twitter.com/inadarei
http://freshblurbs.com

Mark Derricutt

unread,
Sep 1, 2014, 4:37:15 PM9/1/14
to api-...@googlegroups.com

On 1 Sep 2014, at 21:43, Philippe Mougin wrote:

Dynamically changing the list of allowed methods on a resource is fine; it is even described as a possibility in the HTTP spec.

I see that HTTPbis clarified that actually, and added an extra "current state" reference.

However your usage of DELETE as a mean to turn a resource into read-only state is not compliant with HTTP semantics.

We've discussed this at work and don't agree, HTTPbis also was clarified/updated to leave the what "delete" means to your application content rather ambiguous:

"The DELETE method requests that the origin server remove the
association between the target resource and its current
functionality."

which seems fine with what where doing, but then it does also follow that with:

"...it expresses a deletion operation on the URI mapping of the
origin server, rather than an expectation that the previously
associated information be deleted."

Which does imply a read-only version may still exist, but maybe not via the same URI.

Cheers
Mark

Philippe Mougin

unread,
Sep 1, 2014, 5:28:25 PM9/1/14
to api-...@googlegroups.com
Le 1 sept. 2014 à 22:36, Mark Derricutt <ma...@talios.com> a écrit :

On 1 Sep 2014, at 21:43, Philippe Mougin wrote:

Dynamically changing the list of allowed methods on a resource is fine; it is even described as a possibility in the HTTP spec.

I see that HTTPbis clarified that actually, and added an extra "current state" reference.

However your usage of DELETE as a mean to turn a resource into read-only state is not compliant with HTTP semantics.

We've discussed this at work and don't agree, HTTPbis also was clarified/updated to leave the what "delete" means to your application content rather ambiguous:

"The DELETE method requests that the origin server remove the
association between the target resource and its current
functionality."

which seems fine with what where doing,

No because there is still some part of the association you aren't removing. "the association between the target resource and its current functionality" should be shut down as a whole.  When I say "remove your car from my backyard" I mean remove the whole damn car, not just a part of it !
Besides, this is how DELETE has always been understood and documented. You might want to innovate and give it a new interpretation but since you are asking for thoughts I would say that's a bad idea.

but then it does also follow that with:

"...it expresses a deletion operation on the URI mapping of the
origin server, rather than an expectation that the previously
associated information be deleted."

Which does imply a read-only version may still exist, but maybe not via the same URI.

The information once provided by the resource may still exist and may be available by other means but the resource itself should be seen by the client as deleted.
Doing otherwise is riding against the grain and breaking expectations of your API's users. In, say, a C++ API it would be like creating a method named "+" that would implement multiplication instead of addition. 

Philippe 

Mark Derricutt

unread,
Sep 1, 2014, 6:37:27 PM9/1/14
to api-...@googlegroups.com
Ironically - most people here and picking on the choice of DELETE, which
whilst maybe valid, is quite incidental to the main question at hand.

If I'd used a put with "readonly=true" like others suggested, then the
question of response code in subsequent requests is still valid, and
thankfully to others - answered.

Chris Mullins

unread,
Jan 27, 2015, 3:21:41 PM1/27/15
to api-...@googlegroups.com
Mark Wrote:

> This initial arose from discussions around the idempotency of DELETEs 
> and should subsequent DELETEs trigger errors or no-ops - we settled on 
> errors but questioned what the expected error should be. 

What influenced your decision to step away from idempotent delete operations? 

The large scale API systems of which I know, and certainly the distributed systems that sit atop them, are all moving towards a pattern of idempotent APIs wherever possible. The idempotency of a delete operations seems like an easy candidate for that and would significantly help folks build reliable and fault tolerant at-scale distributed systems atop your API. 


Cheers,
Chris 

Johan Groenen

unread,
Jan 28, 2015, 10:51:45 AM1/28/15
to api-...@googlegroups.com
http://stackoverflow.com/questions/4088350/is-rest-delete-really-idempotent

"You would be correct to expect that the status code would be different but this does not affect thecore concept of idempotency - you can send the request more than once without additional changes to the state of the server."

Op maandag 1 september 2014 07:23:24 UTC+2 schreef Mark Derricutt:
Reply all
Reply to author
Forward
0 new messages