手把手教你如何实现 CalDav 协议系列之流程介绍篇

2,310 阅读3分钟

手把手教你如何实现 CalDav 协议系列之流程介绍篇

1、初衷

作者本人当时做 CalDav日程托管第三方的需求时,查阅资料时发现普遍的现象:国内介绍该协议的资料少;国外大多是英文文档耗时久、收获少;Github 上有相关各类语言的实现但大多数都是不全的需要自己进行内部开发,从而导致需求实现成本提高;故根据我做需求的思路写下该系列文档,以便让大家对该协议有些了解。(好,废话不多说,直接进入正题)

2、CalDav 协议简介

维基百科: WebDAV 的日历扩展或CalDAV是一种Internet 标准,允许客户端访问和管理日历数据以及安排与同一服务器或远程服务器上的用户的会议的能力。它允许不同位置的多个用户共享、搜索和同步日历数据。它扩展了WebDAV(基于HTTP的数据操作协议)规范,并使用iCalendar格式作为日历数据。访问协议由RFC 4791定义。 用于调度的 CalDAV 扩展被标准化为RFC 6638。该协议被许多重要的开源应用程序使用。

3、CalDAV 协议 重点关注的 HTTP 方法

  • OPTIONS:用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。
  • PRORFIND :获取请求 URI 标识的资源以及其成员资源的定义的属性。
  • REPORT :报告,用于获取一个或多个资源的信息
  • PROPPATCH :设置和/或删除由请求URI标识的资源上定义的属性
  • PUT :资源的创建/修改
  • MKCALENDAR :创建新的日历集合资源
  • DELETE :删除由请求URI标识的资源

4、C To S 交互流程

本流程是基于抓包的数据和自身对协议的理解分析出来的,如有问题请大家指出,以便及时修正。

思考 : 对于数据同步,第三方如何同步数据呢?以及如何确定数据变更呢? 方案:CalDav 协议就给出了该问题在业界内普遍认可的解决方案。对于同步,CalDav 支持同步和增量(synctoken)两种方式拉取;对于数据变更,CalDav 采用 etag 的方式来标志资源的唯一性(类似于摘要)。对于同步,CalDav 协议做了优化引入 Ctag 标签(类似于 etag)确定该资源目录下是否发生变更,变更就进行数据拉取和更新操作。

全量拉取

sequenceDiagram
autonumber
alt 全量拉取
client->>server: propfind: 获取日历下所有日程的 href 和 etag
server-->>client:  返回 href 和 etag
end

日程数据增量拉取流程图(支持 Ctag 和 Synctoken 的方法)

sequenceDiagram
autonumber
alt 首次拉取
client->>server: propfind: 获取每个日历的ctag 和 sync-token
server-->>client: ctag、sync-token 返回
client->>server: propfind 和 report 协议 配合获取日历下所有数据
server-->>client: 结果返回
end
alt 增量获取
client->>server:   propfind: 获取每个日历的ctag 和 sync-token
server-->>client: ctag、sync-token 返回
client->>client: ctag比对: 判断日历数据是否变化
client->>server: 变化:report协议 依据 synctoken 拉取数据
server-->>client: 返回结果
end

总体交互 C To S流程图

sequenceDiagram
autonumber
alt  首次
client->>server:  PROPFIND /.well-known/caldav HTTP/1.1 (服务自动发现)
server-->>client: redirect  url=/caldav/( 服务端自动重定向)
client->>server: PROPFIND /calendar/ HTTP/1.1 (获取当前用户目录地址)
server-->>client:  /calendar/12345
client->>server:   OPTIONS /calendar/12345/ HTTP/1.1 (确定支持的协议和功能)
server-->>client:   header : DAV、Allow
end
alt 日历数据获取阶段
client->>server:   PROPFIND /calendar/12345/ HTTP/1.1 (确定日历目录 url)
server-->>client: calendar-home-set :/calendar/
client->>server: PROPFIND /calendar/ HTTP/1.1 (拉取日历数据
server-->>client:  href、 displayname、ctag、synctoken、
end

alt 日程数据全量获取
client->>server:  PROPFIND /calendar/F23eQBcuQBBmQBqUwBjBBAH/ HTTP/1.1 (全量拉取日程数据)
server-->>client:  href、etag
client->>server: REPORT /calendar/F23eQBcuQBBmQBqUwBjBBAH/ HTTP/1.1 (mutil-get 分批拉取日程详情数据)
server-->>client:  href、etag、calendar-data
end

alt 日程数据增量获取
client->>server: PROPFIND /calendar/F23eQBcuQBBmQBqUwBjBBAH/ HTTP/1.1(获取 syntoken)
server-->>client:  syntoken
client->>server: REPORT /calendar/F23eQBcuQBBmQBqUwBjBBAH/ HTTP/1.1 (增量拉取)
server-->>client:  href、etag
client->>server: REPORT /calendar/F23eQBcuQBBmQBqUwBjBBAH/ HTTP/1.1 (mutil-get 分批拉取日程详情数据)
server-->>client:  href、etag、calendar-data
end

注:流程图和抓包的数据结合观看是最好的

5、链接