medabdellahi / google-caldav-issues

Automatically exported from code.google.com/p/google-caldav-issues
0 stars 0 forks source link

PUT fails with 'incorrect resource name' #12

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. PUT /calendar/dav/USER/events/z1-20080805-124432-023-1.ics
   If-None-Match: *
   Content-Type: text/calendar; charset="utf-8"; component=VEVENT
   auth etc

   BEGIN:VCALENDAR ... etc

What is the expected output?

A 201 Created HTTP response.

What do you see instead?

A HTTP 403 (Forbidden) with:
---snip---
<HTML>
<HEAD>
<TITLE>incorrect resource name for event z1-20080805-124432-023-1</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>incorrect resource name for event z1-20080805-124432-023-1</H1>
<H2>Error 403</H2>
</BODY>
</HTML>
---snap---

(Notably the 403 response has the content-type application/xml which is
also wrong, its clearly HTML).

Please provide any additional information below.

A PUT with iCal.app works fine, so it must be specific to my request. The
way it looks, I would guess that Google CalDAV requires that the UID of the
VEVENT is equal to the resource name.
But CalDAV has no such restrictions, UID and URL are completely distinct.

Note that the server can still decide to use a different name if thats
required for storage (eg the UID ...) - after a successful PUT.
It would be great if the server would then set the 'location' header at the
time of the PUT (if it already knows it then).

Original issue reported on code.google.com by helge.h...@googlemail.com on 5 Aug 2008 at 1:00

GoogleCodeExporter commented 9 years ago
I also noticed this and using same resource name as UID (+ .ics extension) 
works fine.

Regarding the previous comment, sending 'Location' on successful PUT (204 or 201
response) is forbidden in HTTP and using 301 redirect as per RFC 2616 with 
Location
header doesn't work with any client I've tried.

Original comment by filip.na...@gmail.com on 5 Aug 2008 at 3:52

GoogleCodeExporter commented 9 years ago
There are long discussions on that (just check Google :-), but I'm not aware of 
any
section in HTTP which _forbids_ using location with PUT 204/201. Its mostly the
semantics which are not 100% obvious from the spec and can be argued over.

Sending it at least doesn't hurt any client I've tried ;-)

But in general I agree, the best thing to do is to preserve the relative URL. 
This
avoids all further issues.

Original comment by helge.h...@googlemail.com on 5 Aug 2008 at 4:46

GoogleCodeExporter commented 9 years ago
I've read it all Helge, believe me :) and I don't want to dwelve into this 
debate again.

My stance on this is to respect RFC 2616, section 9.6. - "The PUT method 
requests
that the enclosed entity be stored under the supplied Request-URI". Ok, section
10.2.2. (titled "201 Created") says "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.", but it's neither SHOULD nor MUST.

Certainly I hope to reach the concensus that relocating resources on PUT causes
interoperability problems and that preserving URLs is for the best. This is 
what I
know about the clients that I looked at:

- Mozilla Sunbird/Lightning currently supports relocating within the same 
collection.
On each event upload a PUT is issued, followed by calendar-query on the same
collection (with UID filter) and finally by GET. There were discussions about
changing this behavior in future, but today's build works this way. Any returned
Location is ignored, 301 redirects on PUT don't work, relocating to different
collection is impossible.

- Apple iCal (as of 10.5.4 MacOS X) doesn't work with relocated resources and 
ignores
Location on PUT.

- ZideOne respects Location header I guess (helge.hess would know better, but 
this is
what I gathered from reading their web site).

- eM Client in the current nightly builds is able to work with relocated 
resources,
but only if the Location header is returned by the server. It is totally 
unsupported
configuration though and as such doesn't pass the regular QA testing.

Original comment by filip.na...@gmail.com on 5 Aug 2008 at 5:13

GoogleCodeExporter commented 9 years ago
I think we basically agree.

a) The HTTP spec nowhere specifies that the Location header is
   _forbidden_ with 201 or 204. As you say, it does not require
   it either, which is fine. At best the specific combination
   is undocumented.

b) More importantly, returning a Location doesn't hurt any known
   client (and there are no known reasons how it could
   potentially hurt an implementation), while it does support
   clients which expect it.
   So adding it is not a bad idea. I agree this aspect is
   debatable ;-)

c) If the clients choose to do additional work, eg issuing a UID
   REPORT just to be sure, thats perfectly fine too.

My wish for Google Calendar would be: do no server URL rewrites at all. No 
relocation
issues at all. Thats the best case :-)

Thanks,
  Helge

Original comment by helge.h...@googlemail.com on 5 Aug 2008 at 5:51

GoogleCodeExporter commented 9 years ago
I don't think its a good idea to move the resource after a PUT. OGO has been 
doing
this and we needed to work around by using a fetch-by-uid query, which is not
supported by all servers. We are actually getting rid of this code quite soon. 
I'm
not quite sure of the details, but Bruno told me that moving the resource 
violates a
couple points of the CalDAV spec.

I agree, no relocation at all is the best solution.

Original comment by kewi...@gmail.com on 6 Aug 2008 at 5:59

GoogleCodeExporter commented 9 years ago
The server should definitely allow you to write an event under virtually any 
resource
name you want, but I can't find anything in the CalDAV spec that forbids 
servers from
relocating resources.  In fact, it is generally required for CalDAV servers to
rewrite resources to maintain some kinds of semantic consistency (for example, 
you
respond to an event, and the event is updated in my calendar collection).  I 
think
you should reasonably expect server rewriting and relocating to continue, and
periodically sync with the server (use PROPFIND depth=1) on all events in the
collection.  Alternately, perhaps we should nail down the resource names for 
events
in an update of the CalDAV specification, based on UID.ics.  I don't believe 
clients
gain anything by being able to make up arbitrary resource names.

Original comment by neal.gaf...@gmail.com on 11 Aug 2008 at 7:13

GoogleCodeExporter commented 9 years ago
Sorry for the long reply, a Google CalDAV Google group would be
better for such discussions?

> The server should definitely allow you to write an event under
> virtually any resource name you want

Thats the biggest issue in the current setup. Apparently Google CalDAV
demands that the VEVENT UID matches the resource name. (I think it
actually allows arbitrary names as long as they match the UID)

The WebDAV/CalDAV flow of creating an event under a unique resource
name (w/o LOCK) is a PUT loop with If-None-Match: *, in pseudo code:

  for (counter = 0; counter < 10; counter++) {
    status = PUT ( URL-$counter, If-None-Match: *, $ICAL);
    if (status == 201|204) break;
  }

In short the client attempts a different URL until one is available. By
choosing a pretty unique base URL, multiple PUT attempts are the
exception.

One problem with requiring a UID/URL match is that the $ICAL would
need to be regenerated on each attempt. Which is hard, especially
due to the layering in HTTP libraries (generating the content and
PUTting that to the server are layerwise completely independend
operations).

[maybe open a different issue for the following issue]
> but I can't find anything in the CalDAV spec that forbids servers
> from relocating resources.

It is allowed but has major issues when the 'location' header is
unsupported (and 'location' in PUT responses has 'issues' too).
All WebDAV operations are transactionally safe when used with
proper If headers.

A common workaround is to search using a uid-match REPORT after the
PUT. BUT this isn't transactionally save anymore. The client can't
know whether the resource was modified in the meantime:

  Client A: PUT resource.ics[uid=123]
  Client B: PUT resource-moved.ics[uid=123]
  Client C: REPORT uid=123
  => Client A can't know the record was changed by Client B

That issue gets bigger the more clients work on the same collection,
race conditions are not that unusual as one might think.

Note: transactional safety with relocating servers can be
ensured by using 'location'.

[maybe open a different issue for the following issue]
> In fact, it is generally required for CalDAV servers to
> rewrite resources

Yes, that is a very similiar but slightly different issue. To
properly support rewriting in a safe way, the server would need
to return an ETag in the PUT response which identifies the
state of the resource submitted by the client. The client can
then perform a GET If-None-Match: PUT-ETag. If the server
returns a 304, it did NOT rewrite the content. If it returns a
2xx, it DID rewrite the content (and returns it PLUS the new
etag identifying the rewritting content).

But this raises discussions similiar to the Location ones.

> I think you should reasonably expect server rewriting and
> relocating to continue, and periodically sync with the server
> (use PROPFIND depth=1) on all events in the collection.

This needs to be done _immediatly_ (either PROPFIND, GET and/or
REPORT-uid). Otherwise the client can't do subsequent writes
properly (the cache will point to a different URL, and then
potentially recreate the resource [yes, there is the UID
restriction which is partial protection]).

> Alternately, perhaps we should nail down the resource names
> for events in an update of the CalDAV specification, based
> on UID.ics.

I don't think this would be a good thing to do. I would rather
live with the REPORT/location hacks.

> I don't believe clients gain anything by being able to make up
> arbitrary resource names.

They gain compatibility with WebDAV :-) You might think that
this is useless, but actually its not. If the client can restrict
its operations to GroupDAV/WebDAV, it can actually work with a
plain WebDAV server (eg Apache mod_dav). Which basically has no
functional loss for native clients!

If we would want to make arbitrary restrictions on the protocol,
we could just go for GData :-)

Summary for this issue: to get going it would be good if Google would support 
writing
of resources where the resource name does not match the UID. It would be very 
good if
the server would preserve the resource name and NOT rewrite the location to the 
UID.
(common, it should be too hard to maintain a second UID (aka relative URL) in 
some
extended attribute of your store! :-)

Thanks,
  Helge

Original comment by helge.h...@googlemail.com on 11 Aug 2008 at 8:14

GoogleCodeExporter commented 9 years ago
OK, added Issue 18 (the server moving resources) and Issue 19 (the server 
rewriting
resources) to better track the issues I raised in my last comment.

Original comment by helge.h...@googlemail.com on 11 Aug 2008 at 8:41

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
>> I don't believe clients gain anything by being able to make up
>> arbitrary resource names.

> They gain compatibility with WebDAV :-) You might think that
> this is useless, but actually its not. If the client can restrict
> its operations to GroupDAV/WebDAV, it can actually work with a
> plain WebDAV server (eg Apache mod_dav). Which basically has no
> functional loss for native clients!

So it seems to me it would be best to let my client use UID's
for URL's. In this way my client respects the GroupDAV/WebDAV
protocol and will also work with google CalDAV.

> A common workaround is to search using a uid-match REPORT after
> the PUT. BUT this isn't transactionally save anymore.

Assuming the client uses UID's for URL's this will not be necessary
I guess, because the client knows the resource is not going to be
relocated (I know this is google CalDAV specific and I also assume
resource rewriting isn't going to be a problem). Depending on the
location header after a put doesn't seem to be a good idea either
because its use is controversial and it seems to be broken anyway:
see issue 18, comment 3.

Original comment by dar...@gmail.com on 7 Sep 2012 at 12:23

GoogleCodeExporter commented 9 years ago
> Assuming the client uses UID's for URL's this will not be necessary I guess, 
because the client knows the resource is not going to be relocated

A UID is only required to be unique within a collection by CalDAV. You are 
probably thinking GUID, but a UID doesn't have to be a GUID (though some 
clients use one). CalDAV doesn't require that. UIDs in current deployment are 
very diverse.

Either the client or the server needs to rewrite a UID or the resource URL for 
such servers, if the server requires them to match. I agree that using Location 
is problematic, which is why the server should do it right in the first place 
(aka separate resource name from the entities UID as required by the spec).

Currently CalDAV has no notion to enforce a URL based on some embedded property 
of a resource. We have the uid-conflict precondition in case a UID is already 
taken, but thats the reverse.
As far as I can see the only way to hack that up is the silently move the 
resource. That'll probably work somewhat, but is a dirty hack which potentially 
results in follow-up issues on the client side.

Original comment by helge.h...@googlemail.com on 11 Sep 2012 at 5:55