如何设计出优美的Web API?

  • 概述

WEB API的应用场景很是丰富,例如:将已有系统的功能或数据开放给合做伙伴或生态圈;对外发布可嵌入到其余网页的微件;构建先后端分离的WEB应用;开发跨不一样终端的移动应用;集成公司内部不一样系统等等。在上述场景里,你多是WEB API的使用者,也多是设计者,但你知道如何评判WEB API的优劣吗?php

  • 评判标准

咱们能够从三个维度来评判一个WEB API的优劣:html

  • 易于使用:WEB API的用户是程序仍是人?我以为首先是人,而后是程序。为何这么说呢?是否采用某个WEB API的决定是人作出的,一个好的WEB API必须符合人的审美,例如:简短易记、通俗易懂、便于输入等。从程序角度看,WEB API应该遵循行业规范,在调用时不须要作特殊化处理,有利于复用已有的代码或工具。
  • 便于更改:一个WEB API发布上线以后,免不了要根据真实用户的反馈或者业务发展的须要作更新修改,这些更新修改必须尽可能不影响用户。要么提供多版本支持,要么给用户提供切实可行的更新策略等等。
  • 健壮稳定:对外公开的WEB API存在被攻击的风险,以及没法准确预估的访问量等,一个好的WEB API必需要有防注入、防篡改、防重放等安全机制,还要在访问量急剧上涨时避免服务被击穿。

作到了上述三个方面,咱们才有底气将一个WEB API对外开放,接受公众的检验。好的WEB API不只方便使用,还助于提高我的或企业的技术影响力,从而造成正向循环,带来愈来愈多的业务价值。为了设计出优美的WEB API,咱们须要了解与之相关的设计规范和事实标准,而且在设计开发过程当中尽可能遵循它们。git

  • 设计规范

URI

  • 便于输入的URI,简短不冗余。每一个WEB API都是一个服务,那下面反例当中的“service”就是冗余的,并且“api”也重复出现了两次,这种冗余都不利于记忆和输入:
反例:http://api.example.com/service/api/users
正例:http://api.example.com/users
  • 容易读懂的URI,不要随意采用缩写,缩写必需要符合国际标准规范,不要凭空发明创造,例如:国家代码定义(ISO3166)。反例中出现了两处缩写“sv”、“u”,在没有附加说明的状况下,用户压根不知道含义:
反例:http://api.example.com/sv/u
  • 没有大小写混用的URI。HTTP协议(RFC7230)规定:除了模式(schema)和主机名之外,URI的其余信息都要区分字母的大小写。下述两个反例大小写混用,不方便记忆。
反例:http://api.example.com/Users/12345
反例:http://example.com/API/getUserName
  • 易于修改的URI,命名存在可预见的规律。下述正例咱们能够很容易猜想改变最后的ID就能够访问其余商品的信息。
正例:http://api.example.com/v1/items/123456
  • 不会暴露服务端架构的URI,URI只须要体现功能、数据结构和含义,无需暴露服务端如何运做的信息。这些信息对用户来讲没有意义,还存在潜在的风险,恶意用户或者黑客会利用这些信息来寻找漏洞,发起对服务的攻击。
反例:http://api.example.com/cgi-bin/get_user.php?user=100
  • 规则统一的URI,确保采用统一的规则和风格,方便用户记忆和使用。下述反例中第一个URI采用了查询参数,第二个URI采用了路径参数,这二者没有保持一致,容易形成混乱。
反例:获取好友信息,http://api.example.com/friends?id=100
反例:发送消息,http://api.example.com/friend/100/messages
正例:获取好友信息,http://api.example.com/friends/100
正例:发送消息,http://api.example.com/friends/100/messages
  • URI最好由名词组成。URI的全称是统一资源定位符(Uniform Resource Identifier),用于标识资源在互联网上的位置,相似于邮寄地址,而地址都是由名词组成的。在名词使用上也有一些须要注意的事项:其一,使用名词复数形式;其二,尽可能采用多数API中使用的表示相同含义的单词;其三,经过尽量少的单词来表示;其四,尽量不用奇怪的缩略语等。
  • 不使用空格及须要编码的字符,例如在URI中使用中文等。
  • 使用链接符(-)来链接多个单词,推荐脊柱法:首先,URI里的主机名(域名)容许使用连字符而禁止使用下划线,且不区分大小写。其次,点字符具备特殊含义,为了与主机名的规则保持一致。
脊柱法:http://api.example.com/v1/users/12345/profile-image
蛇形法:http://api.example.com/v1/users/12345/profile_image
驼峰法:http://api.example.com/v1/users/12345/profileImage

查询参数

  • 许多场景下须要经过API分批次获取数据,咱们会常常纠结采用什么样的查询参数,业界有两种经常使用的参数设计(per-page与page、limit与offset),用于标识每次获取的数据量和起始位置。在分批次获取数据的过程当中,数据集合中的记录可能发生增删改变,咱们须要注意采用相对位置或绝对位置所带来的不一样效果。
风格1:http://api.example.com/friends?per-page=50&page=3
风格2:http://api.example.com/friends?limit=50&offset=100
  • 在设计过滤的参数时,业界也有一些事实标准可供参考。若是咱们指望查询结果的特定属性取值跟过滤参数的取值彻底相同,那过滤参数的名称一般为属性名;若是咱们指望查询结果任意属性部分包含过滤参数的取值,那过滤参数的名称一般为“q”。
彻底符合:http://api.example.com/v1/users?name=ken
全文搜索:http://api.example.com/v1/users?q=ken
  • URI是否能够包含动词“search”?一般以搜索为主的在线服务API能够包含,除此以外建议采用名词复数形式。经常使用英文单词“search”和“find”都有查找的含义,但二者仍是有一些细微的差异,其中“search”用于模糊搜索,而“find”用于精准查询。
模糊搜索:http://yboss.yahooapis.com/ysearch/web?q=ipod
  • 某个属性到底是做为URI路径的构成元素仍是做为查询参数呢?咱们能够按照如下规则来判断:若是该属性信息能够惟必定位资源,那么它就适合做为路径构成元素,不然就做为查询参数;若是该属性能够省略,那么它就是适合做为查询参数。
路径元素:http://api.example.com/v1/users/{id}
查询参数:http://api.example.com/v1/users?name=ken

HTTP方法

按照HTTP协议设计的本意,URI用于标识被操做的目标对象(资源),而HTTP方法则是表示操做方法。基于HTTP协议的简单对象访问协议SOAP逐渐被RESTful的原生HTTP协议取代,咱们也没有必要多此一举,最好就是吃透HTTP协议,充分利用它的特性。程序员

GET /v1/users/123 HTTP/1.1
Host: api.example.com
  • GET,获取资源
  • POST,新增资源
  • PUT,更新已有资源
  • DELETE,删除资源
  • PATCH,更新部分资源
  • HEAD,获取资源的元信息

若是遇到上述HTTP方法没法覆盖的场景,那一般是资源的设计粒度太大了,咱们能够把粗粒度的资源分解成多个细粒度的资源。在使用HTTP协议设计WEB API的专业能力上,业界将其划分为四个层级,LEVEL3相对较理想化,缺少实施的基础,LEVEL2是切实可行的:github

  • LEVEL 0:使用HTTP
  • LEVEL 1:引入资源的概念
  • LEVEL 2:引入HTTP动词(GET/POST/PUT/DELETE等)
  • LEVEL 3:引入HATEOAS概念

响应数据

经常使用的数据格式有:HTML、XML、JSON、YAML等,若是咱们的服务在响应时支持不一样类型的数据格式,那应用在调用服务时如何得到指望格式的响应数据呢?一般咱们能够考虑采用下述几种指定数据格式的方法:web

  • 使用查询参数的方法:
示例:https://api.example.com/v1/users?format=xml
  • 使用扩展名的方法:
示例:https://api.example.com/v1/users.json
  • 使用在请求首部指定媒体类型的方法,优先推荐此种方法:
GET /v1/users
Host: api.example.com
Accept: application/json

响应数据应该包含哪些信息呢?是否越多越好?亦或越少越好,仅仅包含ID?建议是按需返回,根据业务功能所需返回相应的数据。若是一个WEB API须要提供给不一样业务场景使用,不一样业务场景对数据属性信息的要求不一样,或多或少,这种状况咱们可让用户来选择响应的内容,选择方法就是经过查询参数指定:面试

示例:http://api.example.com/v1/users/123?fields=name,age

响应数据的结构应该尽可能扁平化,不要嵌套太深,减小没有具体含义的信息载荷,这样既能够压缩报文尺寸,又能够节省带宽的。固然,若是层级结构更具优点,也能够采用。json

出错信息

建议经过HTTP协议首部的状态码来表示出错信息,而不是再封装一层,遵照协议规范的好处是能够减小沟通的成本,也能够利用许多成熟的软硬件产品来处理异常出错信息。HTTP协议定了了五种类型的状态码:后端

  • 1XX:消息
  • 2XX:成功
  • 3XX:重定向
  • 4XX:客户端缘由引发的错误
  • 5XX:服务器端缘由引发的错误

咱们须要每种状态码的使用场景,确保正确使用状态码。除此以外,服务还须要向客户端返回详细的出错信息,咱们一般能够采用下述两种方法来传递详细的出错信息:api

  • 方法1:定义私有的首部,将其填入响应消息的首部。
  • 方法2:将详细的出错信息放入消息体。

版本管理

随着业务的发展,每一个发布上线的WEB API都存在更新修改的可能,那就须要引入版本管理的机制。业界有三种常见的标注WEB API版本的方法:

  • 在URI中嵌入版本编号:
示例:http://api.linkedin.com/v1/people
  • 在查询字符串里加入版本信息:
示例:http://api.example.com/users/123?v=2
  • 经过媒体类型来指定版本信息
Accept: application/vnd.github.v3+json
Content-Type: application/vnd.github.v3+json 

一样,版本编号也存在业界规范:语义化版本控制(Semantic Versioning)规范,网站地址:semver.org。版本编号由点号链接的3个数字组成,例如:1.2.3,分别表示主版本编号、次版本编号、补丁版本编号,版本编号的增长遵循下述规则:

  • 在对软件进行不向下兼容的变动时,增长主版本编号;
  • 在对软件进行向下兼容的变动或废除某些特定的功能时,增长次版本编号;
  • 若是软件的API没有发生变动,只是修正了部分bug,则增长补丁版本编号。

按照版本编号增加的规则,WEB API的版本编号只须要标注主版本编号就能够了,由于次版本编号、补丁版本编号的增长均可以作到向下兼容,不会影响用户使用,惟有主版本编号增长才须要用户更新升级。除了标注版本信息以外,咱们在对外发布WEB API时还须要设计好版本变动的策略,例如:老版本提供多久的过渡期、同时兼容多少个版本、特定版本的终止日期等等。

  • 总结

何为优美?就是符合大众审美的,对于WEB API来讲,就是符合标准规范的,这有利于下降用户学习和使用的成本,便于交流,不存在隐没成本。一般,业界存在的标准规范和事实标准都是通过实践筛选出来的,从遵循模仿开始,而后再找机会创新,而不是一上来就重复发明轮子。

WEB API设计领域的标准规范就是URI、HTTP等,咱们要最大程度地利用这些协议规范,让每一个WEB API都是用户友好(易于使用)、技术友好(支持缓存、易于更改)的。除此以外,咱们还须要考虑WEB API的健壮性,下一次咱们再来谈一谈如何设计健壮的WEB API,欢迎你们找我讨论交流相关话题。

今天先分享到这里,若是你以为有价值,麻烦动动手指 转发 给其余须要的小伙伴。另外,老兵哥我后续还会分享职业规划、应聘面试、技能提高、影响力打造等经验,欢迎 关注 本专栏或歪信公主号 「 IT老兵哥 

微信公众号「 IT老兵哥 」

关注「 IT老兵哥 」,赋能程序人生!

  • 近期职涯类热门文章:
  1. “花式”裁人套路深,你知道吗?
  2. 遭遇裁人,如何渡过心理危机?
  3. 如何在寒冬中找到好工做?
  4. 2C 仍是 2B,跟找工做有什么关系?
  5. 大公司 vs 小公司,你会选哪一个?
  6. 记住这一点,不怕找不到好工做!
  7. 跳槽,跳仍是不跳,该怎么跳?
  8. 程序员“求包养”攻略揭秘
  9. 很努力了,为何我还在原地踏步?

 

  • 近期技术类热门文章:
  1. 程序员必须懂的架构入门课
  2. 从程序员到架构师,有捷径吗?
  3. 图解 Spring:HTTP 请求的处理流程与机制【1】
  4. 图解 Spring:HTTP 请求的处理流程与机制【2】
  5. 图解 Spring:HTTP 请求的处理流程与机制【3】
  6. 图解 Spring:HTTP 请求的处理流程与机制【4】
  7. 图解 Spring:HTTP 请求的处理流程与机制【5】
  8. 如何正确使用 Spring Cloud?【上】
  9. 如何正确使用 Spring Cloud?【中】
  10. 如何正确使用 Spring Cloud?【下】
  11. Spring 核心技术与产品理念剖析【上】
  12. Spring 核心技术与产品理念剖析【下】