Google 数据 API 协议参考

本文档介绍了 Google 数据 API 使用的协议,包括有关查询内容、结果内容等的信息。

有关 Google 数据 API 的详细信息,请参阅 Google 数据开发者指南文档和协议指南

观众

本文档适用于任何想要了解 Google Data API 使用的 XML 格式和协议的详细信息。

如果您只是想编写使用 Google 数据客户端 API 的代码,则无需了解这些详细信息,而可以使用针对特定语言的客户端库

但如果您想了解该协议,请阅读本文档。例如,阅读本文档可以帮助您完成以下任何任务:

  • 评估 Google 数据架构
  • 在不使用所提供的 Google 数据客户端库的情况下使用该协议进行编码
  • 使用新语言编写客户端库

本文档假定您了解 XML、命名空间、联合 Feed 以及 HTTP 中的 GETPOSTPUTDELETE 请求的基础知识,以及 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 作者

/feed/author/name
/feed/author/email

(某些情况下是必需的;请参阅 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
条目摘要

/feed/entry/summary

(某些情况下是必需的;请参阅 Atom 规范。)

/rss/channel/item/atom:summary
条目内容

/feed/entry/content

(如果没有内容元素,则条目必须包含至少一个 <link rel="alternate"> 元素。)

/rss/channel/item/description
条目作者

/feed/entry/author/name
/feed/entry/author/email

(某些情况下是必需的;请参阅 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 全文查询字符串
  • 创建查询时,请以 q=term1 term2 term3 的形式列出以空格分隔的搜索字词。(与所有查询参数值一样,空格必须经过网址编码)。Google 数据服务会返回符合所有搜索字词的所有条目(例如在字词之间使用 AND)。与 Google 的网页搜索一样,Google 数据服务也会搜索完整字词(以及具有相同词干的相关字词),而不是子字符串。
  • 如需搜索完全匹配的词组,请用引号将词组括起来:q="exact phrase".
  • 如需排除与给定字词匹配的条目,请使用 q=-term 格式。
  • 搜索不区分大小写。
  • 示例:如需搜索包含完全匹配词组“Elizabeth Bennet”和字词“Darcy”但未包含字词“Austen”的所有条目,请使用以下查询:?q="Elizabeth Bennet" Darcy -Austen
/-/category 类别过滤器
  • 以类别 /categoryname/ 的形式列出每个类别,就像它是资源 URI 的一部分一样。这是常规 name=value 格式的例外情况。
  • 请在所有其他查询参数之前列出所有类别。
  • 在第一个类别前面加上 /-/,以表明这是类别。例如,如果 Jo 的 Feed 有关于弗里茨的条目类别,您就可以按如下格式请求这些条目:http://www.example.com/feeds/jo/-/Fritz。这样,实现便可以区分类别专用查询 URI 与资源 URI。
  • 您可以列出多个类别参数(用正斜线分隔),从而查询多个类别。Google 数据服务会返回符合所有类别的所有条目(例如在字词之间使用 AND)。例如:http://www.example.com/feeds/jo/-/Fritz/Laurie 会返回与这两个类别都匹配的条目。
  • 如需在字词之间添加 OR,请使用竖线字符 (|),进行网址编码,编码为 %7C。例如:http://www.example.com/feeds/jo/-/Fritz%7CLaurie 会返回与任一类别匹配的条目。
  • 如果某个条目属于 Atom 规范中定义的包含匹配字词或标签的类别,则该条目将与指定类别匹配。(大致而言,“字词”是指软件用于标识类别的内部字符串,而“标签”则是指在界面中向用户显示的可人工读取的字符串。)
  • 要排除与给定类别匹配的条目,请使用 /-categoryname/ 格式。
  • 如需查询具有架构的类别(例如 <category scheme="urn:google.com" term="public"/>),您必须将该架构放在大括号中并放在类别名称前面。例如:/{urn:google.com}public。如果架构包含斜杠字符 (/),则应将其网址编码为 %2F。如需匹配没有架构的类别,请使用一对空的大括号。如果未指定大括号,则任何架构中的类别都将匹配。
  • 上述功能可以结合使用。例如:/A%7C-{urn:google.com}B/-C 表示 (A OR (NOT B)) AND (NOT C)
category 类别过滤器
  • 执行类别过滤器的另一种方法。这两种方法是等效的。
  • 如需在字词之间添加 OR,请使用竖线字符 (|),网址编码为 %7C。例如:http://www.example.com/feeds?category=Fritz%7CLaurie 会返回与任一类别匹配的条目。
  • 如需在字词之间添加 AND,请使用英文逗号 (,)。例如:http://www.example.com/feeds?category=Fritz,Laurie 会返回与这两个类别都匹配的条目。
author 条目作者
  • 该服务会返回作者姓名和/或电子邮件地址与查询字符串匹配的条目。
alt 替代表示法类型
  • 如果您未指定 alt 参数,该服务会返回 Atom Feed。这相当于 alt=atom
  • alt=rss 会返回 RSS 2.0 结果 Feed。
  • alt=json 会返回 Feed 的 JSON 表示法。了解详情
  • alt=json-in-script 请求将 JSON 封装在脚本标记中的响应。了解详情
updated-minupdated-max 条目更新日期的边界
  • 使用 RFC 3339 时间戳格式。例如:2005-08-09T10:57:00-08:00
  • 下限含边界值,而上限不含边界值。
published-minpublished-max 条目发布日期的边界
  • 使用 RFC 3339 时间戳格式。例如:2005-08-09T10:57:00-08:00
  • 下限含边界值,而上限不含边界值。
start-index 要检索的第一个结果的索引(从 1 开始)
  • 请注意,这并非通用光标机制。如果您先使用 ?start-index=1&max-results=10 发送查询,然后使用 ?start-index=11&max-results=10 发送另一个查询,则该服务无法保证结果等同于 ?start-index=1&max-results=20,因为两次查询之间可能会发生插入和删除操作。
max-results 要检索的结果数上限 对于任何具有默认 max-results 值(限制默认 Feed 大小)的服务,如果您希望接收整个 Feed,则可以指定非常大的数字。
条目 ID 要检索的特定条目的 ID
  • 如果您指定了条目 ID,就不能再指定任何其他参数。
  • 条目 ID 的格式由 Google 数据服务确定。
  • 与大多数其他查询参数不同,条目 ID 是作为 URI 的一部分指定的,而不是作为 name=value 对指定的。
  • 示例:http://www.example.com/feeds/jo/entry1

关于类别查询

我们决定为类别查询指定一个不寻常的格式。而不是这样的查询:

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 数据的难度。

身份验证

当客户端尝试访问服务时,可能需要向服务提供用户的凭据,以证明用户有权执行相关操作。

客户端应该使用何种身份验证方法取决于客户端类型:

在 EGL 系统中,桌面客户端要求用户提供其凭据,然后将这些凭据发送到 Google 身份验证系统。

如果身份验证成功,则身份验证系统会返回一个令牌,该客户端会在随后发送 Google 数据请求时使用该令牌(在 HTTP 授权标头中)。

如果身份验证失败,服务器将返回 403“禁止访问”状态代码,以及包含适用于身份验证的质询的 WWW-Authenticate 标头。

AuthSub 系统的工作方式类似,只不过它不是要求用户提供凭据,而是将用户连接到请求凭据的 Google 服务。然后,该服务会返回 Web 应用可以使用的令牌;这种方法的优势在于,Google(而不是 Web 前端)可以安全地处理和存储用户的凭据。

要详细了解这些身份验证系统,请参阅 Google 数据身份验证概览Google 帐号身份验证文档。

会话状态

许多业务逻辑实现都需要会话粘性,即跟踪用户会话的状态。

Google 通过以下两种方式跟踪会话状态:使用 Cookie,使用可作为查询参数发送的令牌。这两种方法可实现相同的效果。我们建议客户支持下列任一会话状态跟踪方法(两种方法足以满足需求)。如果某个客户端不支持其中任一方法,则该客户端仍可使用 Google 数据服务,但与支持这些方法的客户端相比,其性能可能会受到影响。具体而言,如果客户端不支持这些方法,那么每个请求都会产生重定向,因此每个请求(及任何关联数据)都会发送到服务器两次,这会影响客户端和服务器的性能。

Google 客户端库会处理会话状态,因此如果您使用我们的库,则无需执行任何操作即可获得会话状态支持。

其他资源

以下第三方文档可能对您有所帮助:

返回页首