CalDav calendar discovery
I found myself in the unfortunate situation to discover a CalDav uri using different providers. In this short post I guide you through a generic example flow which should work for most calendar providers.
The discovery process can be described as follows:
- Get user principal
- Find home set of user principal
- Get calendar from home set
- Fetch all events from calendar
The individual steps can be tested with curl commands. These curl commands depict the request flow and should work with any provider.
1. Get principal
First, read the principal:
cat <<EOF | curl -s -d @- -XPROPFIND \
-H "Content-Type: application/xml" \
-H "Depth: 0" -u '$USER:$PASSWORD' -L $CALDAV_HOST \
| xmllint --format -
<d:propfind xmlns:d="DAV:">
<d:prop>
<d:current-user-principal />
</d:prop>
</d:propfind>
EOF
The principal path ($PRINCIPAL
) is returned in the XML response tag
<DAV:current-user-principal>
.
2. Find home set
Get calendar home set for the principal:
cat <<EOF | curl -s -d @- -XPROPFIND \
-H "Content-Type: application/xml" \
-H "Depth: 0" -u '$USER:$PASSWORD' $CALDAV_HOST/$PRINCIPAL \
| xmllint --format -
<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
<d:prop>
<c:calendar-home-set />
</d:prop>
</d:propfind>
EOF
The users calendar home set $HOME_SET
is returned in the
<calendar-home-set>
XML tag.
3. Get calendar
This home set contains all calendars of the user. Finally, to list the calendars:
cat <<EOF | curl -s -d @- -XPROPFIND \
-H "Content-Type: application/xml" \
-H "Depth: 1" -u '$USER:$PASSWORD' $CALDAV_HOST/$HOME_SET \
| xmllint --format -
<d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/" xmlns:c="urn:ietf:params:xml:ns:caldav">
<d:prop>
<d:resourcetype />
<d:displayname />
<cs:getctag />
<c:supported-calendar-component-set />
</d:prop>
</d:propfind>
EOF
Choose a calendar CalDav URI to sync with a particular calendar. The <DAV:href>
path in the response is referenced with $CALENDAR
below for illustration purposes.
4. Fetch all events
This part is specific to your application. An example to fetch all events:
cat <<EOF | curl -s -d @- -XREPORT -H "Content-Type: application/xml" \
-H "Depth: 1" -u '$USER:$PASSWORD' $CALDAV_HOST/$CALENDAR \
| xmllint --format -
<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
<d:prop>
<d:getetag />
<c:calendar-data />
</d:prop>
<c:filter>
<c:comp-filter name="VCALENDAR">
<c:comp-filter name="VEVENT" />
</c:comp-filter>
</c:filter>
</c:calendar-query>
EOF
I hope this post helps you to discover user principals and calendar home sets for your specific calendar use case. If the post was too short and concise for you, read this 🤓. I can also suggest to read Building a CalDAV client on sabre.io to get started with your own client.