Google Calendar CalDAV时间范围筛选失效问题排查
CalDAV时间范围筛选问题:返回范围外事件或Bad Request错误
我最近在尝试通过CalDAV请求获取指定时间范围内的日历事件时遇到了两个棘手的问题,折腾了好久都没搞定,想请教下大家:
首先是最初的请求,我直接用VEVENT的comp-filter搭配time-range筛选,但服务器居然返回了时间范围外的事件,比如明明查的是2020年9月19-20日的事件,结果收到了2020年5月22日的条目。请求体如下:
<?xml version="1.0" encoding="UTF-8"?> <C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav"> <D:prop xmlns:D="DAV:"> <C:calendar-data /> </D:prop> <C:filter> <C:comp-filter name="VEVENT"> <C:time-range end="20200920T134847" start="20200919T134847" /> </C:comp-filter> </C:filter> </C:calendar-query>
后来我查了相关示例,发现需要把VEVENT的筛选嵌套在VCALENDAR的comp-filter里,于是修改了请求体:
<?xml version="1.0" encoding="UTF-8"?> <C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav"> <D:prop xmlns:D="DAV:"> <C:calendar-data /> </D:prop> <C:filter> <C:comp-filter name="VCALENDAR"> <C:comp-filter name="VEVENT"> <C:time-range end="20200920T135938" start="20200919T135938" /> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>
结果Google直接返回了Bad Request错误:
<?xml version="1.0" encoding="UTF-8"?> <errors xmlns="http://schemas.google.com/g/2005"> <error> <domain>GData</domain> <code>badRequest</code> <internalReason>Bad Request</internalReason> </error> </errors>
之后我试了icalendar.org上的可行示例,却没法用caldav4j复现对应的请求体;甚至直接复制caldav4j的官方示例请求:
<?xml version="1.0" encoding="UTF-8"?> <C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav"> <D:prop xmlns:D="DAV:"> <D:getetag /> <C:calendar-data> <C:comp name="VCALENDAR"> <C:comp name="VEVENT"> <C:prop name="SUMMARY" /> <C:prop name="UID" /> <C:prop name="DTSTART" /> <C:prop name="DTEND" /> <C:prop name="DURATION" /> <C:prop name="RRULE" /> <C:prop name="RDATE" /> <C:prop name="EXRULE" /> <C:prop name="EXDATE" /> <C:prop name="RECURRENCE-ID" /> </C:comp> <C:comp name="VTIMEZONE" /> <C:prop name="VERSION" /> </C:comp> </C:calendar-data> </D:prop> <C:filter> <C:comp-filter name="VCALENDAR"> <C:comp-filter name="VEVENT"> <C:time-range end="20200920T161921" start="20200919T161921" /> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>
还是得到同样的Bad Request错误,实在找不到问题出在哪了。
问题分析与解决方案(针对上述场景)
1. 第一次请求返回范围外事件的原因
CalDAV规范要求筛选必须从顶层的VCALENDAR组件开始,再向下嵌套VEVENT的筛选规则。直接对VEVENT做筛选会让服务器无法正确解析层级,导致忽略时间范围条件,返回所有VEVENT类型的事件。
2. Google返回Bad Request的核心原因
Google的CalDAV API对请求格式有几个严格要求,踩中任何一个都会触发错误:
- 时间格式必须带UTC标识:Google要求
time-range的时间必须是UTC格式(末尾加Z),比如20200920T135938Z,否则会解析失败。 - 命名空间的统一声明:建议把DAV和CalDAV的命名空间统一在根元素声明,避免子元素的命名空间冲突。
- 请求方法与头信息:必须使用
REPORT方法发送请求,同时设置Content-Type: application/xml; charset=utf-8请求头。
修正后的可行请求示例
<?xml version="1.0" encoding="UTF-8"?> <C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:D="DAV:"> <D:prop> <C:calendar-data /> <D:getetag /> </D:prop> <C:filter> <C:comp-filter name="VCALENDAR"> <C:comp-filter name="VEVENT"> <C:time-range start="20200919T135938Z" end="20200920T135938Z" /> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>
额外注意事项
如果需要获取重复事件在指定时间范围内的实例,还需要在calendar-data中添加expand元素,强制服务器展开重复事件:
<C:calendar-data> <C:expand start="20200919T135938Z" end="20200920T135938Z" /> </C:calendar-data>
内容的提问来源于stack exchange,提问作者Stef
相关产品推荐
相关产品推荐

