Subject: [Simple] xcap issue 3: PUT v. POST

From: Jonathan Rosenberg <[email-masked]>
Date: Mon, 10 May 2004 01:50:29 -0400

Without a doubt, the biggest open issue in xcap today is PUT vs. POST. 
That is, when modifying a document, either by inserting a new element or 
attribute or modifying an existing element or attribute, do we use POST 
or PUT?

The current spec says PUT. However, a few stresses (as Ted has put it) 
have surfaced around this:

1. in some cases, the server needs to modify the document (for example, 
by adding a unique URI for somethign like a buddy list). I modeled this 
as, instead of having the server actually modify the document, there is 
a separate application that modifies it after the document is written. 
There is a lot of ugliness with that approach. The client has to poll to 
find out the URI that is assigned, and the etags will change. Its also 
hard to implement.

2. The place where the document is inserted is schema dependent; that 
is, there is a bit of magic going on in how the server determines where 
to place the content.

3. THe server can reject the PUT request if it doesnt like the content 
for some reason - it causes the document to be invalid, or uses a URI 
that exists in the system. As such, its not just a blind "write this 
here" operation.

So, we have two options. We can either address the above things, to make 
PUT an appropriate method here, else use POST. I am very hesitant to use 
POST because it really then means that we are really using HTTP as a 
tunnel for some other protocol, and that has a whole bunch of problems 
associated with it.

So, here are my proposals for addressing the above three concerns.

First, as I have proposed already on the list, I would remove, from 
xcap, any notion of the servers filling in the document or doing things 
like assigning URIs. If we need a URI assignment service, lets have that 
execute separately. THe client would issue some command (not xcap) to 
get a URI, and once it has it, it would do an XCAP opeartion to write 
the whole document, including the URI, to the server. With such a 
change, things operate much more cleanly. There is no need for polling 
to find out the assigned URI, it would be provided in the response to 
the assignment request. There is no phantom application that modifies 
data. The response to the PUT operation truly indicates whether the 
operation succeeded or failed.

Secondly, I have proposed in another thread that the server perform 
insertions without requiring it to understand the schema. That is, the 
insertion process is completely deterministic and there are no 
schema-specific behaviors. This change addresses the second problem above.

In regards to the third, we *could* have xcap skip any notion of 
validation at all - no XML well-formedness, no schema validation, no 
nothing. In such a case, its a clear "write this here" operation that 
maps to PUT. However, I believe this is not useful for us. Xcap is, at 
the end of the day, a means for user self-provisioning, and I believe 
that data validation is a key component of any provisioning process. 
Thus, I believe we need to be able to reject a request to modify a 
document if the result violates some kind of data constraint.

However, just because the server does such validation, does not mean 
that the operation is no longer a pure PUT. HTTP does envision that PUT 
requests can be validated before doing them. I point to section 10.4.10 
of HTTP 2616, which defines the 409 code:

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

Fielding, et al.            Standards Track                    [Page 67]

RFC 2616                        HTTP/1.1                       June 1999

    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.

I think this clearly says that validation is just fine; almost by 
definition, a validation failure is because there is a conflict with the 
current set of data.

So, I would propose that we make the two changes I have suggested (using 
a separate method for allocating URI, and avoiding schema-specific 
insertion semantics), and retain PUT. In this way, the actual 
modification operation (through PUT) succeeds or doesn't, and what it 
does is well defined. However, the logic which determines whether it 
succeeds or not can be complex, including but not limited to schema 
validation.

Do folks agree?

Thanks,
Jonathan R.
-- 
Jonathan D. Rosenberg, Ph.D.                600 Lanidex Plaza
Chief Technology Officer                    Parsippany, NJ 07054-2711
dynamicsoft
[email-masked]                     FAX:   (973) 952-5050
http://www.jdrosen.net                      PHONE: (973) 952-5000
http://www.dynamicsoft.com

_______________________________________________
Simple mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/simple

---

From: "Joel M. Halpern" <[email-masked]>
Date: Mon, 10 May 2004 10:56:26 -0400

As I said in my earlire message, I think that efforts to remove validation 
from the SCAP behavior are a mistake.

Given that, the XCAP behavior seems semantically closer to POST rather than 
PUT.  However, I can live with either one.

Yours,
Joel M. Halpern

At 01:50 AM 5/10/2004 -0400, Jonathan Rosenberg wrote:
>attribute or modifying an existing element or attribute, do we use POST or PUT?
>
>
>nothing. In such a case, its a clear "write this here" operation that maps 
>to PUT. However, I believe this is not useful for us. Xcap is, at the end 
>of the day, a means for user self-provisioning, and I believe that data 
>validation is a key component of any provisioning process. Thus, I believe 
>we need to be able to reject a request to modify a document if the result 
>violates some kind of data constraint.
>
>However, just because the server does such validation, does not mean that 
>the operation is no longer a pure PUT. HTTP does envision that PUT 
>requests can be validated before doing them. I point to section 10.4.10 of 
>HTTP 2616, which defines the 409 code:
>
>10.4.10 409 Conflict
>
>    between the two versions in a format defined by the response Content-Type.
>
>
>So, I would propose that we make the two changes I have suggested (using a 
>separate method for allocating URI, and avoiding schema-specific insertion 
>semantics), and retain PUT. In this way, the actual modification operation 
>(through PUT) succeeds or doesn't, and what it does is well defined. 
>However, the logic which determines whether it succeeds or not can be 
>complex, including but not limited to schema validation.
>
>Do folks agree?
>
>Thanks,
>Jonathan R.
>--

---

From: Dean Willis <[email-masked]>
Date: Mon, 10 May 2004 10:04:13 -0500

Jonathan Rosenberg wrote:

>  I am very hesitant to use 

I don't agree to this assertion. That's like saying the softwarmor web 
pages are illegally tunneling some other protocol over HTTP because I 
used POST operations in the form-editing scripts.

POST is the preferred HTTP mechanism for handing user-input to 
server-side applications.

PUT is the preferred HTTP mechanism for handing "page" content to a 
server for storage.

Which one of these operations are we doing?

--
Dean

---

From: "Joel M. Halpern" <[email-masked]>
Date: Mon, 10 May 2004 10:56:26 -0400

Yours,
Joel M. Halpern

---

From: Dean Willis <[email-masked]>
Date: Mon, 10 May 2004 10:04:13 -0500

--
Dean

---

From: Jari Urpalainen <[email-masked]>
Date: Tue, 11 May 2004 08:31:34 +0300

> find out the URI that is assigned, and the etags will change. Its also 

As we have already discussed that we can't return server computed data
in the 200/201 OK response for PUT request, what about if e.g. the
server would reject the list creation with 409 response if the list-uri
is empty. In that response we can have this detailed <xcap-error> format
which could be even fairly generic as long as you'll give exact XPATH
reference and proposed modified content in that response. This is almost
similar what I have in my reference implementation when the user tries
to define two lists with the same sip-uri (<uri-exists> error is
returned then). Certainly we'll have two round-trips then, but we'll
avoid POST. I definitely think that this has to be solved with the base
protocol even if the solution is ugly.

BR,
Jari

---

From: Jari Urpalainen <[email-masked]>
Date: Tue, 11 May 2004 08:31:34 +0300

BR,
Jari

---

From: Jonathan Rosenberg <[email-masked]>
Date: Tue, 11 May 2004 12:18:30 -0400

I think this is a great approach. To clarify, if the client has a list 
URI to suggest, it includes it in the body of the request. If not, it 
omits that attribute. Since the list URI would be a mandatory part of 
the schema, sending a document without one would constitute an error, 
resulting in a 409. If one is provided but exists, you also get a 409. 
In either case (and this is why I like doing this in the 409), the body 
of the response contains suggested URIs. When the URI was empty in the 
request, the server can simply return one or more random URis.

Whats nice is, the current 409 content format already allows for 
specifying alternative URIs, so we've got most of what we need in place 
already.

So, to summarize, the common case for creating a buddy list would run 
like this:

  PUT
    http://xcap.example.com/services/presence-lists/users/bill/fr.xml 
HTTP/1.1
    Content-Type:application/presence-lists+xml

    <?xml version="1.0" encoding="UTF-8"?>
    <resource-lists xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <list name="friends"  subscribeable="true">
      </list>
    </resource-lists>

and this is rejected liked this:

HTTP/1.1 409 Conflict
Content-Type: application/xcap-error+xml

<?xml version="1.0" encoding="UTF-8"?>
    <xcap-error xmlns="urn:ietf:params:xml:ns:xcap-error"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <uri-needed>
       <alt-uri>sip:[email-masked]</alt-uri>
      </uri-needed>
    </xcap-error>

and then:

PUT
    http://xcap.example.com/services/presence-lists/users/bill/fr.xml 
HTTP/1.1
    Content-Type:application/presence-lists+xml

    <?xml version="1.0" encoding="UTF-8"?>
    <resource-lists xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <list name="friends"  uri="sip:[email-masked]" 
subscribeable="true">
      </list>
    </resource-lists>

which results in:

HTTP/1.1 200 OK

I really like this.

-Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Tue, 11 May 2004 12:26:25 -0400

inline.

Dean Willis wrote:

>>  I am very hesitant to use POST because it really then means that we 
>> are really using HTTP as a tunnel for some other protocol, and that 
>> has a whole bunch of problems associated with it.
> 
> 

No, thats not what PUT means. I quote from RFC 2616:

> 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. If the
>    Request-URI does not point to an existing resource, and that URI is
>    capable of being defined as a new resource by the requesting user
>    agent, the origin server can create the resource with that URI. 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.
> 
>    If the request passes through a cache and the Request-URI identifies
>    one or more currently cached entities, those entries SHOULD be
>    treated as stale. Responses to this method are not cacheable.
> 
>    The fundamental difference between the POST and PUT requests is
>    reflected in the different meaning of the Request-URI. The URI in a
>    POST request identifies the resource that will handle the enclosed
>    entity. That resource might be a data-accepting process, a gateway to
>    some other protocol, or a separate entity that accepts annotations.
>    In contrast, the URI in a PUT request identifies the entity enclosed
>    with the request -- the user agent knows what URI is intended and the
>    server MUST NOT attempt to apply the request to some other resource.
>    If the server desires that the request be applied to a different URI,
> 
> 
> 
> 
> Fielding, et al.            Standards Track                    [Page 55]
> 
>    it MUST send a 301 (Moved Permanently) response; the user agent MAY
>    then make its own decision regarding whether or not to redirect the
>    request.
> 
>    A single resource MAY be identified by many different URIs. For
>    example, an article might have a URI for identifying "the current
>    version" which is separate from the URI identifying each particular
>    version. In this case, a PUT request on a general URI might result in
>    several other URIs being defined by the origin server.

That is, in essence - PUT means "place this as the content of this 
resource". Nothing in there says "web page". It talks about resources 
and a means for retrieving them.

To me, the quintissential test of this is that, if I do a GET on that 
same URI, it should return what I just PUT. That is, GET(PUT(x)) = x. 
That is true here, and I dont think that anyone has argued that we 
should not be allowed to use GET to fetch the contents of the document. 
It is not ever true for POST, since GET to a resource that represents a 
form processing engine makes no sense.

THe only "twist" that XCAP introduces is that, when I PUT to an xcap 
URI, in many cases that will result in changes not just to that URI, but 
others. In particular, to any other URI that addresses part of the 
content I just PUT. Is PUT to a URI allowed to change other related 
content? YES. It says so above, and I quote, "In this case, a PUT 
request on a general URI might result in several other URIs being 
defined by the origin server". Thats exactly what is happening here.

So, since I believe that the xcap URIs do not represent a form 
processing application, but rather point to the content itself, and 
because GET(PUT(x))=x, this seems to me to be a PUT. So, I would ask 
this - for folks that support POST, what aspect of PUT as defined in 
HTTP do they think xcap violates or breaks? I can point to an explicit 
piece of POST it breaks (that is, if we used POST, it would not make any 
sense to GET to that same URI, and we are doing that).

Thanks,
Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Tue, 11 May 2004 12:18:30 -0400

PUT

HTTP/1.1 409 Conflict

and then:

PUT

which results in:

HTTP/1.1 200 OK

I really like this.

-Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Tue, 11 May 2004 12:26:25 -0400

inline.

Thanks,
Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Mon, 17 May 2004 03:21:45 -0400

The silence is deafening....

I put a concrete challenge below to those who believe this is POST. 
Please respond!

-Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Mon, 17 May 2004 03:21:45 -0400

-Jonathan R.

---

From: Dean Willis <[email-masked]>
Date: Mon, 17 May 2004 17:40:48 -0500

> I put a concrete challenge below to those who believe this is POST.

Okay.

Now, personally, I don't really care all that much whether we're using 
PUT or POST. As far as I can tell, XCAP as currently defined is an 
entirely new protocol that is only loosely based on HTTP, and we're free 
to call the request methods whatever we want, and mandate whatever 
semantics for those methods we want.  But we shouldn't confuse ourselves 
by thinking XCAP so defined is still HTTP, just as SIP itself is no 
longer HTTP even though it started in the same place.

IF XCAP were truly just an HTTP application that needs to behave as you 
have in general specified, then I argue that it would be correctly 
implemented using POST.

Here's my reasoning. Of course, it may be faulty, although proving that 
the logic is faulty doesn't mean the conclusion is wrong, just that I 
failed to support it.

>> and a means for retrieving them.

PUT means "store this content", Not "schema validate and analyze this 
content for semantic correctness within the application's definition and 
get back to me".

>> should not be allowed to use GET to fetch the contents of the 
>> document. It is not ever true for POST, since GET to a resource that 
>> represents a form processing engine makes no sense.

>> The only "twist" that XCAP introduces is that, when I PUT to an xcap 
>> URI, in many cases that will result in changes not just to that URI, 
>> but others. In particular, to any other URI that addresses part of the 

Actually, GET and POST to the same form code up fairly nicely. See the 
example at the end of this rant.

If XCAP did no validation (other than location-matching, which is 
consistent with PUT) I would agree that this is a PUT operation. But it 
doesn't. You're asking the server to validate the content, and to take 
further actions based on the validity (or lack thereof) of that content, 
which might include changing OTHER parts of the "store" outside of the 
explicit scope of the request just made. That "validation" phase is 
where I think we have server-side loic that exceeds the expressivity of PUT.

Does GET(PUT(X))== X?

The operation of PUT(x) might result in no changes whatsoever to the 
content stored at the target URI (x), because the content in the request 
failed validation with respect to the server enforced scehama applied at 
(x). Or, the server might attempt to correct the content, storing 
something that is schematically valid but inconsistent with intent. Or 
(and I'll admit, I haven't though this one through), a change in X might 
result in the creation of Y, the schema of which is so constructed that 
this results in a new change in X by the server, and so on. In any case, 
it is possible that:

GET(PUT(X)) <> X

>> piece of POST it breaks (that is, if we used POST, it would not make 
>> any sense to GET to that same URI, and we are doing that).

Actually, GET and POST happen to the same URL all the time. Here's an 
example from the admin.php script for the working group drafts database 
at www.softarmor.com. Note that the first thing the script does is 
decide whether it was called on a POST or a GET. If it's a GET, it 
displays a menu. If it's a POST, it assumes that the menu had been 
previously displayed and selected from, and executes the selected option.

I haven't figured out how to do this with PUT, because, at least on my 
server, PUT gets picked up by the DAV module and not handed to a 
user-space program.

Some of my newer material has multiple screens of display capability and 
specific forms-processing for a whole database application bundled up in 
one tidy little script, which stores its state entirely in client-side 
parameters that are POSTED back into the application on each client 
action (it's a simple FSM, and the states are stored in client-side 
parameters). It tastes great, and it's less filling. Admittedly, a good 
PHP coder could code it much more tidily.

Example follows:

// Main entry for script
// Check to see if we were called with a form result or not

$submit=$_POST["submit"];

if($submit) {
   procsubmit($submit);
} else{

   // Display the administrative user interface
   echo "<form method=\"post\" action=\"$PHP_SELF\">";
   echo "<p>List files in the docs directory ".
     "<input type=\"submit\" name=\"submit\" value=\"List\"></p>\n";
   echo "<p>List unindexed files in the docs directory ".
     "<input type=\"submit\" name=\"submit\" value=\"Unindexed\"></p>\n";
   echo "<p>Add unindexed files in the docs directory to database, no
working group, marking as current ".
     "<input type=\"submit\" name=\"submit\"
value=\"AddNoneCurrent\"></p>\n";
   echo "<p>Add unindexed files in the docs directory to database, no
working group, marking as expired ".
     "<input type=\"submit\" name=\"submit\"
value=\"AddNoneExpired\"></p>\n";
   echo "</form></p>\n";

   echo "<form method=\"post\" action=\"editnone.php\">".
     "<p>Edit the assignments for all drafts assigned to group \"None\" ".
     "<input type=\"submit\" name=\"AssignNone\"
value=\"AssignNone\"></form></p>\n";

}

---

From: Dean Willis <[email-masked]>
Date: Mon, 17 May 2004 17:40:48 -0500

Okay.

Does GET(PUT(X))== X?

GET(PUT(X)) <> X

Example follows:

// Main entry for script

if($submit) {
   procsubmit($submit);
} else{

}

---

From: Ted Hardie <[email-masked]>
Date: Mon, 17 May 2004 18:05:18 -0700

Early on, we discussed the idea of using new methods, since
they would allow for semantics that were tailored to this
particular problem space.  That discussion raised a lot of issues with
time to deployment.  At that point, the problem space
  XCAP was tackling was also fairly  narrow--how to avoid
the download and re-upload of large lists when single
entries were being changed.  Based somewhat on a WebDAV
view of resources, I (among others) argued that we could
treat the individual entries as addressable resources, even without using
XPATH, provided we saw the lists as hierarchies--allowing
the hierarchy to provide a structure that permitted individual
entries to be addressed by standard HTTP URIs.

The reason that PUT was chosen rather than post was two-fold.
One is this text from the HTTP spec, which Jonathan has put
out before:

In the original, narrow XCAP usage, the request URI was the individual
entry, and a process could GET or PUT it (and the fact it might be
stored in XML document rather than a filesystem or database just
had no relevance to HTTP).

The other reason is practical.  When using POST and pointing at
named process by specific uri (e.g. 
http://www.example.com/xcap.cgi?new_buddy.xml),
we've seen over and over that extensibility becomes very difficult to manage
and that implementations tend to drift over time.  Even with the best of
intentions, using HTTP POST creates a protocol black box where "magic happens"
(since we cannot specify to the level of the code implementing the
handler).  Past performance may be no guarantee of future results, but the
history here tends to be pretty clear.  That has meant the IETF has 
been reluctant
to use POST where it should be specifying a new method, so the choice
looked like PUT vs. new method and we were back to step one.

If we were sticking to the original narrow slice of protocol, I would 
be very confident
that PUT was the right choice.  I still believe it should be PUT, but 
I am concerned
that the growth in scope puts that at risk.  One example that's been recently
discussed is the case of selecting multiple elements.  Looking at the recent
discussion, I'm not at all sure that PUT with multiple selectors can be made
idempotent (cf. 9.1.2 of 2616), especially with positional selectors.
Jonathan's recent message is clearly giving it the old college try
by making the syntax equivalent to a sequence of independent PUTs,
but I'm still working out whether the same thing happens every
time you do the PUT for all cases.  That is if I do:

A put to

http://xcap.example.com/xcap-root/usage/users/joe/doc1//foo/bar[1]|foo/bar[2]

I reach state 1.  If I then do a second PUT to

http://xcap.example.com/xcap-root/usage/users/joe/doc1//foo/bar[1]|foo/bar[2]

with exactly the same body, would a subsequent GET return the same
results as a GET done at state 1?  Reading Jonathan's message I persuade
myself yes in odd number hours and no in even (but in the even I believe it is
idempotent for the each of the sequence of independent PUTs, just not the
whole).

Even granting that it will, the logic is clearly fairly complex, and I'm not at
all sure it's worth it.

To put this another way, I would much rather that we kept the scope
of XCAP to something where it was obvious that PUT was correct than
to grow into something that requires new methods.

My personal opinion,
			regards,
				Ted Hardie

At 5:40 PM -0500 05/17/2004, Dean Willis wrote:
>Now, personally, I don't really care all that much whether we're 
>using PUT or POST. As far as I can tell, XCAP as currently defined 
>is an entirely new protocol that is only loosely based on HTTP, and 
>we're free to call the request methods whatever we want, and mandate 
>whatever semantics for those methods we want.  But we shouldn't 
>confuse ourselves by thinking XCAP so defined is still HTTP, just as 
>SIP itself is no longer HTTP even though it started in the same 
>place.
>
>IF XCAP were truly just an HTTP application that needs to behave as 
>you have in general specified, then I argue that it would be 
>correctly implemented using POST.
>
>Here's my reasoning. Of course, it may be faulty, although proving 
>that the logic is faulty doesn't mean the conclusion is wrong, just 
>that I failed to support it.
>
>>>resource". Nothing in there says "web page". It talks about 
>>>resources and a means for retrieving them.
>
>PUT means "store this content", Not "schema validate and analyze 
>this content for semantic correctness within the application's 
>definition and get back to me".
>
>>>To me, the quintissential test of this is that, if I do a GET on 
>>>that same URI, it should return what I just PUT. That is, 
>>>GET(PUT(x)) = x. That is true here, and I dont think that anyone 
>>>has argued that we should not be allowed to use GET to fetch the 
>>>contents of the document. It is not ever true for POST, since GET 
>>>to a resource that represents a form processing engine makes no 
>>>sense.
>
>>>The only "twist" that XCAP introduces is that, when I PUT to an 
>>>xcap URI, in many cases that will result in changes not just to 
>>>that URI, but others. In particular, to any other URI that 
>>>addresses part of the content I just PUT. Is PUT to a URI allowed 
>>>to change other related content? YES. It says so above, and I 
>>>quote, "In this case, a PUT request on a general URI might result 
>>>in several other URIs being defined by the origin server". Thats 
>>>exactly what is happening here.
>
>Actually, GET and POST to the same form code up fairly nicely. See 
>the example at the end of this rant.
>
>consistent with PUT) I would agree that this is a PUT operation. But 
>it doesn't. You're asking the server to validate the content, and to 
>take further actions based on the validity (or lack thereof) of that 
>content, which might include changing OTHER parts of the "store" 
>outside of the explicit scope of the request just made. That 
>"validation" phase is where I think we have server-side loic that 
>exceeds the expressivity of PUT.
>
>
>Does GET(PUT(X))== X?
>
>content stored at the target URI (x), because the content in the 
>request failed validation with respect to the server enforced 
>scehama applied at (x). Or, the server might attempt to correct the 
>content, storing something that is schematically valid but 
>inconsistent with intent. Or (and I'll admit, I haven't though this 
>one through), a change in X might result in the creation of Y, the 
>schema of which is so constructed that this results in a new change 
>in X by the server, and so on. In any case, it is possible that:
>
>GET(PUT(X)) <> X
>
>>>processing application, but rather point to the content itself, 
>>>and because GET(PUT(x))=x, this seems to me to be a PUT. So, I 
>>>would ask this - for folks that support POST, what aspect of PUT 
>>>as defined in HTTP do they think xcap violates or breaks? I can 
>>>point to an explicit piece of POST it breaks (that is, if we used 
>>>POST, it would not make any sense to GET to that same URI, and we 
>>>are doing that).
>
>Actually, GET and POST happen to the same URL all the time. Here's 
>an example from the admin.php script for the working group drafts 
>database at www.softarmor.com. Note that the first thing the script 
>does is decide whether it was called on a POST or a GET. If it's a 
>GET, it displays a menu. If it's a POST, it assumes that the menu 
>had been previously displayed and selected from, and executes the 
>selected option.
>
>I haven't figured out how to do this with PUT, because, at least on 
>my server, PUT gets picked up by the DAV module and not handed to a 
>user-space program.
>
>Some of my newer material has multiple screens of display capability 
>and specific forms-processing for a whole database application 
>bundled up in one tidy little script, which stores its state 
>entirely in client-side parameters that are POSTED back into the 
>application on each client action (it's a simple FSM, and the states 
>are stored in client-side parameters). It tastes great, and it's 
>less filling. Admittedly, a good PHP coder could code it much more 
>tidily.
>
>Example follows:
>
>// Main entry for script

---

From: Ted Hardie <[email-masked]>
Date: Mon, 17 May 2004 18:05:18 -0700

A put to

My personal opinion,
			regards,
				Ted Hardie

---

From: Aki Niemi <[email-masked]>
Date: Tue, 18 May 2004 10:51:20 +0300

I like the proposal on the table that is based on PUT. I believe it 
works for at least the currently defined AUs.

The only thing that made me wonder was that when exactly would the 
server respond with a conflict? For example, I should be able to PUT a 
conference policy, without requiring it to have a conference URI at this 
point in time. The URI could be assigned later on.

Perhaps the solution is that only when the client attempts to PUT an 
element that the server needs to assign a value for, there would be 
conflict.

Cheers,
Aki

ext Jonathan Rosenberg wrote:
>>> I don't agree to this assertion. That's like saying the softwarmor 
>>> web pages are illegally tunneling some other protocol over HTTP 
>>> because I used POST operations in the form-editing scripts.
>>>

---

From: Aki Niemi <[email-masked]>
Date: Tue, 18 May 2004 10:51:20 +0300

Cheers,
Aki

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 05:04:56 -0400

Thanks for the comments, Ted. Responses inline.

Ted Hardie wrote:

> history here tends to be pretty clear.  That has meant the IETF has been 
> reluctant

I agree with this summary.

> 
> If we were sticking to the original narrow slice of protocol, I would be 
> very confident
> that PUT was the right choice.  I still believe it should be PUT, but I 
> am concerned

Thats a good point - in addition to GET(PUT(x)) = x, idempotency is a 
key requirement as a good "litmus test" for PUT vs. POST. I believe that 
the algorithm I suggested is, in fact, idempotent. Indeed, you can prove 
idempotency if GET(PUT(x)) = x. Here is the proof, by contradiction. 
Assume its not idempotent. This means I can perform two subsequent 
PUT(x) opeartions such that the actual document on the server is s1 in 
one case, s2<>s1 in the second case. Lets say I do a GET after the first 
PUT. Thats GET(PUT(x)) which I know is x. This means that s1 is equal to 
x. Lets say I then do the second put, which is x once again. I then GET 
that result. This is s2, but s2 is equal to GET(PUT(x)) which is again 
x. Thus s2 is x, contradicting the assumption. Therefore, the operations 
must be idempotent.

So, perhaps the problem is that its not clear that the algorithm has the 
property of GET(PUT(x)) = x. I do believe it's so. The trick, as you 
say, is the positional insertions for elements that are children of the 
same parent. Lets say you have N elements that are siblings before the 
insertions. If the positional insertions are for positions p1..PK (for a 
K-element insertion), I need to be sure that, when I do each insertion 
one at a time into positions p1..PK, that the positions in the final 
list of N+k elements remain p1..PK. I think I can also prove that, if 
you do the insertions in order (that is, insert the elements such that 
you do the one with the lowest p first, followed by the next, etc.), 
this property exists. Here's the proof.

Lets say I want to insert an element so that its final position after 
all of the others are inserted is position p. One way to be sure of this 
is that it has position p when I insert it, and no insertions that come 
afterwards change its position. The only way an insertion that comes 
afterwards can change its position is if that insertion comes before the 
one I've just inserted. Any insertions after that element don't change 
the position of that element (i.e., if there are 5 people in line, and I 
want to be third, and I get into the line after the first two people, my 
position remains third no matter how many people join the line after me).

So, what I need to show is that the algorithm has two properties - (1) 
its inserted initially into its final position, and (2) all subsequent 
insertions come afterwards. Property (2) is guaranteed if I insert the 
elements in order of position, as the algorithm does. That is, if the 
URI is something like this:

http://server/doc/~/foo/bar[3][@id="3"]|bar[2][@id="2"]|bar[5][@id="5"]

then I would insert the element corresponding to bar[2][@id="2"] first, 
then the one corresponding to bar[3][@id="3"], and finally 
bar[5][@id="5"]. Since these get put in based on their order, each 
insertion can only come after the one that was just inserted.

So, I only need to prove that by inserting them in order, the first 
property exists. There are N elements initially, N+k after insertion. 
Thus, the values of p can be anything from 1 to N+k. If its greater than 
N+k (in other words, in the URI is something like bar[100][@id="asda"]), 
then when I try to insert it, I'll get an error since at no point in the 
process will there N+k elements already in the list. Indeed, if k 
elements are ordered, and each has a unique index (the algorithm I 
proposed had a check for unique indices), and the largest is less than 
or equal to N+k, than the smallest must be less than or equal to N. So, 
when I insert the smallest, its position is N or less. Since there are N 
elements in the list initially, its possible to insert it into any 
position N or less, and so it can be inserted correctly. Now, there are 
N+1 elements, with k-1 to insert. By recursion, I can also insert this 
one into its desired position. And so, I can insert all of them into 
their desired positions. Thus, the first property can also be 
demonstrated, and thus, for positional insertion, the algorithm retains 
the GET(PUT(x))=x property.

Insertions can also be based on other characteristics besides position, 
in particular, name/values of attributes, names of elements and content 
value. The algorithm as it stands says that, when processing the PUT, if 
there are N components in the URI, it either has to match N elements in 
the doc (an update) or zero (an insertion). In the case of zero, the 
only case where you could get into trouble with these other properties 
is if one element overwrites another during the insertion process. We 
just need to define that as an error condition, which the algorithm does 
also.

So, hopefully that gives folks some confidence that the algorithm has 
the desired properties that we need to retain the usage of PUT and the 
general model we've been going for.

More below.

> idempotent for the each of the sequence of independent PUTs, just not the

Can you point to a specific problem where it doesnt look idempotent, or 
its hard to tell?

The way I've been thinking of it is that the URI with multiple elements 
is still specifying a hierarchy of elements, its just a hierarchy that 
is mapped into the document in a more complex way. Its effecitvely a 
view into a part of the document. As such, when you do a PUT to such a 
URI, you are setting the view to equal the content of the request. It so 
happens that we describe the view by a URI that represents the sequence 
of elements in the view, and that, under such a constraint, it is 
possible to define an algorithm for insertion that runs efficiently and 
works by inserting each at a time.

That is quite different from viewing the URI as a command to insert a 
series of elements; that is definitely more like a form processing 
command, and wouldn't be a match for PUT.

> Even granting that it will, the logic is clearly fairly complex, and I'm 

That may very well be right. As you say, the exercise here is to give it 
the "college try", and see if the feature can be added without 
significant complexity.

> to grow into something that requires new methods.

I'd definitely like to get input from folks on whether they feel that 
the complexity of the URI syntax and the insertion algorithm I described 
warrant the additional feature it brings us.

Thanks,
Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 05:11:38 -0400

inline.

Aki Niemi wrote:

> server respond with a conflict?

Many error cases are outlined. Schema validation failures, for example.

> For example, I should be able to PUT a 

Right. We discussed this. The proposal was that you'd leave the URI out. 
The server rejects the request (since the URI is required), and suggests 
some URI in the body of the 409. You pick one, put it into the body, and 
retry.

> element that the server needs to assign a value for, there would be 

For us, conflict includes nearly all of the error conditions we're 
concerned about. Here's the definition of the 409 code:

10.4.10 409 Conflict



"conflict with the current state of the resource" is not the same as 
"the URI conflicts with one I've already assigned". The latter is one 
example of many of the errors in the former category. Schema validation 
failures is another example of a conflict, in the sense that the 
operation is not permitted based on the current state of the resource. 
The key is really the bit about being able to try again. In all of the 
cases we're worried about, this is true - a request with different 
content might succeed, and so informing the user about the nature of the 
error in the body of the 409 makes sense.

HTH,
Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 05:04:56 -0400

More below.

Thanks,
Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 05:11:38 -0400

inline.

10.4.10 409 Conflict



HTH,
Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 05:29:31 -0400

inline.

> content for semantic correctness within the application's definition and 

We don't "get back to the caller". The content is either stored as 
requested, or the request is rejected. It can be rejected because it 
would put the resource in an invalid state.

>>> but others. In particular, to any other URI that addresses part of 
>>> the content I just PUT. Is PUT to a URI allowed to change other 
>>> related content? YES. It says so above, and I quote, "In this case, a 
>>> PUT request on a general URI might result in several other URIs being 
> explicit scope of the request just made. 

Correct. However, the HTTP spec explicitly acknowledges this as OK in 
the text I quoted previously.

> That "validation" phase is 

I think thats the crux of it. I agree completely that we do validation 
before deciding whether to accept the request or not. Such validation is 
an essential part of the protocol and cannot be avoided. You say that 
such validation is not allowed for PUT, and I say, it is. To me, the 409 
response code seems to be a good indicator that its ok to reject a 
request because of a content problem. I do agree that we're pushing on 
boundaries here, but I believe we fall on the right side of PUT.

> (x). 

Correct, but in such a case, the request fails. If you did a PUT(x) and 
there was NO validation whatsoever, but the request failed for some 
reason (pick your favorite response code), then clearly a GET on that 
won't get you back x either. The GET(PUT(x))=x property only holds if 
the PUT is successful, and thats true for the PUT usages today too.

> Or, the server might attempt to correct the content, storing 
> something that is schematically valid but inconsistent with intent.

No, it does not do this.

There is no content correction. If the request results in a failure of 
schema validation, it is rejected and the change is not applied.

> Or 

No, it does not do this.

Pretty much by definition, the content is stored as given, and if such 
storage is invalid, the change is not made at all and the request is 
rejected.

> GET(PUT(X)) <> X

If this were true (that is, GET(PUT(x))<>x), I agree that we would be 
having an invalid use of PUT. However, it is not true. We're in the 
prcess of verifying that its not true for the multiple insertion cases. 
Leaving that aside, for the single element/attribute cases, it is 
definitely the case that GET(PUT(x))=x for successful PUTs. If you don't 
think its so, please point to the specific case.

Also keep in mind (perhaps this is part of the confusion here), that the 
approach for server assigned URI has changed. The server is not (as 
currently suggested in the spec) adding the URI. Rather, the user makes 
a request with no URI. The server rejects the request, since one is 
required, and the body suggests possibilities. The client then retries 
the request with one of the allowed possibilities, and that is used as 
provided. We agreed on that earlier in the thread, but its not in the 
current doc yet.

>>> HTTP do they think xcap violates or breaks? I can point to an 
>>> explicit piece of POST it breaks (that is, if we used POST, it would 
>>> not make any sense to GET to that same URI, and we are doing that).
> 
> 

OK, thats a fair point. I don't thnk its always, or even usually true, 
in today's HTTP applications, but we could define it this way if we so 
chose.

So, I think it comes down to the question of whether it is a fair usage 
of PUT to decide on whether to accept or reject the request based on 
whether or not the content is something you are happy with. I think it 
is, and I'll try to see if I can find some more supporting documentation 
in rfc2616 besides the one I've already pointed out (the 409 response 
code would be useless if it wasnt OK).

-Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 05:29:31 -0400

inline.

No, it does not do this.

No, it does not do this.

-Jonathan R.

---

From: "Joel M. Halpern" <[email-masked]>
Date: Thu, 20 May 2004 12:03:50 -0400

In one of the earlier descriptions, you (Jonathan) described:

 > 1. break the URI into a sequence of N selectors, each one selecting a
 > specific element
 >
 > 2. if there isn't N elements in the body, reject the request
 >
 > 3. apply the N selectors to the document

[I can not find a newer description of the algorithm, so I will work from 
there.]

I believe that in order to get the effects that are desired the order must be.
1) break the URI into a sequence of N selectors, each one (presumably 
selecting a specific element.

2) If there are not N top level elements in the body, reject the request.

3) Pair the selector components and the element bodies

4) Order the selectors so that elements with the same path and a positional 
selector are in numeric order.  Reject the request if any paths are 
extensions of other paths. (see other discussion this thread.)

4) Iteratively apply the pair of steps
4a) Apply the selector.  If something other than 0 or 1 elements is 
selected, unwind all changes and reject the request
4b) Apply the put, either as an insert or replace as determined by 4a

5) Verify the document integrity.  If this fails, unwind all changes and 
reject the request.

There are some implications with regard to support of multiple conditions, 
but that is for a different thread.

Yours,
Joel

At 05:04 AM 5/20/2004 -0400, Jonathan Rosenberg wrote:
>So, what I need to show is that the algorithm has two properties - (1) its 
>inserted initially into its final position, and (2) all subsequent 
>elements in order of position, as the algorithm does. That is, if the URI 
>is something like this:
>

---

From: "Joel M. Halpern" <[email-masked]>
Date: Thu, 20 May 2004 12:03:50 -0400

Yours,
Joel

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 14:12:49 -0400

Joel M. Halpern wrote:
> [I can not find a newer description of the algorithm, so I will work 
> from there.]

I had posted a much more detailed algorithm in a note on 5/17 
(http://www.ietf.org/mail-archive/working-groups/simple/current/msg02960.html), 
which was this:

4. if the number of elements selected is not 0 or N, reject the request

5. if step 3 yielded N elements, this is a replacement. For each element
selected, replace it with the element content from the body
corresponding to the URI component used in the selection. Verify that,
for each of the N selectors, the content just inserted is selected by
it. If not, reject the request. if so, done.

6. we are now dealing with the case where step 3 yielded zero elements.
Firstly, take the N selector/element content pairs, and reorder them.
The reordering is done thusly. The ordering is by path-length of the
selector. If two selectors have the same path length, and have different
paths, the ordering is irrelevant between them. If they have the same
path length and the paths are the same, then they differ by predicate.
If the predicate includes a positional selector, order them based on the
position, with lowest first. If they have the same positional selector,
its an error. If there is no positional selector, ordering between them
is irrelevant.

7. OK, now, execute an insertion of each of the selector/element pairs
IN ORDER, each one done independently. For each, treat it as if that
selector/element was received in a PUT by itself. For each, if, when you
evaluate the URI/selector, it points to an element that exists in the
document, its an error - reject the request.

> 4) Order the selectors so that elements with the same path and a 
> positional selector are in numeric order.  Reject the request if any 
> paths are extensions of other paths. (see other discussion this thread.)
> 

This is close to what I describe above, but allows for operations that 
consist of part modifications, part insertions. Maybe thats OK, but its 
a difference.

I also had described an ordering by path length, but based on recent 
discussions, if we disallow nesting, this step is unneeded.

I had an error check to make sure the positional indicators are unique; 
this is a necessary step as I outlined in my proof of idempotency.

You have the "validate when done" step, which I have omitted. It is of 
course a necessary step.

Beyond that, I think its more or less the same.

So, it does raise an issue about whether, if we do multiple insertions 
(and its still not a given), can a PUT operation modify some elements 
and insert others? I'll have to consider whether there are implications 
of it...

Thanks,
Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Thu, 20 May 2004 14:12:49 -0400

Thanks,
Jonathan R.

---

From: "Joel M. Halpern" <[email-masked]>
Date: Thu, 20 May 2004 14:39:38 -0400

[Sorry to copy so much, but I think we need the "steps" under discussion.]

There are actually two significant differences in the processes.
One, as you note is that my suggestion allows for mixing inserts and 
modifies.  While I consider that desirable, it is actually a consequence of 
the other change whcih I consider necessary.

Locators must be evaluated only after earlier insert / modifies have been 
done.  This is true even if we restrict things to being only inserts or 
only modifies within a single PUT.

Simplifying by eliminating most of the paths, suppose I have a list of 3 
bar elements:
    <bar id="q"/>
    <bar id="l"/>
    <bar id="p"/>
and I want to insert two more elements (id="m" and id="d"), one each before 
and after the id="l" element.  I will use positional references.
In several of the messages, it has been clear that the URI expression should be
     bar[2][@id="m"]|bar[4][@id="d"]

If I evaluate those both before doing either insertion, the second one will 
evaluate to the end of the list.  If I do that, and then perform a get 
using the same URI, I will get id="m" and id="p" because the list will be
    <bar id="q"/>
    <bar id="m"/>
    <bar id="l"/>
    <bar id="p"/>
    <bar id="d"/>

On the other hand, if I evaluate the bar[2][@id="m"] element, determine its 
location, apply its insertion, and then evaluate the bar[4][@id="d"], 
determine its location, and apply its insertion, I will get the right 
result, namely:
    <bar id="q"/>
    <bar id="m"/>
    <bar id="l"/>
    <bar id="d"/>
    <bar id="p"/>
Which has the property that get(put(x)) == x.

This changes what was step 3 "apply the N selectors to the document".

Yours,
Joel

At 02:12 PM 5/20/2004 -0400, Jonathan Rosenberg wrote:

>consist of part modifications, part insertions. Maybe thats OK, but its a 
>difference.
>
>(and its still not a given), can a PUT operation modify some elements and 
>insert others? I'll have to consider whether there are implications of it...
>
>Thanks,
>Jonathan R.
>
>
>--

---

From: "Joel M. Halpern" <[email-masked]>
Date: Thu, 20 May 2004 14:39:38 -0400

Yours,
Joel

---

From: Dean Willis <[email-masked]>
Date: Thu, 20 May 2004 18:15:36 -0500

Ahah! I think we have the heart of the matter. I've elided some of the 
conversation, leaving what I think is teh critical thread. I'll respond 
below.

Jonathan Rosenberg wrote:
 > Dean said:
>> That "validation" phase is where I think we have server-side loic that 
. . .

>> Or, the server might attempt to correct the content, storing something 
>> that is schematically valid but inconsistent with intent.
> 
> 
> No, it does not do this.
> 
. . .
> provided. We agreed on that earlier in the thread, but its not in the 

I think you have it here -- my argument was indeed based on the status 
of XCAP as of the tutorial presented in Seoul, and we did agree to 
change this behaviour earlier in this thread. With the revised handling, 
I think we're OK.

It's still a little bit of a stretch on the semantics of 409, but I 
think we're down to an "angels dancing on pins" problem rather than 
something fundamental.

--
Dean

---

From: Dean Willis <[email-masked]>
Date: Thu, 20 May 2004 18:15:36 -0500

. . .

. . .

--
Dean

---

From: Jonathan Rosenberg <[email-masked]>
Date: Sun, 23 May 2004 18:49:19 -0400

Great! Anyone else still think it needs to be POST? I'd really like to 
close this issue (we'll discuss at the interim of course).

-Jonathan R.

Dean Willis wrote:

>>> That "validation" phase is where I think we have server-side loic 
>>> that exceeds the expressivity of PUT.
>>
>>
>>
>> before deciding whether to accept the request or not. Such validation 
>> is an essential part of the protocol and cannot be avoided. You say 
>> that such validation is not allowed for PUT, and I say, it is. To me, 
>> the 409 response code seems to be a good indicator that its ok to 
>> reject a request because of a content problem. I do agree that we're 
>> pushing on boundaries here, but I believe we fall on the right side of 
>> PUT.
>>
> . . .
> 
>> Also keep in mind (perhaps this is part of the confusion here), that 
>> the approach for server assigned URI has changed. The server is not 
>> (as currently suggested in the spec) adding the URI. Rather, the user 
>> makes a request with no URI. The server rejects the request, since one 
>> is required, and the body suggests possibilities. The client then 
>> retries the request with one of the allowed possibilities, and that is 
>> used as provided. We agreed on that earlier in the thread, but its not 
>> in the current doc yet.
> 
>

---

From: Jonathan Rosenberg <[email-masked]>
Date: Sun, 23 May 2004 19:23:45 -0400

inline.

Joel M. Halpern wrote:

> modifies.  While I consider that desirable, it is actually a consequence 
> of the other change whcih I consider necessary.
> 
> Locators must be evaluated only after earlier insert / modifies have 
> been done.  This is true even if we restrict things to being only 
> inserts or only modifies within a single PUT.

I believe thats a neccesary feature of the algorithm, in order to keep 
it simple. However, the primary requirement is that the locators 
properlty identify each element after all insertions have been done. 
Thats absolutely essential to maintain the GET(PUT(x))=x property.

> and I want to insert two more elements (id="m" and id="d"), one each 
> before and after the id="l" element.  I will use positional references.
> If I evaluate those both before doing either insertion, the second one 
> will evaluate to the end of the list.  If I do that, and then perform a 
> get using the same URI, I will get id="m" and id="p" because the list 
> will be
>    <bar id="q"/>
>    <bar id="m"/>
>    <bar id="l"/>
>    <bar id="p"/>
>    <bar id="d"/>

Right. The problem is that, as al *algorithm*, evaluating the locators 
before inserting doesnt work.

> 
> On the other hand, if I evaluate the bar[2][@id="m"] element, determine 
> its location, apply its insertion, and then evaluate the 
> bar[4][@id="d"], determine its location, and apply its insertion, I will 
> get the right result, namely:
>    <bar id="q"/>
>    <bar id="m"/>
>    <bar id="l"/>
>    <bar id="d"/>
>    <bar id="p"/>

Ah, I see.

In my version, since I didn't allow mixing of insertions and 
modifications, such a step was fine. It served mostly to make a 
determination about which case we had - an insertion (0 matches) vs. a 
modification (N matches). In the case of insertion, I would then go and 
insert the elements one at a time, each one requiring the re-evaluation 
of the locator to perform the insertion (as you suggest) - this is 
described in step 6. In the case of a modification, we have no problem 
since all of the elements to be modified exist in the document already.

If we allow a mix, we would need to eliminate this step, primarily 
because behavior wouldn't be different for insertion vs. modification.

Having thought about it some more, I dont see any problems with allowing 
mixed insertions/modifications. As long as you check ahead of time that 
no two locators identify elements that are the same or are descendants 
or each other, it should be fine. The processing I suggest in step 6 
will work.

-Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Sun, 23 May 2004 18:49:19 -0400

-Jonathan R.

---

From: Jonathan Rosenberg <[email-masked]>
Date: Sun, 23 May 2004 19:23:45 -0400

inline.

Ah, I see.

-Jonathan R.

---

From: Jari Urpalainen <[email-masked]>
Date: Mon, 24 May 2004 10:14:17 +0300

> or each other, it should be fine. The processing I suggest in step 6 

in step 6 the server is required to order sibling node requests. IMO,
the clients should at least be adviced to give them already as ordered
as it has also performance implications. 

I have a related question about server side checks related to
get(put(x))=x behavior. As put in XCAP means also replace in addition to
append/insert consider the case where a client will try to change e.g.
attribute content with a request like put /a[@b="foo"]/@b with content
"bar" when there already exists <a b="foo">. At least my implementation
would happily apply the request and result would be <a b="bar">.
However, this would break get(put(x))=x as how I understand this is that
you have to have exactly the same R-URI in both requests. Of course,
this won't happen if the request is e.g. like /a[3]/@b, but that's not
the point. So does the server has to check that get(put(x))=x applies to
this case too ? Similar cases may easily happen with text-node
comparisons.

BR,
Jari

---

From: Jari Urpalainen <[email-masked]>
Date: Mon, 24 May 2004 10:14:17 +0300

BR,
Jari