Web API设计之最佳实践

21CTO社区导读:
许多文章讲述API的开发,如REST,SOAP,Json等。本篇以实践为中心,理论和实践相结合,与各位开发者讨论在API开发前的设计思维。让你可以在开发之前,将这些事想清楚,相信会事半功倍。


/uploads/fox/26091024_0.jpeg

概述


各位朋友,何谓API?想必你一定知道APP,APP我们手机端的软件应用,它是Application 的简写。
本文中心思想主要讲述API的设计。API是个甚?API是英文是Application Programming Interface的简写,中文是应用编程接口之意,用于对接两个应用间的数据和消息,以及函数调用等。
APP是面向最终用户,API是面向软件开发者。
在单机时代,类似于系统与应用程序之间,会有开放的函数来交互,称之为系统级别的API,比如Windows系统的称为Win32 API,Linux内核也有开放接口。这些API绝大多数由C/C++来开发,编译或封装给应用开发者调用。
开源平台因为已经将源代码开放到了底。我们在使用API的时候,还能看到API和底层方法怎么写的,可以根据自身需要重新编译。比如JDK、Python、PHP的虚拟机,开发者引用内置函数,知道其然还知所以然。
移动互联网时代,越来越多的设备和应用需要接入互联网。它们需要一个标准的协议和规范,来与服务器交互。例如网站,APP,微信公众号,IPad客户端,iWatch还有很多VR设备、物联网应用等都需要与服务器间交互。
当然最普遍的是Web网站应用。因为要求上线速度快,人员能力等各种原因,好多是面条式的代码,而使用API,能够让这种情况得到有效改观——因为使用了统一的通讯接口。
由于是与服务器通讯,皆使用HTTP协议,我们不去谈RESTFful ,且将此类称为HTTP API或Web API。
Web API的报文协议,RPC有几类,比如最常见的WebService,此类为开放的XML或远程方法。另外还有Json格式,还有如protobuffer,thirft等协议效率会更高。

API设计之目标


下面我们开始着手设计API(本文默认API为Web API)。API开发者,首先需要站得更高的视角,尽最大努力以用户的视角来开始设计。
API开发者往往是这样的视角:『这个服务需要做什么?』或『这个服务需要提供什么?』
而API使用者关注的则是:我怎样才能使用这个API,API怎么满足我的需要?或者更准确的说,『我咋样才能花费最少时间,很简单的调用?』。归根结底,API得好用。
各位看,其实不同角色导致了两种截然不同的思维。所以,要设计好一个API,前提是视角要从API设计者转向使用者。
我们要不断地问自己,如果你是使用的人,会问哪些问题。与其思考API可以作些什么,不妨多考虑它可能需要的,然后专注于完成这些,尽可能让用户调用方便。
说时容易做时难,实际上会出很多情况会出忽我们的意料。比如某个公司写SOA API的工程师,使用Thirft也好还是使用其它协议,写的方法和参数非常晦涩难懂(这里不抓图了)。
为何出此?出问题的可能是设计的架构师,或者工程师自己。这种情况就违背了我们写API的初衷,如果调用API,还不如存取数据库方便,API是为了效率更高,而非显得很高深。
有鉴于此,我们再一起聊一聊写好API接口的几个方面。

1 优秀的API文档


程序猿最烦的两件事儿,第一件是别人要他给自己的代码写文档,第二件是别人的程序没有留下文档。
写API的应该不是一个程序员,或者不能把自己当程序员,我们要对自己自己很高的要求。你要有写一篇API文档,能够帮助开发者快速入手。
不必写特别长的文字,只需要干净利索,函数说明,参数,返回值是啥就可以。API比程序更复杂,所以你写的文档是极具价值的。
其实有很多值得关注的优秀的API文档之范例。比如看Twilio,Django还有淘宝、天猫、404网站Google的开放平台文档。这些产品都提供了非常全的文档,且清晰易用,更促进用户认可,更增进产品的市场份额。
一篇好文档的体现,使用者在15分钟能够明白整体的使用,包括要遵循的规约和基础函数。如果使用者不能在这此时间内能够整合调用,这意味站我们有更多的事儿要做。

2 稳定与一致性


有的网站API,他们经常修改和完全重写它们API。无论它有多牛,或者我们多么尊重他们的文化。但却不是站在开发人员友好的角度。
一个网站或应用要成功,不仅要对他的亿万用户友好,还要对合作伙伴、开发者友好,这样的公司会更伟大,更成功。
无论有没有庞大的用户群,API设计者都不要轻易做修改。比如多版本运行,比如对老版本应用支持相当长的一段时间,甚至是几年。
比如一个类似的URL,它返回JSON格式的内容。表面上URL没变,但是我经常修改的JSON结构,加字段或修改数组类型。这样调用的人都要和重新和接口重新对接,原来的逻辑被打乱。哎呀,这样怎能受得了。
因此,在做API设计时,我们做一些提前规划。比如从一开始就明确地URL命名为一个版本号。例如:
http://21ctom.com/api/widgets?version= 1
 
这样一来,比如初版的应用仍然可以正常工作,新版本的产品之间不会影响。
除非你有很详实的数据表明,老版已经无用户,我们当然在某个时候逐步淘汰以前的版本。在还有用户的时候,需要继续维护,然后给用户足够的提示,并提供足够好的过渡计划。
好的URL方案将包括URL中的主要版本.。对输出格式或支持的数据类型的任何更改都会导致新的主要版本出现故障.。一般来说,如果你所做的是在你的输出中添加密钥或节点,但要在安全的地方,任何时候输出的变化,碰撞一个版本,一般都可以保持相同的版本。
另外,除了随着时间的推移,保持API稳定性,比如内部函数保持一致。在API中处理好参数,尽量使用相同或共享的参数体系,如在整个API中使用相同的命名约定和数据返回。
有时候实在不得已需要修改,尽量能够最小差异的做改变。每次更新,我们可以记录和发布API更新的文档,告诉调用者API的版本差异,详细说明如何升级。

3 灵活性


灵活性,表示输入灵活,输出多样,这尤其适用于开放平台的API开发者。调用的开发者,有个人开发者,公司,有网站,有APP,还有各种应用软件,客户端平台并不是一致的,有的可能还不支持JSON,不支持OAuth等。
所以在设计API时,要有一定的灵活性和格式宽容,对于你的输入和输出的限制这是很好的。
API可以支持多种输出,如XML、JSON、YAML等格式。但在URL请求是一致的,如/api/v1/component。也可以接受请求类似application/json的HTTP头,或者支持URL的GET参数变量,如?version=json等。
为了容错,对参数可以忽略大小写,让调用者减轻不必要的挫折。输入的参数也可以做到多种格式,比如GET和POST方法都支持,格式可以为变量,也可以是json和XML。
支持多数的标准的输入输出,可以最大化的让API具备灵活性,不在是我们个人的技术偏好。
/uploads/fox/26091024_1.jpeg

4 安全性


安全是API相当重要的任务。对于内容型的API,如果没有私密的数据传输,当然可以不设置鉴权。但对于一些数据敏感的数据来说,需要对调用的用户进行身份验证鉴权。
对于大多数API,可以使用简单的基于token的身份验证。token是一个哈希分配给调用者,允许通过POST或HTTP请求。比如可以用sha1或MD5的哈希字符串给到调用者,也可以使用DES的方式,如:da39a3ee5e6b4b0d3255bfef95601890afd80709”。
一个安全的token,最好不只是一串标识符,不可逆当然是最好的。
比如在创建调用者用户ID时生成一个sha1 token,存储在数据库里。可以将哈希+ Salt的方式生成token,比如username + 123456,然后再到数据库查询匹配用户(篇幅原因,详细可参阅本人拙著《PHP与MySQL高性能应用开发》,这里不再赘述)。
另一个使用广泛的方法,可以采用OAuth 2.0 + SSL。
现在的时代,无论如何都得使用SSL。另外OAuth 2.0也已经成为服务器端验证的标准,大多数开发语言都有成熟的把持。
Web API大多需要支持Java调用,如JQuery等库来获取数据。这时需要严格验证来源,以保证非授权网站调用,防止用户数据丢失或被窃取。
可以使用白名单或用户角色处理。比如可以通过用户分级来对限制数据的创建、读取、更新和删除等操作。比如只有授权用户才可以调用诸如/user/delete/id。如果未经授权,返回错误消息,比如406响应。
另外,还要避免API受跨站请求伪造(CSRF)攻击。一些API应用会有session或cookie认证,一定要注意CSRF跨站。比如有一个请求来查看用户的详细信息(如account/card/view/152423),需要在代码中检查ID=152423是指经过授权访问的资源。
为此,API需要严密验证输入数据,包括数据完整性和数据精度,以保证所有来自用户的输入能够精确解析。
可以对API请求的历史进行日志记录,包括次数,频率,异常时及时报警。

5 易用性


上面说了好多规则,似乎说的挺严重。
其实做的时候考虑周全,做到倒也不难。在开篇时我提到过,API文档要做到能够在15分钟内能让开发者明白咋用,不是为了文档而文档,而是一篇优秀的教程,这也同时说明API的简单易用。
如果我们做的是内部应用的API,最重要的是不需要沟通,通过看文档就能让调用者完成开发,这是一个可以达到的目标。
再总结一些具体的建议,与大家一起学习探讨。
  • 保持简单,不做花哨的身份验证

不做自定义的URL规则,比如SOAP、JSON或REST等啥都用。采用主流技术,让开发者学习API,而不是既得学习API 还有我那二把刀的新技术。
时至今日,已经有很多不错的工具能够自动为生成API和API Doc,如Thirft、Alpaca(,后者支持Java,PHP,Python,Ruby。C++,Perl,Haskell,Erlang,C #、、Java、Node.js,Smalltalk等语言。
另外,github上也有一些生成API和DOC的库,各种语言均有。当然我们要选择成熟的,自己能够控制好的项目。
  • 提供一流的技术支持

很多时候,技术支持是国内产品的一大障碍。(这里我要检讨一下,21CTO公众号网站我们会及时更新和回复的^_^)
需要经常问自己的几个问题:
  1. 对于用户提交的问题,我们如何处理和回复?
  2. 对用户来说,文档足够简单好学吗?

如果是开放平台的API,在线客服,Bug跟踪,邮件支持是基本的选项。确保第一时间回答bug,并真正解决它。
/uploads/fox/26091024_2.jpeg

小结


如今大量的网络服务和APP应用,有很多难用的产品,主要的原因包括设计不佳,缺乏文档,经常修改,稳定,错误解决慢等问题。
希望本文有助于各位设计的API干净,规范和易用,同时也对自己一个提醒。
虽然事情有时不会那么完美,但是我们在开始就这样做,并一直向好的方向努力。如同下棋,多看5步,多想几圈,总比只盯眼前好。你说对吗?

/uploads/fox/26091024_3.png
作者:杜江。21CTO(21cto.com)社区创始人。多年架构与管理经验。 著有《PHP5与MySQL5 Web开发技术详解》、《PHP5完全攻略》、《PHP与MySQL高性能应用开发》(机械工业出版社出版,各大电商平台和书店有售)。


2 个评论

学习了/酷
职责单一,一个接口只做件事。
抽象原则,接口只体现业务目标,不体现业务逻辑。

要回复文章请先登录注册