Skip to content
RuaRuan
返回

详解 CalDAV

CalDAV(Calendaring Extensions to WebDAV)是 IETF 在 RFC 4791​ 中定义的开放标准,本质是在 WebDAV/HTTP 之上给“日历数据”加的一套扩展语义。它让任意兼容客户端(Apple 日历、Thunderbird、DAVx5、GNOME Calendar 等)能以统一方式读写远端服务器上的日程,实现跨厂商、跨设备的双向同步与共享。

一、它处在协议栈的哪一层

简单说:WebDAV 管“怎么像操作文件一样操作资源”,CalDAV 管“这些资源被解释为日历是什么意思”,iCalendar 管“事件本身长啥样”。

二、数据模型:principal → home → calendar collection → object

https://cal.example.com/
└── principals/users/alice/        current-user-principal
    └── calendars/alice/           CALDAV:calendar-home-set
        ├── work/                  calendar collection (resourcetype=calendar)
        │   ├── event-1.ics        calendar object resource (VEVENT)
        │   └── event-2.ics
        └── personal/              another calendar collection

三、核心 HTTP 方法与典型交互

CalDAV 没有发明新传输,只是复用/扩展 HTTP 动词:

方法作用典型场景
OPTIONS探能力客户端首连看服务器是否声明 CalDAV 支持
PROPFIND读属性/发现结构查 current-user-principal、calendar-home-set、列出日历集合、getetag/displayname
PROPPATCH改集合属性改日历名、改颜色、改描述
MKCALENDAR建日历集合新建“工作日历”(Google 不支持,Nextcloud/Radicale 支持)
GET取单个 .ics 原文拉某个事件完整 iCalendar
PUT新建/覆盖事件建事件带 If-None-Match: *;改事件带 If-Match: <旧ETag> 做并发保护
DELETE删事件/集合删单个 VEVENT 资源
REPORTCalDAV 灵魂calendar-query(按时间窗/组件类型过滤)、calendar-multiget(按 href 批量取)、sync-collection(增量)

响应大量使用 207 Multi-Status​ + DAV:multistatus XML 包装多个资源的属性/数据/错误。

一个最小建事件示例:

PUT /calendars/alice/work/meeting-123.ics HTTP/1.1
Host: cal.example.com
Content-Type: text/calendar
If-None-Match: *

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example//CalDAV//EN
BEGIN:VEVENT
UID:meeting-123@example.com
DTSTAMP:20260831T120000Z
DTSTART:20260901T010000Z
DTEND:20260901T020000Z
SUMMARY:Sync design review
END:VEVENT
END:VCALENDAR

成功回 201 Created 带新 ETag。

四、同步机制(重点)

CalDAV 同步不是“每次全量下载”,而是三层游标:

  1. ETag(单事件级)
    每个 .ics 资源有 ETag。客户端缓存 href + ETag,下次 PROPFIND Depth:1 只拿 (href, getetag),比对就能知道哪个事件被改/删。
  2. CTag / getctag(日历集合级)
    集合整体变更计数。没变就跳过,变了再进集合扫 ETag。
  3. sync-token(RFC 6578 增量)
    客户端存上次 sync-token,发 REPORT DAV:sync-collection 带旧 token,服务器只回“自那以后新增/修改/删除的 href 列表”,带宽最小。这是现代客户端(iOS、macOS、DAVx5)的主流模式。

时间窗查询也很关键:客户端打开“本月视图”时发

REPORT /calendars/alice/work/
<calendar-query><prop><getetag/></prop>
  <filter><comp-filter name="VCALENDAR"><comp-filter name="VEVENT">
    <time-range start="20260901T000000Z" end="20261001T000000Z"/>
  </comp-filter></comp-filter></filter>
</calendar-query>

服务器只回落在窗口内的事件,避免拉全年历史。

冲突处理靠 If-Match + ETag:两人同时改同一事件,后写者若带旧 ETag 会被 412 Precondition Failed 拒绝,客户端再决定覆盖还是合并。

五、发现(Service Discovery)

只填一个服务器域名就能用,靠两套机制:

六、安全与认证

七、CalDAV vs CardDAV vs 私有协议

八、常见服务端 / 客户端

九、实现一个最小 CalDAV 服务器要答哪些请求

按 RFC 4791 的“MUST”:

  1. OPTIONS 在日历资源上返回 Allow 含 PROPFIND REPORT PUT DELETE 等,且 DAV 头含 1 和 calendar-access
  2. PROPFIND 能答 resourcetype、displayname、current-user-principal、calendar-home-set、supported-calendar-component-set、getetag
  3. PUT 校验 Content-Type text/calendar、解析 iCalendar、按 UID 落库、发 ETag
  4. REPORT 支持 calendar-query(至少按时间窗过滤 VEVENT)、calendar-multiget
  5. DELETE 删资源;可选 MKCALENDAR、sync-collection、ACL
  6. 错误用 207 内嵌 DAV:error 或 403/409 带 CalDAV 预条件 XML 元素


下一篇
CalDAV同步过程中如何处理时区差异问题?