GNOME Bugzilla – Bug 560185
Support 'getctag' in CalDAV, if available
Last modified: 2013-09-14 16:52:36 UTC
I had a chat with karora about CalDAV last Friday and he mentioned that there is an extension for CalDAV, the 'getctag', which, if I got it right, is similar to getetag, but this one is for the whole calendar. We can use this to check for updates only when the ctag changes, which will reduce required bandwidth.
Here's an example of some XML requests and responses using the tag. Firstly, here's a simple one against the calendar URL which will just fetch the calendar's displayname and current getctag. This should be the content of a PROPFIND against URL for the calendar, and should include an HTTP "Depth: 0" header: <?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:" xmlns:CS="http://calendarserver.org/ns/"> <prop> <displayname/> <CS:getctag/> <resourcetype/> </prop> </propfind> The response from a calendar will look something like this (taken from DAViCal 0.9.6.1): <?xml version="1.0" encoding="utf-8" ?> <multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:A="http://calendarserver.org/ns/"> <response> <href>/caldav.php/user2/home/</href> <propstat> <prop> <resourcetype> <collection/> <C:calendar/> <C:schedule-calendar/> </resourcetype> <displayname>home</displayname> <A:getctag>"13249ced6c7527191a003f54f7e3cd25"</A:getctag> </prop> <status>HTTP/1.1 200 OK</status> </propstat> </response> </multistatus> A similar request can also be used against the same calendar URL to fetch the getctag for the calendar, and the getetag for all of the calendar content. This time you should include an HTTP "Depth: 1" header (in order for the PROPFIND request to include the properties of the resources within the collection): <?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:" xmlns:CS="http://calendarserver.org/ns/"> <prop> <CS:getctag/> <getetag/> </prop> </propfind> The response from a calendar will look something like this: <?xml version="1.0" encoding="utf-8" ?> <multistatus xmlns="DAV:" xmlns:A="http://calendarserver.org/ns/"> <response> <href>/caldav.php/user2/home/</href> <propstat> <prop> <A:getctag>"13249ced6c7527191a003f54f7e3cd25"</A:getctag> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <getetag/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> <response> <href>/caldav.php/user2/home/33169d69-2969-4a96-a3e1-2e312b7614e6.ics</href> <propstat> <prop> <getetag>"64d28f4f57515d6c63cec02b5d882eaa"</getetag> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <A:getctag/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> <response> <href>/caldav.php/user2/home/047871e3-6b70-4178-9af8-0ceb50f7b092.ics</href> <propstat> <prop> <getetag>"58cba7e3fafb6080e85619ea77d08c7a"</getetag> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <A:getctag/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> <response> <href>/caldav.php/user2/home/9429a973-2b13-4b1a-be09-948d75425c45.ics</href> <propstat> <prop> <getetag>"13249ced6c7527191a003f54f7e3cd25"</getetag> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <A:getctag/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> </multistatus> This is a constructed response as the actual OK/Not Found propstat responses will vary (DAViCal will actually return a getetag on the calendar URL, for example, which will actually be the same value as the getctag response). Evolution can then ignore the <propstat>... Not Found...</propstat> elements and focus on the successful ones, which contain all of the desired information. Here's some pseudocode outlining how I think this would best work (only using the first of the requests above). At startup: New: Depth 0, PROPFIND for getctag (+ displayname?) => STORE calendar supports getctag Existing: REPORT for getetag => delete removed content from cache => GET requests for new/modified content Every (refresh frequency): IF ( calendar supports getctag ) New: Depth 0, PROPFIND for getctag IF ( getctag not supported OR getctag has changed ) Existing: REPORT for getetag => delete removed content from cache => GET requests for new/modified content Cheers, Andrew (karora).
Created attachment 122440 [details] [review] proposed eds patch for evolution-data-server; Thanks for the examples. This should work, but I found some issues with rscds, thus I wasn't able to fully check whether it works fine or not. I downloaded a new rscds from the sf.net in rpm form, davical-0.9.6.1-2.noarch.rpm libawl-php-0.33-2.noarch.rpm and it doesn't want to play with my, seems like a bug in rscds. I sent there: <propfind xmlns="DAV:" xmlns:CS="http://calendarserver.org/ns/"> <prop> <CS:getctag/> </prop> </propfind> with soup_message_headers_append (message->request_headers, "Depth", "0"); as a PROPFIND, and rscds responded with status 207, which is ok, but the body: <?xml version="1.0" encoding="utf-8" ?> <multistatus xmlns="DAV:"> <response> <href>/rscds/caldav.php/AJA/home/</href> <propstat> <prop> <HTTP://CALENDARSERVER.ORG/NS/:GETCTAG/> </prop> <status>HTTP/1.1 200 OK</status> </propstat> </response> </multistatus> seems to be broken. Just to tell, I had some rscds on the machine before, and simply rpm -Uvh those above and restarted daemons. Any idea? My other server doesn't support this, just returns the 404 status for the tag.
The fact that the getctag request has been upper-cased suggests that you didn't upgrade libawl when you upgraded DAViCal. Cheers, Andrew.
Hmm, strange: $ rpm -qa | grep awl libawl-php-0.33-2.noarch the one I've downloaded from sf.net.
thanks for help, it works fine with your test server.
Committed to trunk. Committed revision 9783.