Web API 设计之最佳实践

wmwj0083 8年前
   <p>许多文章讲述API的开发,如REST,SOAP,Json等。本篇以实践为中心,理论和实践相结合,与各位开发者讨论在API开发前的设计思维。让你可以在开发之前,将这些事想清楚,相信会事半功倍。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/c496de49642ba905cf0ca8f75c5603ae.jpg"></p>    <p><strong>概述</strong></p>    <p>各位朋友,何谓 API ?想必你一定知道 APP , APP 我们手机端的软件应用,它是 Application 的简写。</p>    <p>本文中心思想主要讲述 API的 设计。 API 是个甚? API 是英文是 Application Programming Interface 的简写,中文是应用编程接口之意,用于对接两个应用间的数据和消息,以及函数调用等。</p>    <p>APP 是面向最终用户, API 是面向软件开发者。</p>    <p>在单机时代,类似于系统与应用程序之间,会有开放的函数来交互,称之为系统级别的 API ,比如 Windows 系统的称为 Win32 API , Linux 内核也有开放接口。这些 API 绝大多数由 C/C++ 来开发,编译或封装给应用开发者调用。</p>    <p>开源平台因为已经将源代码开放到了底。我们在使用 API 的时候,还能看到 API 和底层方法怎么写的,可以根据自身需要重新编译。比如 JDK 、 Python 、 PHP 的虚拟机,开发者引用内置函数,知道其然还知所以然。</p>    <p>移动互联网时代,越来越多的设备和应用需要接入互联网。它们需要一个标准的协议和规范,来与服务器交互。例如网站, APP ,微信公众号, IPad 客户端, iWatch 还有很多 VR 设备、物联网应用等都需要与服务器间交互。</p>    <p>当然最普遍的是Web网站应用。因为要求上线速度快,人员能力等各种原因,好多是面条式的代码,而使用 API ,能够让这种情况得到有效改观——因为使用了统一的通讯接口。</p>    <p>由于是与服务器通讯,皆使用 HTTP 协议,我们不去谈 RESTFful ,且将此类称为 HTTP API 或 Web API 。</p>    <p>Web API 的报文协议, RPC 有几类,比如最常见的 WebService ,此类为开放的 XML 或远程方法。另外还有 Json 格式,还有如 protobuffer , thirft 等协议效率会更高。</p>    <p><strong>API设计之目标</strong></p>    <p>下面我们开始着手设计 API (本文默认 API 为 Web API )。 API 开发者,首先需要站得更高的视角,尽最大努力以用户的视角来开始设计。</p>    <p>API 开发者往往是这样的视角: 『这个服务需要做什么?』或『这个服务需要提供什么?』</p>    <p>而 API 使用者关注的则是:我怎样才能使用这个 API , API 怎么满足我的需要?或者更准确的说,『我咋样才能花费最少时间,很简单的调用 ?』。归根结底, API 得好用。</p>    <p>各位看,其实不同角色导致了两种截然不同的思维。所以 ,要设计好一个 API ,前提是视角要从 API 设计者转向 使用者。</p>    <p>我们要不断地问自己,如果你是使用的人,会问哪些问题。与其思考 API 可以作些什么,不妨多考虑它可能需要的,然后专注于完成这些,尽可能让 用户调用方便。</p>    <p>说时容易做时难,实际上会出很多情况会出忽我们的意料 。 比如某个公司写 SOA API 的工程师,使用 Thirft 也好还是使用其它协议,写的方法和参数非常晦涩难懂(这里不抓图了)。</p>    <p>为何出此?出问题的可能是设计的架构师,或者工程师自己。这种情况就违背了我们写 API 的初衷,如果调用 API ,还不如存取数据库方便,API是为了效率更高,而非显得很高深。</p>    <p>有鉴于此,我们再一起聊一聊写好 API 接口的几个方面。</p>    <p><strong>1 优秀的API 文档</strong></p>    <p>程序猿最烦的两件事儿,第一件是别人要他给自己的代码写文档,第二件是别人的程序没有留下文档。</p>    <p>写 API 的应该不是一个程序员,或者不能把自己当程序员,我们要对自己自己很高的要求。你要有写一篇 API 文档,能够帮助开发者快速入手。</p>    <p>不必写特别长的文字,只需要干净利索,函数说明,参数,返回值是啥就可以。 API 比程序更复杂,所以你写的文档是极具价值的。</p>    <p>其实有很多值得关注的优秀的 API 文档之范例。比如看 Twilio , Django 还有淘宝、天猫、 404 网站 Google 的开放平台文档。这些产品都提供了非常全的文档,且清晰易用,更促进用户认可,更增进产品的市场份额。</p>    <p>一篇好文档的体现,使用者在 15 分钟能够明白整体的使用,包括要遵循的规约和基础函数。如果使用者不能在这此时间内能够整合调用,这意味站我们有更多的事儿要做。</p>    <p><strong>2 稳定与一致性</strong></p>    <p>有的网站 API ,他们经常修改和完全重写它们 API 。无论它有多牛,或者我们多么尊重他们的文化。但却不是站在开发人员友好的角度。</p>    <p>一个网站或应用要成功,不仅要对他的亿万用户友好,还要对合作伙伴、开发者友好,这样的公司会更伟大,更成功。</p>    <p>无论有没有庞大的用户群,API设计者 都不要轻易做修改。比如多版本运行,比如对老版本应用支持相当长的一段时间,甚至是几年。</p>    <p>比如一个类似 http://21cto.com/api/widgets 的URL,它返回 JSON 格式的内容。表面上 URL没变 ,但是我经常修改的 JSON结构 ,加字段或修改数组类型。这样调用的人都要和重新和接口重新对接,原来的逻辑被打乱。哎呀,这样怎能受得了。</p>    <p>因此,在做 API 设计时,我们做一些提前规划。比如从一开始就明确地 URL 命名为一个版本号。例如:</p>    <p>http://21ctom.com/api/widgets?version= 1</p>    <p>http://21cto.com/api/widgets/v1</p>    <p>这样一来,比如初版的应用仍然可以正常工作,新版本的产品之间不会影响。</p>    <p>除非你有很详实的数据表明,老版已经无用户,我们当然在某个时候逐步淘汰以前的版本。在还有用户的时候,需要继续维护,然后给用户足够的提示,并提供足够好的过渡计划。</p>    <p>好的 URL 方案将包括 URL 中的主要版本 . 。对输出格式或支持的数据类型的任何更改都会导致新的主要版本出现故障 . 。一般来说,如果你所做的是在你的输出中添加密钥或节点,但要在安全的地方,任何时候输出的变化,碰撞一个版本,一般都可以保持相同的版本。</p>    <p>另外,除了随着时间的推移,保持 API 稳定性,比如 内部函数保持一致。 在 API 中处理好参数,尽量使用相同或共享的参数体系,如在整个 API 中使用相同的命名约定和数据返回。</p>    <p>有时候实在不得已需要修改,尽量能够最小差异的做改变。每次更新,我们可以记录和发布 API 更新的文档,告诉调用者 API的 版本差异,详细说明如何升级。</p>    <p><strong>3 灵活性</strong></p>    <p>灵活性,表示输入灵活,输出多样,这尤其适用于开放平台的 API 开发者。调用的开发者,有个人开发者,公司,有网站,有 APP ,还有各种应用软件,客户端平台并不是一致的,有的可能还不支持 JSON ,不支持 OAuth 等。</p>    <p>所以在设计 API 时,要有一定的灵活性和格式宽容,对于你的输入和输出的限制这是很好的。</p>    <p>API 可以支持多种输出,如 XML 、 JSON 、 YAML 等格式。但在 URL 请求是一致的,如 /api/v1/component 。也可以接受请求类似 application/json 的 HTTP 头,或者支持 URL 的 GET 参数变量,如 ?version=json 等。</p>    <p>为了容错,对参数可以忽略大小写,让调用者减轻不必要的挫折。输入的参数也可以做到多种格式,比如 GET 和 POST 方法都支持,格式可以为变量,也可以是 json 和 XML 。</p>    <p>支持多数的标准的输入输出,可以最大化的让 API 具备灵活性,不在是我们个人的技术偏好。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2e9962d70e6188f6ca82e4bff9d0c6cc.jpg"></p>    <p><strong>4 安全性</strong></p>    <p>安全是 API 相当重要的任务。对于内容型的 API ,如果没有私密的数据传输,当然可以不设置鉴权。但对于一些数据敏感的数据来说,需要对调用的用户进行身份验证鉴权。</p>    <p>对于大多数 API ,可以使用简单的基于 token 的身份验证。 token 是一个哈希分配给调用者,允许通过 POST 或 HTTP 请求。比如可以用 sha1 或 MD5 的哈希字符串给到调用者,也可以使用 DES 的方式,如: da39a3ee5e6b4b0d3255bfef95601890afd80709 ”。</p>    <p>一个安全的 token ,最好不只是一串标识符,不可逆当然是最好的。</p>    <p>比如在创建调用者用户 ID 时生成一个 sha1 token ,存储在数据库里。可以将哈希 + Salt 的方式生成 token ,比如 username + 123456 ,然后再到数据库查询匹配用户(篇幅原因,详细可参阅本人拙著《 PHP 与 MySQL 高性能应用开发》,这里不再赘述)。</p>    <p>另一个使用广泛的方法,可以采用 OAuth 2.0 + SSL 。</p>    <p>现在的时代,无论如何都得使用 SSL 。另外 OAuth 2.0 也已经成为服务器端验证的标准,大多数开发语言都有成熟的把持。</p>    <p>Web API大多需要 支持 JavaScript 调用,如 JQuery 等库来获取数据。这时需要严格验证来源,以保证非授权网站调用,防止用户数据丢失或被窃取。</p>    <p>可以使用白名单或用户角色处理。比如可以通过用户分级来对限制数据的创建、读取、更新和删除等操作。比如只有授权用户才可以调用诸如 /user/delete/id 。如果未经授权,返回错误消息,比如 406 响应。</p>    <p>另外,还要避免 API 受跨站请求伪造( CSRF )攻击。一些 API 应用会有 session 或 cookie 认证,一定要注意 CSRF跨站 。比如有一个请求来查看用户的详细信息(如 account/card/view/152423 ),需要在代码中检查 ID=152423 是指经过授权访问的资源。</p>    <p>为此, API 需要严密验证输入数据,包括数据完整性和数据精度,以保证所有来自用户的输入能够精确解析。</p>    <p>可以对 API 请求的历史进行日志记录,包括次数,频率,异常时及时报警。</p>    <p><strong>5 易用性</strong></p>    <p>上面说了好多规则,似乎说的挺严重。</p>    <p>其实做的时候考虑周全,做到倒也不难。在开篇时我提到过, API 文档要做到能够在 15 分钟内能让开发者明白咋用,不是为了文档而文档,而是一篇优秀的教程,这也同时说明 API 的简单易用。</p>    <p>如果我们做的是内部应用的 API ,最重要的是不需要沟通,通过看文档就能让调用者完成开发,这是一个可以达到的目标。</p>    <p>再总结一些具体的建议,与大家一起学习探讨。</p>    <ul>     <li> <p>保持简单,不做花哨的身份验证</p> </li>    </ul>    <p>不做自定义的 URL 规则,比如 SOAP 、 JSON 或 REST 等啥都用。采用主流技术,让开发者学习 API ,而不是既得学习 API 还有我那二把刀的新技术。</p>    <p>时至今日,已经有很多不错的工具能够自动为生成 API 和 API Doc ,如 Thirft 、 Alpaca( https://github.com/pksunkara/alpacaThrift) ,后者支持 Java , PHP , Python , Ruby 。 C++ , Perl , Haskell , Erlang , C # 、、 JavaScript 、 Node.js , Smalltalk 等语言。</p>    <p>另外, github 上也有一些生成 API 和 DOC 的库,各种语言均有。当然我们要选择成熟的,自己能够控制好的项目。</p>    <ul>     <li> <p>提供一流的技术支持</p> </li>    </ul>    <p>很多时候,技术支持是国内产品的一大障碍。(这里我要检讨一下, 21CTO 公众号网站我们会及时更新和回复的 ^_^ )</p>    <p>需要经常问自己的几个问题:</p>    <ol>     <li> <p>对于用户提交的问题,我们如何处理和回复?</p> </li>     <li> <p>对用户来说,文档足够简单好学吗?</p> </li>    </ol>    <p>如果是开放平台的 API ,在线客服, Bug 跟踪,邮件支持是基本的选项。确保第一时间回答 bug ,并真正解决它。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/c85c8d792734452d15d83f471a364659.jpg"></p>    <p><strong>小结</strong></p>    <p>如今大量的网络服务和 APP 应用,有很多难用的产品,主要的原因包括设计不佳,缺乏文档,经常修改,稳定,错误解决慢等问题。</p>    <p>希望本文有助于各位设计的 API 干净,规范和易用,同时也对自己一个提醒。</p>    <p>虽然事情有时不会那么完美,但是我们在开始就这样做,并一直向好的方向努力。如同下棋,多看 5 步,多想几圈,总比只盯眼前好。 你说对吗?</p>    <p> </p>    <p> </p>    <p>来自:http://mp.weixin.qq.com/s/hOuex-oWxHypx-RzburkZQ</p>    <p> </p>