WebAPI在过去几年里非常的盛行,我们很多以往的技术手段都慢慢的转换为使用WebAPI来开发,因为它的语法简单规范化,以及轻量级等特点,这种方式收到了广泛的推崇。
通常我们使用RESTFul(Representational State Transfer)的设计方式来设计Web api,这通常用来分离API结构了业务逻辑,它使用典型的HTTP方法,诸如GET,POST.DELETE,PUT来和资源进行交互。
以下是设计RESTful API的是个最佳实践:
1. 使用名词而不是动词
为了易于理解,为资源使用下面的API结构:
不要使用动词
<code>/getAllCars /createNewCar /deleteAllRedCars/<code>
2. Get方法和查询参数不应该改变资源状态
使用Put,Post和Delete方法替代Get方法来改变资源状态。不要使用Get来使状态改变:
<code>GET
/users/711?activate or
GET
/users/711/activate
/<code>
3. 使用名词的复数形式
不要混合使用单数和复数形式,而应该为所有资源一直保持使用复数形式:
<code>/cars instead of /car /users instead of /user /products instead of /product /settings instead of /setting/<code>
4. 为关系使用子资源
假如资源连接到其它资源,则使用子资源形式:
<code>GET/cars/711/drivers/
Returns a listof
driversfor
car711
GET /cars/711
/drivers/4
Returns driver /<code>
5. 使用HTTP头决定序列化格式
在客户端和服务端都需要知道使用什么格式来进行通信,这个格式应该在HTTP头中指定:
- Content-Type:定义请求的格式;
- Accept :定义允许的响应格式的列表
6. 使用HATEOAS
Hypermedia as the Engine of A pplication State是一个指导原则,它规定超文本链接应该被用于在API中创建更好的资源导航:
<code>{"id"
:711
,"manufacturer"
:"bmw"
,"model"
:"X5"
,"seats"
:5
,"drivers"
: [ {"id"
:"23"
,"name"
:"Stefan Jauker"
,"links"
: [ {"rel"
:"self"
,"href"
:"/api/v1/drivers/23"
} ] } ] }/<code>
7. 为集合提供过滤、排序、字段选择以及分页
过滤
为所有字段或者查询语句提供独立的查询参数:
<code>GET /cars?color=red Returns alist
of red cars GET /cars?seats2
Returns alist
of cars with a maximum of2
seats/<code>
排序
允许跨越多字段的正序或者倒序排列:
<code>GET /cars?sort
=-manufactorer,+model/<code>
字段选择
一些情况下,我们只需要在列表中查询几个有标识意义的字段,我们不需要从服务端把所有字段的值都请求出来,所以需要支持API选择查询字段的能力,这也可以提到网络传输性能和速度:
<code>GET
/cars?fields=manufacturer,model,id,color/<code>
分页
使用offset和limit来获取固定数量的资源结果,当其中一个参数没有出现时,应该提供各自的默认值,比如默认取第一页,或者默认取20条数据:
<code>GET /cars?offset=10
&limit=5
GET/cars?&limit=5 /
/Get first five result GET/cars?&offset=5 /
/Getdefault
amount result offset5
/<code>
使用自定义的头X-Total-Count发回给调用段实际的资源数量。
前一页后一页的链接也应该在HTTP头链接中得到支持,遵从下文中的链接原则而不要构建你自己的头:
<code>Link:<
https:
//blog.mwaysolutions.com
/sample
/api
/v1
/cars
?offset
=15&limit
=5
>; rel="next",<
https:
//blog.mwaysolutions.com
/sample
/api
/v1
/cars
?offset
=50&limit
=3
>; rel="last",<
https:
//blog.mwaysolutions.com
/sample
/api
/v1
/cars
?offset
=0&limit
=5
>; rel="first",<
https:
//blog.mwaysolutions.com
/sample
/api
/v1
/cars
?offset
=5&limit
=5
>; rel="prev",/<code>
8. 版本化你的API
确保强制实行API版本,并且不要发布一个没有版本的API,使用简单的序列数字,避免使用2.5.0这样的形式:
<code>/blog/api/v1/<code>
9. 使用HTTP状态码处理错误
忽略错误处理的API是很难使用的,简单的返回500和调用堆栈是非常不友好也非常无用的:
使用HTTP状态码
HTTP标准提供了70多个状态码来描述返回值,我们不需要完全用到他们,下文中列出10个使用率较高的:
200 – OK – 一切正常201 – OK – 新资源已经被创建204 – OK – 资源删除成功
304 – 没有变化,客户端可以使用缓存数据
400 – Bad Request – 调用不合法,确切的错误应该在error payload中描述,例如:“JSON 不合法 ”401 – 未认证,调用需要用户通过认证403 – 不允许的,服务端正常解析和请求,但是调用被回绝或者不被允许404 – 未找到,指定的资源不存在422 – 不可指定的请求体 – 只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失。
500 – Internal Server Error – 标准服务端错误,API开发人员应该尽量避开这种错误
使用 error payloads
所有的异常都应该被映射到error payloads中,下文中的例子是一个json payload的模板:
<code>{"errors"
: [ {"userMessage"
:"Sorry, the requested resource does not exist"
,"internalMessage"
:"No car found in the database"
,"code"
:34
,"more info"
:"http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
} ] } /<code>
10. 允许重写HTTP方法
一些代理只支持GET和POST方法,为了在这种限制下支持RESTful API,API需要重写HTTP方法。
使用自定义的X-HTTP-Method-Override HTTP头来重写POST方法。