白宫Web API的指南和示例


本文档提供了白宫Web API的指南和示例,鼓励跨前后端的一致性,可维护性和最佳实践。白宫API旨在平衡真正的RESTful API接口和积极的开发者体验(DX)。该文件大量借鉴:

这些指南旨在支持真正的RESTful API。以下是一些例外情况:

  • 将API的版本号放在URL中(参见下面的示例)。不接受任何未指定版本号的请求。
  • 允许用户像这样请求JSON或XML等格式:
    • http://example.gov/api/v1/magazines.json
    • http://example.gov/api/v1/magazines.xml

RESTful URL的一般准则

  • URL标识资源。
  • 网址应包含名词,而不是动词。
  • 使用复数名词只是为了一致性(没有单数名词)。
  • 使用HTTP谓词(GET,POST,PUT,DELETE)对集合和元素进行操作。
  • 不应该比资源/标识符/资源更深嵌套了。
  • 将版本号放在URL的尾部,例如http://example.com/v1/path/to/resource。
  • URL 和Header的选择:
    • 如果更改了你编写的逻辑以处理响应,请将其放入URL中。
    • 如果它没有更改每个响应的逻辑,例如OAuth信息,请将其放在标题Header中。
  • 在逗号分隔列表中指定可选字段。
  • 格式应采用api/v2/resource/{id} .json的形式

好的URL示例

  • 杂志资源列表:
    • GET http://www.example.gov/api/v1/magazines.json
  • 过滤是一种查询:
    • GET http://www.example.gov/api/v1/magazines.json?year=2011&sort=desc
    • GET http://www.example.gov/api/v1/magazines.json?topic=economy&year=2011
  • JSON格式的一个杂志资源:
    • GET http://www.example.gov/api/v1/magazines/1234.json
  • 本杂志中的所有文章(或属于本杂志):
    • GET http://www.example.gov/api/v1/magazines/1234/articles.json
  • 本杂志中的所有文章都是XML格式:
    • GET http://example.gov/api/v1/magazines/1234/articles.xml
  • 在逗号分隔列表中指定可选字段:
    • GET http://www.example.gov/api/v1/magazines/1234.json?fields=title,subtitle,date
  • 在特定杂志中添加新文章:
    • POST http://example.gov/api/v1/magazines/1234/articles

错误的URL示例
  • 非复数名词:
    • http://www.example.gov/magazine
    • http://www.example.gov/magazine/1234
    • http://www.example.gov/publisher/magazine/1234
  • 网址中的动词:
    • http://www.example.gov/magazine/1234/create
  • 在查询字符串之外过滤
    • http://www.example.gov/magazines/2011/desc

HTTP动词

应使用HTTP谓词或方法,以符合HTTP / 1.1标准下的定义。动作时与正在处理的媒体类型及其当前状态有关。以下是HTTP谓词如何映射到特定上下文中的创建,读取,更新,删除操作的示例:
/dogs
POST: 创建一个狗
GET: 列表
UPDATE:更新
DELETE:删除所有

响应

  • key中不能有值
  • 不能有内部特定的名称(例如“node”和“taxonomy term分类术语”)
  • 元数据应仅包含响应集的直接属性,而不包含响应集成员的属性

"键中没有值"的好例子

"tags": [
  {
"id": "125", "name": "Environment"},
  {
"id": "834", "name": "Water Quality"}
],

"键中有值"的坏例子

"tags": [
  {
"125": "Environment"},
  {
"834": "Water Quality"}
],

错误处理

错误响应应包括常见的:HTTP状态代码,开发人员的消息,最终用户的消息(适当时),内部错误代码(对应于某些特定的内部确定的ID),开发人员可以找到更多信息的链接。
例如:

{
  "status" : 400,
 
"developerMessage" : "Verbose, plain language description of the problem. Provide developers
   suggestions about how to solve their problems here
",
 
"userMessage" : "This is a message that can be passed along to end-users, if needed.",
 
"errorCode" : "444444",
 
"moreInfo" : "http://www.example.gov/developer/path/to/help/for/444444,
   http:
//drupal.org/node/444444",
}


使用三个简单的常见响应代码表示(1)成功,(2)由于客户端问题导致的故障,(3)由于服务器端问题导致的故障:

200 - 好的
400 - 错误请求
500 - 内部服务器错误


版本

  • 永远不要在没有版本号的情况下发布API。
  • 版本应为整数,而不是十进制数,前缀为“v”。例如:
    • 好:v1,v2,v3
    • 差:v-1.1,v1.2,1.3
  • 维护至少一个版本的API。

记录限制

  • 如果未指定限制,则返回默认限制。
  • 要获得记录51到75,请执行以下操作:
    • http://example.gov/magazines?limit=25&offset=50
    • offset = 50表示'跳过前50条记录'
    • limit = 25表示'最多返回25条记录'

有关记录限制和总可用计数的信息也应包含在响应中。例:

{
    "metadata": {
       
"resultset": {
           
"count": 227,
           
"offset": 25,
           
"limit": 25
        }
    },
   
"results":
}

请求和响应示例
API资源

  • GET /magazines
  • GET /magazines/[id]
  • POST /magazines/[id]/articles
  •  

GET /magazines

Example: http://example.gov/api/v1/magazines.json
响应体:

{
    "metadata": {
       
"resultset": {
           
"count": 123,
           
"offset": 0,
           
"limit": 10
        }
    },
   
"results": [
        {
           
"id": "1234",
           
"type": "magazine",
           
"title": "Public Water Systems",
           
"tags": [
                {
"id": "125", "name": "Environment"},
                {
"id": "834", "name": "Water Quality"}
            ],
           
"created": "1231621302"
        },
        {
           
"id": 2351,
           
"type": "magazine",
           
"title": "Public Schools",
           
"tags": [
                {
"id": "125", "name": "Elementary"},
                {
"id": "834", "name": "Charter Schools"}
            ],
           
"created": "126251302"
        }
        {
           
"id": 2351,
           
"type": "magazine",
           
"title": "Public Schools",
           
"tags": [
                {
"id": "125", "name": "Pre-school"},
            ],
           
"created": "126251302"
        }
    ]
}

GET /magazines/[id]

Example: http://example.gov/api/v1/magazines/[id].json
响应体:

{
    "id": "1234",
   
"type": "magazine",
   
"title": "Public Water Systems",
   
"tags": [
        {
"id": "125", "name": "Environment"},
        {
"id": "834", "name": "Water Quality"}
    ],
   
"created": "1231621302"
}

POST /magazines/[id]/articlesExample: Create – POST http://example.gov/api/v1/magazines/[id]/articles
响应体:

[
    {
        "title": "Raising Revenue",
       
"author_first_name": "Jane",
       
"author_last_name": "Smith",
       
"author_email": "jane.smith@example.gov",
       
"year": "2012",
       
"month": "August",
       
"day": "18",
       
"text": "xxxxxxx.. "
    }
]

模拟响应

建议每个资源在测试服务器上接受'mock'参数。传递此参数应返回模拟数据响应(绕过后端)

。在开发早期实现此功能可确保API表现出一致的行为,支持测试驱动的开发方法。注意:如果mock参数包含在对生产环境的请求中,则应引发错误。

JSONP
解释JSONP最简单是用一个例子。这是StackOverflow中的定义:

假设您在域名abc.com上,并且您想向域xyz.com发出请求。要做到这一点,你需要跨越域边界,在大多数浏览器领域都是禁忌。绕过此限制的一个项目是标签。

当您使用这个脚本标签时,跨域限制将被忽略,但在正常情况下,您无法对结果做任何事情,只会对脚本进行评估。

当你向启用了JSONP的服务器发出请求时,你会传递一个特殊参数,告诉服务器一些关于您的页面的信息。这样,服务器就能够以您的页面可以处理的方式很好地包装其响应。例如,假设服务器需要一个名为“callback”的参数来启用其JSONP功能。然后你的请求看起来像:
http://www.xyz.com/sample.aspx?callback=mycallback

如果没有JSONP,这可能会返回一些基本的javascript对象,如下所示:
{ foo: 'bar' }

但是,使用JSONP时,当服务器收到“callback”参数时,它会以不同的方式包装结果,返回如下内容:
mycallback({ foo: 'bar' });

如您所见,它现在将调用您指定的方法。因此,在您的页面中,您定义了回调函数:
mycallback = function(data){ alert(data.foo); };