Subject: Status code for creating lock-null resource

From: "Lisa Dusseault" <[email-masked]>
Date: Thu, 14 Jun 2001 09:54:15 -0700

RFC 2518 seems to want 200 OK for the response to a LOCK request.  However,
that means clients can't tell the difference between a lock of an existing
resource and the creation of a LOCK-null resource.  Shouldn't 201 Created be
returned if a lock-null resource is created?

lisa

---

From: "Hall, Shaun" <[email-masked]>
Date: Fri, 15 Jun 2001 10:15:59 +0100

Granted a client cannot tell the difference as you state *if* they took no
preceding action.

However, I don't think the spec should be changed:

1) Obviously it would go against the definition in RFC 2616 for 201 Created.
2) You haven't actually created a resource. An LNR doesn't physically exist,
you've only reserved the "name". You have created a lock, but that is not
the same thing.
3) Doesn't make sense to me to get a "201 Created" response for a successful
LNR, then if you tried to DELETE or GET it for example, get a 404 or 405 (as
per RFC 2518 sec 7.4).
4) Might break existing applications etc.

Alternatively, a client could perform one of a number of actions to discover
that the resource didn't exist before they attempt to LOCK it (create the
LNR) and get a 404.

Side notes - results when creating an LNR with:

5) mod_dav pre v1.0 (think v0.9.16) returns a 200 OK response.
6) IIS 5.0 (on Win2K) returns a 201 Created response.

Regards

Shaun Hall
Xerox Europe

> -----Original Message-----
> From: Lisa Dusseault [mailto:[email-masked]]
> Sent: 14 June 2001 17:54
> To: Webdav WG
> Subject: Status code for creating lock-null resource
> 
> 
>

---

From: [email-masked]
Date: Fri, 15 Jun 2001 12:03:56 +0100

"Hall, Shaun" <[email-masked]> wrote:
> 2) You haven't actually created a resource. An LNR doesn't
> physically exist, you've only reserved the "name". You have
> created a lock, but that is not the same thing.

Arrgh, where did this idea that a resource must "physically exist" come
from??

In what sense does  http://foo.com/cgi-bin/quote?myportfolio,yesterday  (or
whatever) 'physically exist'?

A 201 Created response looks like the ideal response for the creation of a
lock-null resource.  I did not read anything in RFC2616 to contradict that.

> 3) Doesn't make sense to me to get a "201 Created" response
> for a successful LNR, then if you tried to DELETE or GET it
> for example, get a 404 or 405 (as per RFC 2518 sec 7.4).
> Alternatively, a client could perform one of a number of
> actions to discover that the resource didn't exist before
> they attempt to LOCK it (create the LNR) and get a 404.

Lock-null resources are generally bad and should have been strangled at
birth.

> 6) IIS 5.0 (on Win2K) returns a 201 Created response.

Tim

---

From: "Clemm, Geoff" <[email-masked]>
Date: Wed, 27 Jun 2001 17:21:12 -0400

Yes, I think violent agreement is accurate description
of our attitude toward lock null resources.

The reason I believe backward compatibility is not
an issue here is that very few servers have
implemented the specified lock-null behavior (e.g.
auto-delete on unlock, or the ability to create an
arbitrary type of resource at the locked URL
(e.g. a collection by MKCOL).

Since there is no common functionality for lock-null
resources today, the only interoperable thing a
client can do today is to
create the resource first and then lock it.
So I'm just suggesting that we capture that interoperable
approach in the revised spec.

So I think we should just say "A server SHOULD fail
an attempt to lock an unmapped URL", and then remain
silent on what a server might end up doing if it lets
the lock of an unmapped URL succeed.  In general,
a MAY here is of little more use to the client than having
the protocol remain discretely silent, and the
benefit of using one of the several different
flavors of lock-null behavior is unlikely to warrant
writing special purpose code for each of those flavors.

Cheers,
Geoff

-----Original Message-----
From: Dan Brotsky [mailto:[email-masked]]
Sent: Wednesday, June 27, 2001 4:28 PM
To: Clemm Geoff
Cc: [email-masked]
Subject: RE: Status code for creating lock-null resource

So it sounds like you and I are in violent agreement about this: we 
both believe LOCK should simply create a no-content resource that's 
mapped to the URI and locked.  You seem to take the additional 
position that there shouldn't be any way for clients to request the 
"auto-delete on unlock" behavior.  It also sounds like you're 
suggesting that servers shouldn't be allowed to implement the 
"lock-null special method handling" or "auto-delete on unlock" 
behavior as a matter of policy, but (while I might agree this is not 
a good thing for them to do) I don't think we should be trying to 
legislate server policy (and it would be a hugely 
backward-incompatible change).

     dan

At 3:46 PM -0400 6/27/01, Clemm, Geoff wrote:
>I agree with point 0, but believe there is a much simpler
>answer to points 1 and 2.  In particular, we just define a LOCK
>on an unmapped URI as just being equivalent to an atomic
>PUT (with an empty body) followed by a LOCK.  No other special
>behavior.
>
>I am very much against making any of this behavior server-defined.
>That would just make the already difficult job of writing an
>interoperable client that much harder.
>
>And if I really could roll back time, I'd say: "LOCK on an
>unmapped URL just fails" (i.e. you can only LOCK a URL if
>there is a resource mapped to that URL).  If you want to LOCK
>a URL, you first have to create a resource at that URL to
>display the lock.  If some other client gets their
>lock in before you, that's no different from somebody today
>getting their lock-null resource created before you.  In either case,
>you have to either try your request again at some other URL,
>or wait until the other client releases the lock.
>
>Cheers,
>Geoff
>
>From: Dan Brotsky [mailto:[email-masked]]
>Sent: Wednesday, June 27, 2001 2:10 AM
>To: Tim Ellison
>Cc: [email-masked]
>Subject: RE: Status code for creating lock-null resource
>
>
>I'm definitely in the camp that thinks lock-null resources should go
>away in the next revise of 2518, and I very much like the way this
>discussion went, which I would summarize as:
>
>0. we don't talk about "null resources" any more, just unmapped-URIs.
>
>1. lock-null resources are just "regular resources" that are required
>to respond to certain methods in certain ways.
>
>2. creating a lock-null resource should return 201
>
>So far I would say a simple rephrasing might be:
>
>a. The result of a LOCK call on an unmapped-URI is that the URI gets
>mapped to a no-content resource that responds to certain (non-write)
>methods with 404 or 405.
>
>But the problem with this rephrasing is that:
>
>3. GET on the resource returns 404 or 405 not 204 (as would be
>expected for a "regular" no-content resource).  [Aside: 404 really
>makes no sense here, given that the resource is required to appear as
>a member of its parent collection - PROPFIND returns 207 but GET
>returns 404?  But that's a different issue.]
>
>4. OPTIONS and other non-write methods return 404 or 405 for no
>particular reason.
>
>5. UNLOCK on the resource returns the URL to an unmapped state.
>
>Note that restrictions #3 and #4 are unmotivated, as far as I can
>tell; the only "special" aspect of this resource (aside from #5) is
>that the server really can't know whether it's a collection or not.
>[Aside: The DAV:resourcetype property really needs another value in
>these cases, such as "indeterminate".  But that's another issue.]
>
>Which brings us to #5: UNLOCK (essentially) deletes the resource.  I
>think I understand the motivation for this: a client that locks the
>URI but then decides not to write it doesn't want to have to do a
>delete in order not to leave an empty resource mapped to the URI.
>But my problem is that the spec *mandates* this behavior, rather than
>leaving up to the server (or allowing the client to request it
>specially as part of the UNLOCK).
>
>Essentially the spec is requiring that a LOCK/UNLOCK combination with
>no intervening write operations do *nothing* to a URI or the resource
>mapped to it.  (This is a mandate that has been picked up in deltaV,
>as well.)  But while I can understand that servers might want to work
>this way, and that clients might want to request this, I can see no
>reason to mandate this.
>
>In fact, my experience with building workflow and document-management
>servers leads me to entirely the other conclusion: servers need the
>discretion to interpret LOCK as a statement of intent in the
>workflow, one that an UNLOCK does not necessarily "undo."  In
>particular, LOCK is the only way in WebDAV for a client to create a
>no-content resource (as opposed to one with content-length 0), and
>just because the client doesn't create the content before unlocking
>doesn't mean that the client wants the created resource (and live
>properties such as its creator) to be expunged from the server.
>
>As we revise 2518, I think we should give servers much more
>discretion about how they handle LOCK/UNLOCK pairs, and possibly we
>should give clients a way of indicating in the UNLOCK that "the lock
>was a mistake, undo it if you can" (much as deltaV allows undoing a
>checkout).  If we do so, I think lock-null resources (and their
>concomitant problems) can be done away with completely, and LOCK can
>simply be seen as creating a no-content resource when applied to
>unmapped URIs.  Servers who wish to preserve the lock-null kinds of
>behavior for those resources are welcome to, and they will still be
>in compliance with the spec.
>
>      dan
>--
>Daniel Brotsky, Adobe Systems
>tel 408-536-4150, pager 877-704-4062
>2-way pager email: <mailto:[email-masked]>

-- 
Daniel Brotsky, Adobe Systems
tel 408-536-4150, pager 877-704-4062
2-way pager email: <mailto:[email-masked]>

---

From: "Hall, Shaun" <[email-masked]>
Date: Thu, 28 Jun 2001 13:49:32 +0100

Bits snipped. All IMHO...

> From: Alan Kent [mailto:[email-masked]]
> Sent: 28 June 2001 06:56
> To: [email-masked]
> Subject: Re: Status code for creating lock-null resource
> 
> Without the current LOCK semantics, you would have to do a PUT to
> create an empty file and then LOCK it. Does PUT have an OVERWRITE Y/N
> flag? (I dont have the spec handy). If it always overwrites, then
> there is the potential for a race condition.

There is no Overwrite with PUT. Unless you use one of the If-* headers, PUT
will overwrite the existing resource (assuming permissions etc are okay).
This is the kind of thing LOCK is suppose to deal with.

> 
> Personally I would say tough luck. The above seems important in /tmp
> or C:\temp etc, but not on a WebDAV file system. And there are lots of
> potentials for race conditions in other parts of WebDAV arn't there?
> (OK, so I don't actually know of any...). So why worry about one case
> when it makes things so much more confusing overall?
>
> Alan

There are lots of conditions and requests that conflict with each other, so
it is important. In fact, some servers have "undefined" behaviour.

Am I the only person who actually has no real big problem with lock-null
resources (LNRs) ?

Regards

Shaun Hall
Xerox Europe

---

From: "Jason Crawford" <[email-masked]>
Date: Thu, 28 Jun 2001 15:55:12 -0400

> >   At any
> >rate, I wouldn't support adding a completely new concept (no-content
> >resources) even if we did remove the lock-null concept.
> No-content resources are not new; they're in HTTP 1.0 and 1.1.
I agree and to go further, the point isn't that there is no content.  We
might chose to enhance this later to allow it to have content or to create
a type of resource that doesn't even have the concept of content.  The
point isn't content or no-content.  The real point is that a resource is
created.

---

From: "Clemm, Geoff" <[email-masked]>
Date: Fri, 29 Jun 2001 10:59:22 -0400

But in the workflows I described, the user concept is not "intent
   to create" per se, it's "intent to edit, creating if necessary".
   From a user point of view, I'm being asked to work on resource
   "foo," creating it if necessary.  I don't want to have to tell my
   client to do something different in the two cases.

I understand and agree with that, but in general, a user gesture
will invoke several client requests (sometimes a very large number).
Your client will be doing at least 2 requests for this gesture
anyway (i.e. LOCK/GET), so having it do 3 requests (i.e. PUT/LOCK/GET)
is not qualitatively different.  In somewhat more detail:

PUT(URL)/if-does-not-exist
LOCK(URL)
if (lock-failed)
  then report-error; break;
GET(URL)
PROPFIND(URL, appropriate-authoring-properties)

Notice that the only difference in this sequence and the one you
suggest is the initial "PUT(URL)/if-does-not-exist".  That additional
request seems to be a relatively minor imposition on the client,
compared to the complexity of dealing with the variety of ways that
servers end up handling LNRs.

   I just want to
   tell it "I want to edit 'foo'; do the right thing."  Which, if we
   allow LOCK to create foo if necessary (as it does currently), is
   always done by the sequence LOCK / GET (but only if the GET is
   allowed to succeed on the LOCKED created resource).

Yes, I agree that this is a good argument against the current LNR
behavior of returning a 404 on a GET.  In general, this is a very good
argument for why a client can be written more simply if there is a
"real" resource that holds the lock, instead of some "null" resource
with special behavior.

   I actually think (from your next message) that we agree about what 
   should happen.  And I actually believe that LNRs can be changed 
   fairly easily to be "empty" rather than "null" resources; all we have 
   to do is remove the method response restrictions AND take away the 
   "auto-delete" on UNLOCK behavior.

Yes, but if we are going to implicitly create a real resource, I think
it is a simpler and more consistent model to just have the client
explicitly create the resource.  In particular, the "auto PUT with an
empty body" doesn't handle the case where you want to create a
collection there.  That's what motivated the "auto-morph" behavior
of a LNR.  If the client just creates the kind of resource it
wants there (PUT, MKCOL, MKWORKSPACE, whatever), you can do what you
need without having to have a special "LNR" that has the ability to
morph into another kind of resource (thus requiring special code in
MKCOL, MKWORKSPACE, etc.).

   A no-content resource is one which returns 204.  (By the way, some 
   servers do this for directory resources when "default docs" and 
   "directory listings" are turned off.)  The response means "there's a 
   resource here but it has no body (and thus no mime type).

   A 0-length resource corresponds to a 0-length file in a file system; 
   it has a MIME type but no octets.

   No-content resources and 0-length resources both show up in listings 
   and both respond to GET.

A problem with distinguishing no-content resources from 0-length
resources is that most repositories have no such distinction, and
it is a non-trivial amount of work to layer this distinction on
existing repositories.  Which means you want to require it only if
it really gives you significant benefit.  But either the no-content
has the auto-morph capability (which means every "create" method
has to have a special case for it), or it does not, in which case
it does not handle any of the LNR use cases that are collections or
other types of resources not created by PUT.

   >   It might be just as
   >hard for servers to handle no-content resources (if they currently only
   >handle 0-length resources) as it is to support a lock-null resource.

   That's a good point.  But I'm not arguing against LNRs cause I think 
   they're hard to implement :^).  I don't like their conceptual model, 
   and I think we don't need to introduce them at all.

I'm somewhat different ... I believe they are a pain to implement,
I'm fairly neutral on their conceptual model, but then agree with
you on the conclusion, i.e. that we don't need to introduce them at
all.  

Yes, but the distinction between a no-content and zero-length resource
is made by many repositories, and is not a feature currently required
by 2518 servers, so requiring it for locking behavior would be
problematic.

Cheers,
Geoff

---

From: "Clemm, Geoff" <[email-masked]>
Date: Fri, 29 Jun 2001 10:59:24 -0400

I think the only thing that currently separates what Dan and I
prefer is the "explicit initial resource creation".  So at the
risk of being repetitive, I'll try to give a detailed response
to Dan's message on this issue.

   At 11:00 PM -0400 6/27/01, Clemm, Geoff wrote:
   >    ... it doesn't allow users to
   >    simultaneously create and LOCK resources for further editing, which
   >    bothers me.
   >Could you expand on why this bothers you?

   There are actually three reasons:

   1. Because it sets you up for ambiguity and race conditions by 
   breaking a single user-conceptual operation (beginning to edit a new 
   resource) into two protocol operations (PUT and LOCK).

The conceptual operation is probably "get me the locked
content and properties of this resource so I can edit them".
This will be at least 3 client requests (LOCK, GET, PROPFIND),
so making it be 4 client requests (PUT, LOCK, GET, PROPFIND) is
not qualitatively different.

   A client that 
   wants to create and edit a new resource will go through a 
   conventional sequence such as HEAD (to verify the URL as unmapped), 
   PUT (to create the resource), and LOCK (to reserve the resource for 
   editing).

No need for the HEAD/PUT ... just the PUT/If-None-Match:* is sufficient.

   This conflicts not only with itself but with the conventional
   sequence for editing an existing resource is LOCK / GET (LOCK first
   to make sure the GET content is the latest content).

I don't see that prefixing the LOCK/GET with a PUT/If-None-Match:*
would conflict with anything.

   This gives rise to two canonical problem cases:

   a. If I'm creating and editing a new resource, and you are editing a 
   resource but specify my name by mistake, then my client has to deal 
   with the unexpected (and meaningless at the user level) case where I 
   successfully create the resource but then can't edit it, and your 
   client has to deal with the unexpected (and meaningless at the user 
   level) case where you open a resource to edit it only to find that 
   it's empty or doesn't contain anything like what I was expecting.

The user does not see any of this.  Your client just issues an initial
PUT/If-None-Match:*, and then ignores the result (your client doesn't
care if it ended up creating an empty resource with this request or
not ...  it just wants to make sure it can lock that URL).  From the
user's perspective, it either succeeds, and you have the lock, or it
fails because somebody else has that URL locked (and it doesn't really
matter to the client that the LOCK by that other client was done weeks
ago, or was done a millesecond ago).

   b. If we're both trying to create and edit the same (new) resource, 
   and my PUT precedes yours but my LOCK follows yours, then once I've 
   obtained the LOCK I find that the etag on the resource is different 
   than the one I got back from my PUT.

You don't care at all what the response from the PUT/If-None-Match:*
request was.  You only care what the response is from the LOCK request.

   This is the canonical 
   client-side warning sign that I'm in a race with someone else, and I 
   have to stop and make sure that I pull down the current content.

No race condition here because you don't pull down the current content
until you have the lock.

   At 
   that point, unless you and I were using the same "template" resource 
   in our initial PUTs, I've got a real problem.  I either have to blow 
   away your edit (which I'm not entitled to do under normal 
   circumstances) or I need to give up my lock.

You have exactly the same failure case if your lock succeeds and there
already was a resource there.  It doesn't matter if the resource got
there a millisecond ago or a few weeks ago.

   But by then your LOCK 
   has failed, so you've figured out that someone else is creating the 
   resource and you've given up.

You don't care that someone else is creating the resource ... you only
whether someone else has that resource locked.

   2. Because there's no well-defined way for PUT to reliably create a 
   no-content resource, which is the kind I claim you want to be 
   creating when you're creating a new one but don't have content for it 
   yet.  Most servers given a PUT of 0 length create a 0-length 
   resource, which is quite a different thing than a no-content one.

If a no-content resource can morph into any kind of resource, then
it is difficult to implement (most repositories have no such resource).
If it cannot morph into any kind of resource, then I do not see
an important reason to distinguish a new no-content resource from
a new 0-length resource.

   3. Because doing a PUT and then a LOCK and then (eventually) another 
   PUT forces you to make *two* updates to the resource rather than one, 
   and the controlling server may not actually want to authorize that. 
   (For example, workflow servers often want to send things off for 
   approval, etc., each time they are updated.)

How can something be sent off for approval unless there is a way
for me to store what I want on the server so that it can be approved?

   So let me ask you the converse question: You seem to be worried by
   the fact that we don't know what kind of resource (collection or
   not) the new resource is going to be.  What's the problem with
   letting the new resource start out as a no-content non-collection
   and then be made into a collection?

None of my repositories have a resource that has that behavior.
This means that I have to figure out a way to simulate such a
resource, and have to make sure that the locking semantics is
satisfied by all the other protocols that I currently implement
on my repository.  It is very likely that we would make the same
choice made by most servers today wrt LNR's, namely simply be
non-compliant with the protocol unless a compelling use case
motivated us making this fairly major effort.

   Note that in both of our proposals the same requests are 
   made---either a PUT or a MKCOL and a LOCK.  It's just that in my 
   version the LOCK comes first (a la the LOCK / GET sequence that 
   initiates an edit).  And in my version the client doesn't have to 
   figure out whether the resource exists before initiating the 
   sequence: all edits (of both existing and new resources) start out 
   with a LOCK / GET, and in the case of the create the LOCK comes back 
   with a 201 which tells the client that the GET would return a 204 
   (and thus there's no reason to issue it).

I agree that your proposal would allow the client to omit the
initial PUT/If-None-Match:*, but adding that call in our clients
is trivial compared to the cost of implementing resources that
are locked but can morph to any resource type when first updated.

Cheers,
Geoff