RESTful API 设计最佳实践(8)
2017-02-28 00:40
501 查看
前面几篇文章介绍了一些RESTful API设计方面的参考规范,这篇文章我们来看几个“不良”的例子,并以个人的实践总结为这一系列做个结尾。欢迎大家评论交流。
点评: 只是去掉了rpc的外壳包袱,可以在浏览器中直接查了,但method=status这种格式是典型的rpc。
2. 玩家领取活动礼包
点评:(1)客户端发送数据选择了application/x-www-form-urlencoded格式,而不是更为广泛使用的json或edn格式。 (2)为某个玩家增加一个礼包,应该为:
POST /activity/users/{user-id}/packages/{package-name}
3. 根据牌局信息查找对应的牌局ID(UUID)
点评:
(1)这里要获取的资源是game-id,过滤条件是qijuid、username、gamesign,所以,应该设计为:
GET /games/game-id?qijuid={qijuid}&username={username}&game-sign={game-sign}.
(2)game-id不存在时,不应该返回nil 而是返回404.
(3)如果没有特殊需要,统一返回JSON或EDN。
4.1. 获取单局牌局录像信息
4.2. 获取单局牌局分享信息
点评:
牌局记录信息只是牌局分享信息中的一个属性,分成两个接口获取是非REST的。在资源定义时,牌局这一资源(包括上述所有信息)应该是暴露给外部的,可以统一用一个API解决。
如,获取牌局录像:
GET /super-star/games/:game-id?fields=record
获取牌局所有分享信息:
GET /super-star/games/:game-id
还是以RPC的思想来设计RESTful API和REST服务。最明显的表现是,习惯性在设计API时使用“根据XX得到XX”,这是典型的RPC设计,针对过程,而非资源。
对“资源”来抽象服务的这种形式理解不到位。还是会将资源对应为一个过程产生的值。
在设计资源关系的API时,处理不正确,参考上述例子。
对于什么时候该用查询参数,什么时候将“变量”写到基本URI中不太清楚。
开发流程有问题,先根据初步设计API,再实现,再修改API,导致API设计妥协于实现。但REST服务的实现应该是RESTful API驱动开发的,类似于测试驱动开发。
API的设计和REST服务妥协于实现/现实。
时间压力:要实现一个真正的REST服务,实现其灵活性和可扩展性,相对于那种RPC式的开发可能要花费更多的时间,比如要支持查询参数灵活变动、自定义排序、自定义所需的资源属性等。
第二步:设计RESTful API,对第一步定义的资源进行标识,并确定其资源表述格式,包括header(如支持的媒体类型,content-type等)、body。比如确定哪些资源是支持通过查询参数自由过滤的,那些是支持自由指定返回的资源属性的,哪些是整个资源全部返回的;成功时的状态码,异常时的状态码及异常消息格式等。
第三步:针对API进行实现。
一、几个“不良”示例
1. 查询当前活动状态** 请求:** GET /activity/query?method=status&game=PDK&type=a Accept:json ** 应答:** {:status-code 200 :body { status : 当前活动状态close/open}
点评: 只是去掉了rpc的外壳包袱,可以在浏览器中直接查了,但method=status这种格式是典型的rpc。
2. 玩家领取活动礼包
** 请求:** POST /activity/package User-Agent: 浏览器信息 Cookie: token=XXXXXXXXXXXXXX Accept:application/json; charset=UTF-8 Content-type: application/x-www-form-urlencoded; charset=UTF-8 body: username=aa&name=”礼包名称” ** 回应:** {status-code: 201 // 领取成功 body: { name : “礼包名称” msg : “*******”}}
点评:(1)客户端发送数据选择了application/x-www-form-urlencoded格式,而不是更为广泛使用的json或edn格式。 (2)为某个玩家增加一个礼包,应该为:
POST /activity/users/{user-id}/packages/{package-name}
3. 根据牌局信息查找对应的牌局ID(UUID)
** 请求:** GET /games/game-id/{qijuid}/{username}/{gamesign} Cookie: token=XXXXXXXXXXXXXX ** 回应:** {status-code: 200 body: “fds4324324gfdfds324d /nil (如果没有,返回nil)”
点评:
(1)这里要获取的资源是game-id,过滤条件是qijuid、username、gamesign,所以,应该设计为:
GET /games/game-id?qijuid={qijuid}&username={username}&game-sign={game-sign}.
(2)game-id不存在时,不应该返回nil 而是返回404.
(3)如果没有特殊需要,统一返回JSON或EDN。
4.1. 获取单局牌局录像信息
** 请求:** GET /games/record/game-id Cookie: token=XXXXXXXXXXXXXX Accept:json ** 回应:** {status-code: 200 body: {record: JKJKDJFSFDSJK…. //牌局记录信息}
4.2. 获取单局牌局分享信息
** 请求:** GET /games/game/game-id Cookie: token=XXXXXXXXXXXXXX Accept:json ** 回应:** {status-code: 200 body: {id: 牌局ID username: 分享者ID flower: 12345 time: 分享时间 desc: 分享者分享时的描述}}
点评:
牌局记录信息只是牌局分享信息中的一个属性,分成两个接口获取是非REST的。在资源定义时,牌局这一资源(包括上述所有信息)应该是暴露给外部的,可以统一用一个API解决。
如,获取牌局录像:
GET /super-star/games/:game-id?fields=record
获取牌局所有分享信息:
GET /super-star/games/:game-id
二、总结
总的来说,当前我们对RESTful API的设计与服务的实现可能存在以下几个方面的不足:还是以RPC的思想来设计RESTful API和REST服务。最明显的表现是,习惯性在设计API时使用“根据XX得到XX”,这是典型的RPC设计,针对过程,而非资源。
对“资源”来抽象服务的这种形式理解不到位。还是会将资源对应为一个过程产生的值。
在设计资源关系的API时,处理不正确,参考上述例子。
对于什么时候该用查询参数,什么时候将“变量”写到基本URI中不太清楚。
开发流程有问题,先根据初步设计API,再实现,再修改API,导致API设计妥协于实现。但REST服务的实现应该是RESTful API驱动开发的,类似于测试驱动开发。
API的设计和REST服务妥协于实现/现实。
时间压力:要实现一个真正的REST服务,实现其灵活性和可扩展性,相对于那种RPC式的开发可能要花费更多的时间,比如要支持查询参数灵活变动、自定义排序、自定义所需的资源属性等。
三、个人REST实践流程总结
第一步:定义资源(REST中资源是粗粒度的),使用“资源”来抽象整个服务(一定是资源!千万不要陷入“根据什么来获取什么”的思路中!),确定哪些资源需要暴露给外部,资源的具体属性可以先不细致确定。第二步:设计RESTful API,对第一步定义的资源进行标识,并确定其资源表述格式,包括header(如支持的媒体类型,content-type等)、body。比如确定哪些资源是支持通过查询参数自由过滤的,那些是支持自由指定返回的资源属性的,哪些是整个资源全部返回的;成功时的状态码,异常时的状态码及异常消息格式等。
第三步:针对API进行实现。
相关文章推荐
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践(转)
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- 转:RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践(转)
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- (转)RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- RESTful API 设计最佳实践
- [转]RESTful API 设计最佳实践
- ****RESTful API 设计最佳实践(APP后端API设计参考典范)
- RESTful API 设计最佳实践