RESTful 是目前最流行的 API 设计规范,是一种网络应用程序的设计风格和开发方式,基于 HTTP,可以使用 XML 格式定义或 JSON 格式定义。
REST 的全称叫:表现层状态转换(英语:Representational State Transfer,缩写:REST)是 Roy Thomas Fielding 博士于 2000 年在他的博士论文中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。
很多人往往会理解错 RESTful,本文列举了 RESTful 的 7 个最佳实践,希望能加深大家对 RESTful 的理解!
版本
相信不少人在面试中都被问到过,RESTful 在遇到版本问题时是如何设计的。这里我们可以借鉴 Github 的做法。
如 github 开放平台 https://developer.github.com/v3/,就是将版本放在 url,简洁明了,这个只有用了才知道,一般的项目加版本 v1,v2,v3。。。
也有的项目会将版本号放在 header 里面,但是不如放在 url 直接了当。
除了 Github,Google APIs 和 Twitter APIs 在 URL 中加入了版本。需要注意的是在 URL 中带有版本信息,并不是使用错误。这是一种正确的合法的,符合 REST 各种约束的使用方法。
参数命名规范
query parameter 可以采用驼峰命名法,也可以采用下划线命名的方式,推荐采用下划线命名的方式,据说后者比前者的识别度要高。当然这也不是绝对的,具体因团队规范而异吧。
https://example.com/api/users/today_login 获取今天登陆的用户
https://example.com/api/users/today_login&sort=login_desc 获取今天登陆的用户、登陆时间降序排列
url 命名规范
API 命名应该采用约定俗成的方式,保持简洁明了。在 RESTful 架构中,每个 url 代表一种资源所以 url 中不能有动词,只能有名词,并且名词中也应该使用复数。实现者应使用相应的 Http 动词 GET、POST、PUT、PATCH、DELETE、HEAD 来操作这些资源即可。
不规范的的 url,冗余没有意义,形式不固定,不同的开发者还需要了解文档才能调用。
https://example.com/api/getallUsers GET 获取所有用户
https://example.com/api/getuser/1 GET 获取标识为1用户信息
https://example.com/api/user/delete/1 GET/POST 删除标识为1用户信息
https://example.com/api/updateUser/1 POST 更新标识为1用户信息
https://example.com/api/User/add POST 添加新的用户
规范后的 RESTful 风格的 url,形式固定,可读性强,根据 users 名词和 http 动词就可以操作这些资源。
https://example.com/api/users GET 获取所有用户信息
https://example.com/api/users/1 GET 获取标识为1用户信息
https://example.com/api/users/1 DELETE 删除标识为1用户信息
https://example.com/api/users/1 Patch 更新标识为1用户部分信息,包含在body中
https://example.com/api/users POST 添加新的用户
统一返回数据格式
对于合法的请求应该统一返回数据格式,这里演示的是 json。
- code——包含一个整数类型的HTTP响应状态码。
- status——包含文本:”success”,”fail”或”error”。HTTP状态响应码在500-599之间为”fail”,在400-499之间为”error”,其它均为”success”(例如:响应状态码为1XX、2XX和3XX)。这个根据实际情况其实是可要可不要的。
- message——当状态值为”fail”和”error”时有效,用于显示错误信息。参照国际化(il8n)标准,它可以包含信息号或者编码,可以只包含其中一个,或者同时包含并用分隔符隔开。
- data——包含响应的body。当状态值为”fail”或”error”时,data仅包含错误原因或异常名称、或者null也是可以的
返回成功的响应 json 格式
{
"code": 200,
"message": "success",
"data": {
"userName": "123456",
"age": 16,
"address": "beijing"
}
}
返回失败的响应 json 格式。
{
"code": 401,
"message": "error message",
"data": null
}
下面这个 ApiResult 的泛型类是在项目中用到的,拓展性强,使用方便。返回值使用统一的 ApiResult 或 ApiResult 错误返回 使用 ApiResult.Error 进行返回;成功返回,要求使用 ApiResult.Ok 进行返回。
http 状态码
在之前开发的 xamarin android 博客园客户端的时候,patch、delete、post 操作时 body 响应里面没有任何信息,仅仅只有 http status code。HTTP 状态码本身就有足够的含义,根据 http status code 就可以知道删除、添加、修改等是否成功。(ps:有点linux设计的味道哦,没有返回消息就是最好的消息,表示已经成功了)服务段向用户返回这些状态码并不是一个强制性的约束。简单点说你可以指定这些状态,但是不是强制的。常用 HTTP 状态码对照表 HTTP 状态码也是有规律的。
- 1** 请求未成功
- 2** 请求成功、表示成功处理了请求的状态代码。
- 3** 请求被重定向、表示要完成请求,需要进一步操作。通常,这些状态代码用来重定向。
- 4** 请求错误这些状态代码表示请求可能出错,妨碍了服务器的处理。
- 5**(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。
合理使用query parameter
在请求数据时,客户端经常会对数据进行过滤和分页等要求,而这些参数推荐采用HTTP Query Parameter的方式实现。
比如设计一个最近登陆的所有用户
https://example.com/api/users?recently_login_day=3
搜索用户,并按照注册时间降序
https://example.com/api/users?recently_login_day=3
搜索用户,并按照注册时间升序、活跃度降序
https://example.com/api/users?q=key&sort=create_title_asc,liveness_desc
关于分页,看看博客园开放平台分页获取精华区博文列表
https://api.cnblogs.com/api/blogposts/@picked?pageIndex={pageIndex}&pageSize={pageSize}
返回示例:
[
{
“Id”: 1,
“Title”: “sample string 2”,
“Url”: “sample string 3”,
“Description”: “sample string 4”,
“Author”: “sample string 5”,
“BlogApp”: “sample string 6”,
“Avatar”: “sample string 7”,
“PostDate”: “2017-06-25T20:13:38.892135+08:00”,
“ViewCount”: 9,
“CommentCount”: 10,
“DiggCount”: 11
},
{
“Id”: 1,
“Title”: “sample string 2”,
“Url”: “sample string 3”,
“Description”: “sample string 4”,
“Author”: “sample string 5”,
“BlogApp”: “sample string 6”,
“Avatar”: “sample string 7”,
“PostDate”: “2017-06-25T20:13:38.892135+08:00”,
“ViewCount”: 9,
“CommentCount”: 10,
“DiggCount”: 11
}
]
多表、多参数连接查询如何设计URL
这是一个比较头痛的问题,在做单个实体的查询比较容易和规范操作,但是在实际的API并不是这么简单而已,这其中常常会设计到多表连接、多条件筛选、排序等。比如我想查询一个获取在6月份的订单中大于500元的且用户地址是北京,用户年龄在22岁到40岁、购买金额降序排列的订单列表。
https://example.com/api/orders?order_month=6&order_amount_greater=500&address_city=北京&sort=order_amount_desc&age_min=22&age_max=40
从这个 URL 上看,参数众多、调用起来还得一个一个仔细对着,而且API本身非常不容易维护,命名看起来不是很容易,不能太长,也不能太随意。
在.net WebAPI 总我们可以使用属性路由,属性路由就是讲路由附加到特定的控制器或操作方法上装饰 Controll 及其使用[Route]属性定义路由的方法称为属性路由。
这种好处就是可以精准地控制URL,而不是基于约定的路由,简直就是为这种多表查询量身定制似的的。从webapi 2开发,现在是RESTful API开发中最推荐的路由类型。我们可以在Controll中标记 Route。
[Route(“api/orders/{address}/{month}”)]
Action中的查询参数就只有金额、排序、年龄。减少了查询参数、API的可读性和可维护行增强了。
https://example.com/api/orders/beijing/6?order_amount_greater=500&sort=order_amount_desc&age_min=22&age_max=40
这种属性路由比如在博客园开放的 API 也有这方面的应用,如获取个人博客随笔列表。
请求方式:GET
请求地址:https://api.cnblogs.com/api/blogs/{blogApp}/posts?pageIndex={pageIndex}
(ps:blogApp:博客名)
以上,7 种最佳实践希望能对大家有所帮助!
: » RESTful 的 7 个最佳实践
原创文章,作者:wure,如若转载,请注明出处:https://blog.ytso.com/252921.html