JSON

软件开发外包中API设计学习之Github

字号+ 作者:H5之家 来源:H5之家 2017-03-20 15:00 我要评论( )

几年提供 HTTP API 服务的公司越来越多,许多公司都把 API 作为产品重要的一部分,作为服务提供出去。而微服务的兴起,也让企业内部开始重视和频繁使用 HTTP API

软件开发外包中API设计学习之Github

2017-03-17 14:30:40

几年提供 HTTP API 服务的公司越来越多,许多公司都把 API 作为产品重要的一部分,作为服务提供出去。而微服务的兴起,也让企业内部开始重视和频繁使用 HTTP API 。好的 HTTP API 设计容易理解、符合 RFC 标准、提供使用者便利的功能,其中经常被拿来作为教科书典范的当属 Github API。这篇文章就通过 Github API 总结了一些非常好的设计原则,可以作为以后要编写 HTTP API 的参考。

注意:这篇文章只讨论设计原则,不是强制要求(API 设计者可以根据实际情况实现部分内容,甚至实现出和某些原则相反的内容),也不会给出实现的思路和细节。

1. 使用 HTTPS

这个和 Restful API 本身没有很大的关系,但是对于增加网站的安全是非常重要的。特别如果你提供的是公开 API,用户的信息泄露或者被攻击会严重影响网站的信誉。

NOTE:不要让非SSL的url访问重定向到SSL的url。

2. API 地址和版本

在 url 中指定 API 的版本是个很好地做法。如果 API 变化比较大,可以把 API 设计为子域名,比如 https://api.github.com/v3;也可以简单地把版本放在路径中,比如https://example.com/api/v1。

3. schema

对于响应返回的格式,JSON 因为它的可读性、紧凑性以及多种语言支持等优点,成为了 HTTP API 最常用的返回格式。因此,最好采用 JSON 作为返回内容的格式。如果用户需要其他格式,比如 xml,应该在请求头部 Accept 中指定。对于不支持的格式,服务端需要赶回正确的 status code,并给出详细的说明。

4. 以资源为中心的 URL 设计

资源是 Restful API 的核心元素,所有的操作都是针对特定资源进行的。而资源就是URL(Uniform Resoure Locator)表示的,所以简洁、清晰、结构化的 URL 设计是至关重要的。Github 可以说是这方面的典范,下面我们就拿 repository 来说明。

/users/:username/repos /users/:org/repos /repos/:owner/:repo /repos/:owner/:repo/tags /repos/

我们可以看到几个特性:

  • 资源分为单个文档和集合,尽量使用复数来表示资源,单个资源通过添加 id 或者 name 等来表示
  • 一个资源可以有多个不同的 URL
  • 资源可以嵌套,通过类似目录路径的方式来表示,以体现它们之间的关系
  • NOTE: 根据RFC3986定义,URL是大小写敏感的。所以为了避免歧义,尽量使用小写字母。

    5. 使用正确的 Method

    有了资源的 URL 设计,所有针对资源的操作都是使用 HTTP 方法指定的。比较常用的方法有:

    Verb 描述

    HEAD 只获取某个资源的头部信息。比如只想了解某个文件的大小,某个资源的修改日期等

    GET 获取资源

    POST 创建资源

    PATCH 更新资源的部分属性。因为 PATCH 比较新,而且规范比较复杂,所以真正实现的比较少,一般都是用 POST 替代

    PUT 替换资源,客户端需要提供新建资源的所有属性。如果新内容为空,要设置 Content-Length为 0,以区别错误信息

    DELETE 删除资源

    比如:

    /repos//repos//repos//repos/:owner/:repo

    NOTE:更新和创建操作应该返回最新的资源,来通知用户资源的情况;删除资源一般不会返回内容。

    不符合 CRUD 的情况

    在实际资源操作中,总会有一些不符合 CRUD(Create-Read-Update-Delete) 的情况,一般有几种处理方法。

    使用 POST

    为需要的动作增加一个 endpoint,使用 POST 来执行动作,比如 POST /resend 重新发送邮件。

    增加控制参数

    添加动作相关的参数,通过修改参数来控制动作。比如一个博客网站,会有把写好的文章“发布”的功能,可以用上面的 POST /articles/{:id}/publish 方法,也可以在文章中增加 published:boolean 字段,发布的时候就是更新该字段 PUT /articles/{:id}?published=true

    把动作转换成资源

    把动作转换成可以执行 CRUD 操作的资源, github 就是用了这种方法。

    比如“喜欢”一个 gist,就增加一个 /gists/:id/star 子资源,然后对其进行操作:“喜欢”使用 PUT /gists/:id/star,“取消喜欢”使用 DELETE /gists/:id/star 。

    另外一个例子是 Fork,这也是一个动作,但是在 gist 下面增加 forks资源,就能把动作变成 CRUD 兼容的:POST /gists/:id/forks 可以执行用户 fork 的动作。

    6. Query 让查询更自由

    比如查询某个 repo 下面 issues 的时候,可以通过以下参数来控制返回哪些结果:

  • state:issue 的状态,可以是 open,closed,all
  • since:在指定时间点之后更新过的才会返回
  • assignee:被 assign 给某个 user 的 issues
  • sort:选择排序的值,可以是 created、updated、comments
  • direction:排序的方向,升序(asc)还是降序(desc)
  • ……
  • 7. 分页 Pagination

    当返回某个资源的列表时,如果要返回的数目特别多,比如 github 的 /users,就需要使用分页分批次按照需要来返回特定数量的结果。

    分页的实现会用到上面提到的 url query,通过两个参数来控制要返回的资源结果:

  • per_page:每页返回多少资源,如果没提供会使用预设的默认值;这个数量也是有一个最大值,不然用户把它设置成一个非常大的值(比如 99999999)也失去了设计的初衷
  • page:要获取哪一页的资源,默认是第一页
  • 返回的资源列表为 [(page-1)*per_page, page*per_page)。github API 文档中还提到一个很好的点,相关的分页信息还可以存放到 Link 头部,这样客户端可以直接得到诸如下一页、最后一页、上一页等内容的 url 地址,而不是自己手动去计算和拼接。

    8. 选择合适的状态码

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    网友点评