PUT for partial update of an existing resource
- View SourceI've been pondering whether or not it is OK to use PUT for a partial update of a
resource. When I look at the HTTP spec it says "The PUT method requests that the
enclosed entity be stored under the supplied Request-URI." This seems to be a
little loosy goosy to me, as the entity is a represenation and the Request-URI
identifies a resource and so the thing I create (the resource) is logically
different than one particular representation of it. To illustrate this, suppose
my media type allows an optional create-timestamp field and my server supplies
the value using its own clock if the resource does not already exist. I might
want to allow PUT operations to do updates, but not allow them to include the
create-timestamp. In fact, I might explicitly define in the media type that PUT
requests will be rejected if they include the create-timestamp.
I don't think this violates any requirement for PUT that I can find.
Specifically, I don't think I see anything that requires that a if I put
representation X to resource Y and follow it by a GET that I have to get back
the same representation. In fact, I don't think anything requires that if I use
PUT I have to support GET at all, let alone with the same media type, let alone
with the same representation provided by PUT. All that I see required is that
PUT is idempotent and that the enclosed entity be stored under the supplied
Request-URI, which doesn't seem (to me) to imply that it must be all that is
stored. I would think that each media type can define the semantics of PUT in
terms of how resource state is affected.
If the above create-timestamp is OK, then why not PUT for wholesale partial
updates? If I create a car resource with an engine within its state and then I
PUT a new engine why can I not expect to store this engine under the original
car resource, so that a subsequent GET returns the car?
Sam Ruby in his blog
"Having some servers interpret the removal of elements (such as content) as a
modification, and others interpret the requests in such a way that elided
elements are to be left alone is hardly uniform or self-descriptive." I think
this is easily disposed of. It isn't the server that interprets what to do, it
should be defined by the media type.
What do other people think of PUT for partial updates?
- View SourceBryan it strikes me that the very part of the specification you're referring to as the ambiguity is the root of the clarity with regard to whether the PUT verb can accommodate a subset of the information associated with the representation of the an existing addressable resource:
'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.' (Section 9.6, RF2616)
'...the URI in a PUT request identifies the entity enclosed with the request' (Section 9.6, RF2616)
I'll explain why I see it this way.
Firstly the reference to 'enclosed entity' is key in my opinion. From a data modelling perspective entity refers to something atomic comprising one or more attributes. Whilst this is far from a strong argument in the 2616 context - falling back to a general survey of definitions there is a general trend towards this definition of entity as:
'An entity is something that exists separately from other things and has a clear identity of its own.' (example from http://en.wikipedia.org/wiki/Entity)
So the reference to an enclosed-entity within the PUT verb semantics leads me to a strong belief that PUT should convey an atomic representation which will then be regarded by the server as the 'replacement' for any prior representations. This alone means to me that partial PUT, or PUT conveying an arbitrary subset of attributes (whoever much I may wish that to be embraced by 2616) is not compliant with the albeit terse, '2616 specification'.
In reality I too have a strong tendency to look to optimise what may be a heavy overhead in conveying large amounts of information for what may be a single attribute modification in my resource representation between my clients and server.
That said I regard my own willingness to optimise and add more intelligence to my own implementation of the PUT (modify) interaction as my own overlay or deviation from the base specification in RFC2616. In such cases, the merits of adopting this approach have to consider the likelihood of breaking assumptions between my clients and intermediaries about what is being conveyed by PUT.
The most interesting clause, the one referring to:
'HTTP/1.1 does not define how a PUT method affects the state of an origin server.' (Section 9.6, RFC2616)
In my opinion this clause does mean that so long as you ensure that the PUT is compliant to the specification (i.e. atomic replacement), then the server is open to doing funky stuff with previous representation versions, or even deriving the extent of the delta's between versions of the resource.
However that still does not open the door to conveying partial resource representations between the client and the server and I don't believe conveying a partial does actually satisfy these constraints as per your statement about satisfying all constraints.
--- In firstname.lastname@example.org, "bryan_w_taylor" <bryan_w_taylor@...> wrote:
> --- In email@example.com, Craig McClanahan <craigmcc@> wrote:
> > Given that HTTP PATCH has been a released IETF standard for over a year
> > now, and it specifically addresses the partial update use case, why are we
> > still wasting both bandwidth and intellectual bits talking about using PUT
> > for partial updates?
> > Craig
> My question that started the thread was whether or not it is OK to use PUT for partial updates. The fact that another verb can be used for partial updates is irrelevent. That was already true with POST anyway. When you ask if something is legal per the spec, you don't get to add additional constraints on the design of solutions by requiring them to solve the problem a way you like. A good spec should unambiguously define what is and isn't compliant. If somebody comes along and implements a design that uses these verbs in a way nobody thought of, the only question is whether you can find black letters in the text of the spec that you can circle in a red pen to defend the assertion that "you didn't comply with this".
> Lore is that PUT cannot be a partial update, but no one has answered my challenge to point to the text of the spec to support this lore. Nothing in RFC 2616 backs up the contention that the server must forget all previous state, in fact to the contrary, the spec says "HTTP/1.1 does not define how a PUT method affects the state of an origin server". It's required to be idempotent and to support the vague notion that "the enclosed entity be stored under the supplied Request-URI." To my reading, partial updates can satisfy all the constraints that are actually documented in the spec.
> It very well may be that the community that produced HTTP 1.1 did not have partial updates in mind when they wrote the spec. This is irrelevant to the question of whether the text of the spec forbids it or not.
> As to why not use PATCH, I don't object if others don't want use it. I choose not to for a variety of reasons, which can be summarized as it's too exotic for me to expect of my clients. A client which supports only a subset methods explicitly given by RFC 2616 will not understand PATCH, and I believe this is true of most of my clients. I also think I can solve the problem without it, by using POST, using PUT with refinements, or using PUT with partial updates.