- From: Fish <fish@infidels.org>
- Date: Tue, 27 Mar 2001 18:53:55 -0800
- To: <www-talk@w3.org>
> -----Original Message----- > From: Aaron Swartz [mailto:aswartz@swartzfam.com] > Sent: Tuesday, March 27, 2001 6:33 AM > To: Fish; www-talk@w3.org > Subject: Re: Implementing HTTP PUT > > > Fish <fish@infidels.org> wrote: > > > What do you mean by: "What type of RESPONSE should be returned with > > an error [RESPONSE] and a 200 OK [RESPONSE]..."? (emphasis mine) > > > > Could you perhaps mean which of the variety of *response HEADERS* > > should/must one include in their response to a PUT request?? > > You're right, I don't quite know the proper terminology, so I'm being a bit > unclear. What I'm really curious about is the mix of headers and body that > is included. Mostly the body, to be truthful. Does it matter? I don't think so. AFAIK the body of your response can be pretty much whatever you want. > In my first > experimentation with it, when I returned a 200 response with a text/plain > body of "OK", Amaya claimed there was an error of "OK". So I believe I'm > missing something. Probably. Was there an "Expect: 100-continue" header in the request? If so, then you should have responded to the PUT request with two separate responses: the first being a "100 Continue" response and the second a "200 OK" final status response. See RFC 2616 section 8.2.3 "Use of the 100 (Continue) Status". (But you knew that, right? How familiar are you with HTTP/1.1 anyway? Please understand I'm not bashing you; I'm just curious, that's all. It helps to know the background and experience of the person asking the question.) (Also please understand that I'm certainly no expert in this either. I'm just familiar with RFC 2616, having written my own proxy server, that's all. However, I must if course quickly add that PUT and DELETE requests and their associated responses is not something I'm very familiar with, so if anyone else out there has first hand experience, *please* jump in and correct me! Thanks. :) (That includes you too, Nick. >;-) Anyway, from the sounds of it (and from my quick reading of RFC 2616), how one responds to a PUT request depends largely on what the request looks like and what the two of you (the client, and you, the server) are trying to accomplish. The way RFC 2616 is worded, it sounds very much like the PUT and DELETE requests (and their associated responses) were designed for something like CVS clients and servers (or something very similar). What follows below are some brief excerpts from what I believe are the pertinent sections of RFC 2616 and a few intervening comments by myself: ----------------------------------- 9.6 PUT [...] If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a 501 (Not Implemented) response in such cases. ----------------------------------- Ok. Here's where we begin. A PUT request. The entity we're "PUT"ting may or may not already exist. If it doesn't, we should respond with "201 Created" whereas if it already does (and the request thus simply modified the already existing entity) then we should respond with "200 OK". If some "Content-Range" headers were included in the request (to request modification of only a portion of the entity in question and not the complete entity) and we don't support such requests, we should respond "501 Not Implemented". So far so good. Now the "201 Created" response also appears to carry with it some other requirements: ----------------------------------- 10.2.2 201 Created The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate. The entity format is specified by the media type given in the Content-Type header field. [...] ----------------------------------- Ah-ha. It looks like your response should include a list of URIs that tells the client how it should refer to the just-created entity. That is to say, now that the entity has been created, if it (the client) should then need to issue a 'GET' request at some later point in time to retrieve what it just PUT, what URI should it use in that 'GET' request? (Apparently the URI used in the PUT request can differ from the URI used to 'GET' it. Within the context of the CVS analogy, this makes sense.) So... your response should include a "Location:" header specifying the *preferred* URI, with all the other possibly URIs (if any) specified in the actual body of your response (with an appropriate "Content-Type:" header in your response specifying which format the entity body of your response is in; e.g. "text/plain" or "text/html", etc.) ----------------------------------- ("10.2.2 201 Created" continued): [...] The origin server MUST create the resource before returning the 201 status code. If the action cannot be carried out immediately, the server SHOULD respond with 202 (Accepted) response instead. A 201 response MAY contain an ETag response header field indicating the current value of the entity tag for the requested variant just created, see section 14.19. ----------------------------------- Ok. Since the very nature of PUT requests is to modify entities on the server and there could theoretically be several different versions of that one entity (using the previously mentioned CVS analogy), the protocol allows for the requestor (the client making the PUT request) to specify *which* of the various entity versions it wishes to modify by including an "If-Match:", "If-None-Match:" or "If-Unmodified-Since:" header in its request (At least that's my reading of it. Do you concur?), and your response should (may) include an "ETag:" header, indicating which entity was actually created/updated: ----------------------------------- 14.19 ETag The ETag response-header field provides the current value of the entity tag for the requested variant. ----------------------------------- Or, you can simply include a "Last-Modified:" header in your response from the sounds of it: ----------------------------------- 14.29 Last-Modified The Last-Modified entity-header field indicates the date and time at which the origin server believes the variant was last modified. ----------------------------------- As I said earlier, it all depends on who you're talking to (i.e. the client) and what they (the client) expect their response to look like. <shrug> ----------------------------------- 14.26 If-None-Match [...] The meaning of "If-None-Match: *" is that the method MUST NOT be performed if the representation selected by the origin server (or by a cache, possibly using the Vary mechanism, see section 14.44) exists, and SHOULD be performed if the representation does not exist. This feature is intended to be useful in preventing races between PUT operations. ----------------------------------- Ok. That sounds simple enough. If the client making the request believe it's *creating* a new entity, it should include an "If-None-Match: *" header, meaning its requests should be interpreted as meaning "only PUT this entity if it does NOT already exist". If it does (or of any of the other request conditions cannot be honored (i.e. "If-Match:" and "If-Unmodified-Since"), then the response should of course be "412 Precondition Failed": ----------------------------------- 10.4.13 412 Precondition Failed The precondition given in one or more of the request-header fields evaluated to false when it was tested on the server. This response code allows the client to place preconditions on the current resource metainformation (header field data) and thus prevent the requested method from being applied to a resource other than the one intended. ----------------------------------- The only thing left is "409 Conflict": ----------------------------------- 10.4.10 409 Conflict The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required. Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type. ----------------------------------- This is the wording I was talking about that makes it sound like PUT/DELETE were designed for CVS or similar client/server exchanges. If a client requests a PUT for entity "foo.c" using a URI that specified version 1.0 for example (e.g. "PUT /usr/cvs/project/version_1.0/foo.c HTTP/1.1") but version 1.0 is no longer the current version (because presumably someone just uploaded a new version in the mean time), then a "409 Conflict" response might, in this case, be appropriate and not a "200 OK" as would normally be expected. All in all, it sounds like there are a few headers and response body requirements (or at least *expectations*) that accompany proper handling of PUT (and DELETE) requests, and, as I said, it all depends on what you and the client are doing (i.e. trying to accomplish). <shrug> At least, that's *my* take on it. But as I said, I'm certainly no expert in this. I'm just going by what I'm reading in the RFC. > What I'd love is just simple traces of a 200 response, an error response, > and even a 201 response would be nice. I agree. That would certainly help. Unfortunately I don't have any. :( Maybe your client was expecting an "ETag:" header in the response? I don't know. Perhaps you could include the exact text of the request sent to you and the response you sent back. Maybe that would help shed some might on what's going on. > Thanks for your help, > > -- > [ Aaron Swartz | me@aaronsw.com | http://www.aaronsw.com ] You're very welcome, Aaron. I only hope that I indeed *did* help some. I don't know. Did I? Or did I just confuse you further? %P :) -- "Fish" (David B. Trout) fish@infidels.org
Received on Tuesday, 27 March 2001 21:54:06 UTC