本文档介绍了 Google 数据 API 使用的协议,包括有关查询内容、结果内容等的信息。
有关 Google 数据 API 的详细信息,请参阅 Google 数据开发者指南文档和协议指南。
观众
本文档适用于任何想要了解 Google Data API 使用的 XML 格式和协议的详细信息。
如果您只是想编写使用 Google 数据客户端 API 的代码,则无需了解这些详细信息,而可以使用针对特定语言的客户端库。
但如果您想了解该协议,请阅读本文档。例如,阅读本文档可以帮助您完成以下任何任务:
- 评估 Google 数据架构
- 在不使用所提供的 Google 数据客户端库的情况下使用该协议进行编码
- 使用新语言编写客户端库
本文档假定您了解 XML、命名空间、联合 Feed 以及 HTTP 中的 GET
、POST
、PUT
和 DELETE
请求的基础知识,以及 HTTP 的“资源”概念。如需详细了解这些内容,请参阅本文档中的其他资源部分。
本文档不依赖任何特定的编程语言;您可以使用任何允许您发出 HTTP 请求并解析基于 XML 的响应的编程语言来发送和接收 Google 数据消息。
协议详情
本部分介绍了 Google 数据文档格式和查询语法。
文档格式
Google 数据、Atom 和 RSS 2.0 均共用相同的基本数据模型:即存储一些全局数据和任意数量的条目的容器。对于每种协议,格式由基本架构定义,但可以使用外部命名空间进行扩展。
Google Data API 可以使用 Atom 整合格式(用于读取和写入)或 RSS 格式(仅用于读取)。
Atom 是 Google 数据的默认格式。如需请求 RSS 格式的响应,请使用 /alt=rss/
参数;如需了解详情,请参阅查询请求。
当您请求 RSS 格式的数据时,Google 数据会以 RSS 格式提供 Feed(或其他资源表示形式)。如果给定的 Google 数据属性没有对应的 RSS 属性,Google 数据会使用 Atom 属性,并使用适当的命名空间来标记它,以表明它是 RSS 的扩展。
注意:大多数采用 Atom 格式的 Google 数据 Feed 都会通过在 Feed 元素上指定 xmlns
属性来将 Atom 命名空间用作默认命名空间;请参阅示例部分,了解具体操作方法。因此,本文档中的示例没有为 Atom 格式的 Feed 中的元素明确指定 atom:
。
下表显示了架构元素的 Atom 和 RSS 表示法。这些表中未提及的所有数据将被视为普通 XML,并在两种表示中表现相同。除非另有说明,否则指定列中的 XML 元素位于与该列对应的命名空间中。此摘要使用标准的 XPath 表示法:特别是,斜杠表示元素层次结构,@ 符号表示元素的属性。
在以下每个表格中,突出显示的项为必填项。
下表显示了 Google 数据 Feed 的元素:
Feed 架构项 | Atom 表示法 | RSS 表示法 |
---|---|---|
Feed 标题 | /feed/title |
/rss/channel/title |
Feed ID | /feed/id |
/rss/channel/atom:id |
Feed HTML 链接 | /feed/link[@rel="alternate"] \[@type="text/html"]/@href |
/rss/channel/link |
Feed 说明 | /feed/subtitle |
/rss/channel/description |
Feed 语言 | /feed/@xml:lang |
/rss/channel/language |
Feed 版权 | /feed/rights |
/rss/channel/copyright |
Feed 作者 |
(某些情况下是必需的;请参阅 Atom 规范。) |
/rss/channel/managingEditor |
Feed 上次更新日期 | /feed/updated (RFC 3339 格式) |
/rss/channel/lastBuildDate (RFC 822 格式) |
Feed 类别 | /feed/category/@term |
/rss/channel/category |
Feed 类别架构 | /feed/category/@scheme |
/rss/channel/category/@domain |
Feed 生成器 | /feed/generator /feed/generator/@uri |
/rss/channel/generator |
Feed 图标 | /feed/icon |
/rss/channel/image/url (除非还有徽标,在此情况下 Feed 中不包含该图标) |
Feed 徽标 | /feed/logo |
/rss/channel/image/url |
下表显示了 Google 数据搜索结果 Feed 的元素。请注意,Google 数据在其搜索结果 Feed 中公开了一些 OpenSearch 1.1 响应元素。
搜索结果 Feed 架构项 | Atom 表示法 | RSS/OpenSearch 表示法 |
---|---|---|
搜索结果数量 | /feed/openSearch:totalResults |
/rss/channel/openSearch:totalResults |
搜索结果起始索引 | /feed/openSearch:startIndex |
/rss/channel/openSearch:startIndex |
每页的搜索结果数 | /feed/openSearch:itemsPerPage |
/rss/channel/openSearch:itemsPerPage |
下表显示了 Google 数据条目的各元素:
条目架构项 | Atom 表示法 | RSS 表示法 |
---|---|---|
条目 ID | /feed/entry/id |
/rss/channel/item/guid |
条目版本 ID | (可选)嵌入到 EditURI 中(请参阅本文档的乐观并发部分)。 | — |
条目标题 | /feed/entry/title |
/rss/channel/item/title |
条目链接 | /feed/entry/link |
/rss/channel/item/link /rss/channel/item/enclosure /rss/channel/item/comments |
条目摘要 |
(某些情况下是必需的;请参阅 Atom 规范。) |
/rss/channel/item/atom:summary |
条目内容 |
(如果没有内容元素,则条目必须包含至少一个 |
/rss/channel/item/description |
条目作者 |
(某些情况下是必需的;请参阅 Atom 规范。) |
/rss/channel/item/author |
条目类别 | /feed/entry/category/@term |
/rss/channel/item/category |
条目类别方案 | /feed/entry/category/@scheme |
/rss/channel/item/category/@domain |
参评发布日期 | /feed/entry/published (RFC 3339) |
/rss/channel/item/pubDate (RFC 822) |
条目更新日期 | /feed/entry/updated (RFC 3339) |
/rss/channel/item/atom:updated (RFC 3339) |
查询
本部分介绍如何使用查询系统。
查询模型设计原则
查询模型非常简单。基本原则如下:
- 查询以 HTTP URI 的形式表示,而不是以 HTTP 标头或载荷的形式表示。此方法的一个好处是,您可以链接到查询。
- 谓词的范围限定为单个项。因此,无法发送关联查询,例如“查找来自今天至少向我发送 10 封电子邮件的用户的所有电子邮件”。
- 查询可谓词集的属性非常有限;大多数查询只是全文搜索查询。
- 结果排序取决于实现。
- 该协议本身就可扩展。如果您希望在服务中公开其他谓词或排序方式,可通过引入新参数轻松完成。
查询请求
客户端通过发出 HTTP GET
请求来查询 Google Data 服务。查询 URI 由资源的 URI(在 Atom 中称为 FeedURI)后跟查询参数组成。大多数查询参数都表示为传统的 ?name=value[&...]
网址参数。类别参数的处理方式不同,请参阅下文。
例如,如果 FeedURI 为 http://www.example.com/feeds/jo
,那么您可以使用以下 URI 发送查询:
http://www.example.com/feeds/jo?q=Darcy&updated-min=2005-04-19T15:30:00Z
Google 数据服务支持 HTTP 条件 GET
。这些 API 会根据返回的 Feed 或条目中的 <atom:updated>
元素的值设置 Last-Modified 响应标头。客户端可以将此值作为 If-Modified-Since 请求标头的值发回,以避免在内容未发生更改时再次检索该内容。如果内容自 If-Modified-Since 以来没有变化,那么 Google 数据服务会返回 304(未修改)HTTP 响应。
Google 数据服务必须支持类别查询和 alt
查询;对其他参数的支持是可选的。传递给定服务无法理解的标准参数会导致 403 Forbidden
响应。传递不受支持的非标准参数会导致 400 Bad Request
响应。如需了解其他状态代码,请参阅本文档中的 HTTP 状态代码部分。
下表汇总了标准查询参数。所有参数值都需要经过网址编码。
参数 | 含义 | 备注 |
---|---|---|
q |
全文查询字符串 |
|
/-/category |
类别过滤器 |
|
category |
类别过滤器 |
|
author |
条目作者 |
|
alt |
替代表示法类型 | |
updated-min ,updated-max |
条目更新日期的边界 |
|
published-min ,published-max |
条目发布日期的边界 |
|
start-index |
要检索的第一个结果的索引(从 1 开始) |
|
max-results |
要检索的结果数上限 | 对于任何具有默认 max-results 值(限制默认 Feed 大小)的服务,如果您希望接收整个 Feed,则可以指定非常大的数字。 |
条目 ID | 要检索的特定条目的 ID |
|
关于类别查询
我们决定为类别查询指定一个不寻常的格式。而不是这样的查询:
http://example.com/jo?category=Fritz&category=2006
我们使用:
http://example.com/jo/-/Fritz/2006
此方法可在不使用查询参数的情况下识别资源,并能生成更简洁的 URI。我们之所以选择类别方法,是因为我们认为类别查询是最常见的查询。
这种方法的缺点是,您需要在类别查询中使用 /-/
,以便 Google 数据服务能够将类别查询与其他资源 URI(例如 http://example.com/jo/MyPost/comments
)区分开。
查询响应
查询将返回 Atom Feed、Atom 条目或 RSS Feed,具体取决于请求参数。
查询结果直接在 <feed>
元素或 <channel>
元素下包含以下 OpenSearch 元素(具体取决于结果是 Atom 还是 RSS):
openSearch:totalResults
- 查询的搜索结果总数(不一定全部存在于结果 Feed 中)。
openSearch:startIndex
- 第一个结果的索引(从 1 开始)。
openSearch:itemsPerPage
- 每页最多可显示的内容项数。这样,客户端就可以生成指向任意一组后续网页的直接链接。不过,如需了解使用此数字的可能的误区,请参阅查询请求部分的表
start-index
注意事项。
Atom 响应 Feed 和条目还可能包含以下任一 Atom 和 Google 数据元素(以及 Atom 规范中列出的其他元素):
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="..."/>
- 指定用于检索整个 Atom Feed 的 URI。
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="..."/>
- 指定 Atom Feed 的 PostURI(可在其中发布新条目)。
<link rel="self" type="..." href="..."/>
- 包含此资源的 URI。
type
属性的值取决于请求的格式。如果在此期间没有任何数据更改,则向此 URI 发送另一个 GET 会返回相同的响应。 <link rel="previous" type="application/atom+xml" href="..."/>
- 指定此查询集的上一个分块的 URI(如果分块的话)。
<link rel="next" type="application/atom+xml" href="..."/>
- 指定此查询集的下一个分块(如果分块了)的 URI。
<link rel="edit" type="application/atom+xml" href="..."/>
- 指定 Atom 条目的 EditURI(即发送已更新条目的位置)。
以下是响应搜索查询的示例响应正文:
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"> <id>http://www.example.com/feed/1234.1/posts/full</id> <updated>2005-09-16T00:42:06Z</updated> <title type="text">Books and Romance with Jo and Liz</title> <link rel="alternate" type="text/html" href="http://www.example.net/"/> <link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <link rel="self" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> <generator version="1.0" uri="http://www.example.com">Example Generator Engine</generator> <openSearch:totalResults>2</openSearch:totalResults> <openSearch:startIndex>0</openSearch:startIndex> <entry> <id>http://www.example.com/feed/1234.1/posts/full/4521614025009481151</id> <published>2005-01-09T08:00:00Z</published> <updated>2005-01-09T08:00:00Z</updated> <category scheme="http://www.example.com/type" term="blog.post"/> <title type="text">This is the title of entry 1009</title> <content type="xhtml"> <div xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1009</div> </content> <link rel="alternate" type="text/html" href="http://www.example.com/posturl"/> <link rel="edit" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full/4521614025009481151"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> </entry> <entry> <id>http://www.example.com/feed/1234.1/posts/full/3067545004648931569</id> <published>2005-01-07T08:00:00Z</published> <updated>2005-01-07T08:02:00Z</updated> <category scheme="http://www.example.com/type" term="blog.post"/> <title type="text">This is the title of entry 1007</title> <content type="xhtml"> <div xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1007</div> </content> <link rel="alternate" type="text/html" href="http://www.example.com/posturl"/> <link rel="edit" type="application/atom+xml" href="http://www.example.com/feed/1234.1/posts/full/3067545004648931569"/> <author> <name>Elizabeth Bennet</name> <email>liz@gmail.com</email> </author> </entry> </feed>
如果请求的 Feed 采用 Atom 格式,并且如果未指定查询参数,并且结果不包含所有条目,则会将以下元素插入顶级 Feed:<link rel="next" type="application/atom+xml" href="..."/>
。它指向包含下一组条目的 Feed。后续集包含相应的 <link rel="previous" type="application/atom+xml" href="..."/>
元素。通过遵循所有下一个链接,客户端可以从 Feed 中检索所有条目。
HTTP 状态代码
下表介绍了各种 HTTP 状态代码在 Google Data 服务环境中的含义。
编码 | 说明 |
---|---|
200 OK | 无错误。 |
201 已创建 | 已成功创建资源。 |
304 未修改 | 在该请求的 If-Modified-Since 标头中指定的时间之后,该资源并未发生更改。 |
400 请求无效 | 请求 URI 或标头无效,或不受支持的非标准参数。 |
401 未授权 | 需要授权。 |
403 已禁止 | 标准参数不受支持,或者身份验证或授权失败。 |
404 无法找到 | 找不到资源(例如 Feed 或条目)。 |
409 冲突 | 指定的版本号与资源的最新版本号不匹配。 |
500 内部服务器错误 | 内部错误。这是用于所有无法识别的错误的默认代码。 |
乐观并发(版本控制)
有时,务必要确保多个客户端不会无意中覆盖彼此的更改。最简单的方法是确保客户端正在修改的条目版本与客户端基于其修改的版本相同。如果第二个客户端先于第一个客户端进行更新,则第一个客户端的更新会被拒绝,因为第一个客户端已不再基于最新版本的修改。
在支持版本控制的 Google 数据 Feed 中,我们通过在每个条目的 EditURI 中附加版本 ID 来实现这些语义。请注意,只有 EditURI 会受到影响,条目 ID 不会受到影响。在此方案中,每次更新都会更改相应条目的 EditURI,从而确保基于原始版本的后续更新失败。当然,对于此功能,删除操作等同于更新;如果您发送具有旧版本号的删除操作,则删除操作会失败。
并非所有 Google 数据 Feed 都支持乐观并发。在支持它的 Feed 中,如果服务器检测到 PUT 或 DELETE 版本冲突,则会以 409 Conflict
响应。响应的正文包含条目的当前状态(Atom 条目文档)。建议客户使用 409 响应中的 EditURI 解决冲突,然后重新提交请求。
动机和设计说明
这种乐观并发控制方法让我们可以实现所需的语义,而无需为版本 ID 添加新标记,从而使 Google 数据的响应与非 Google 数据 Atom 端点兼容。
我们可以选择查看每个条目的更新时间戳 (/atom:entry/atom:updated
),而不是指定版本 ID。但是,使用更新时间戳存在两个问题:
- 此操作仅适用于更新,而不适用于删除。
- 它会强制应用使用日期/时间值作为版本 ID,这会加大在许多现有数据存储区基础上改造 Google 数据的难度。
身份验证
当客户端尝试访问服务时,可能需要向服务提供用户的凭据,以证明用户有权执行相关操作。
客户端应该使用何种身份验证方法取决于客户端类型:
- 桌面应用应使用 Google 专用的身份验证系统,即针对已安装应用的帐号身份验证。(基于网络的客户端不应使用此系统。)
- 基于网络的客户端(例如 Google 数据服务的第三方前端)应使用特定于 Google 的身份验证系统,名为适用于 Web 应用的帐号身份验证代理(也称为“AuthSub”)。
在 EGL 系统中,桌面客户端要求用户提供其凭据,然后将这些凭据发送到 Google 身份验证系统。
如果身份验证成功,则身份验证系统会返回一个令牌,该客户端会在随后发送 Google 数据请求时使用该令牌(在 HTTP 授权标头中)。
如果身份验证失败,服务器将返回 403“禁止访问”状态代码,以及包含适用于身份验证的质询的 WWW-Authenticate 标头。
AuthSub 系统的工作方式类似,只不过它不是要求用户提供凭据,而是将用户连接到请求凭据的 Google 服务。然后,该服务会返回 Web 应用可以使用的令牌;这种方法的优势在于,Google(而不是 Web 前端)可以安全地处理和存储用户的凭据。
要详细了解这些身份验证系统,请参阅 Google 数据身份验证概览或 Google 帐号身份验证文档。
会话状态
许多业务逻辑实现都需要会话粘性,即跟踪用户会话的状态。
Google 通过以下两种方式跟踪会话状态:使用 Cookie,使用可作为查询参数发送的令牌。这两种方法可实现相同的效果。我们建议客户支持下列任一会话状态跟踪方法(两种方法足以满足需求)。如果某个客户端不支持其中任一方法,则该客户端仍可使用 Google 数据服务,但与支持这些方法的客户端相比,其性能可能会受到影响。具体而言,如果客户端不支持这些方法,那么每个请求都会产生重定向,因此每个请求(及任何关联数据)都会发送到服务器两次,这会影响客户端和服务器的性能。
Google 客户端库会处理会话状态,因此如果您使用我们的库,则无需执行任何操作即可获得会话状态支持。
其他资源
以下第三方文档可能对您有所帮助:
- Atom 和 RSS 的比较
- IBM 的 Atom 概览
- RSS 的 Dublin Core 扩展程序
- HTTP 1.1 方法定义;针对
GET
、POST
、PUT
和DELETE
的规范 - HTTP 1.1 状态代码定义
- 如何创建 REST 协议
- 以 REST 方式构建 Web 服务
- XML 技术简介
- XML 命名空间示例