近期,组内的前后端分离项目中用到了RESTful进行后台API的设计,经过一段时间的学习和实践,我对RESTful API设计有了进一步的认识。该项目中后台部分采用的框架是ThinkPHP5
,前端部分用的是vue2+vue-router+vuex
的全家桶,用axios
进行数据交互。这里总结一下对RESTful API的学习和设计心得。
RESTful简介
RESTful(Representational State Transfer,表现层状态转移)是一种软件架构风格,主要用于客户端(包括浏览器)与服务器端进行数据交互的场景。一个好的RESTful API设计,可以让服务器端只实现一套API接口,就能同时为Web应用、移动端、电脑端同时提供更简洁,更有层次,更易于实现缓存的服务。
RESTful设计举例
知乎上对RESTful API有一条言简意赅的解释:
看
url
就知道要什么,看http method
就知道干什么,看http status code
就知道结果如何。
举个例子:如果拿课程(course)作为一个资源,对其进行符合RESTful的API接口设计,其url一般可以设计成如下格式:
- 获取课程资源列表
[GET]http://api.hostname.com/v1/courses
- 获取指定id的课程资源
[GET]http://api.hostname.com/v1/courses/id
- 新建课程资源
[POST]http://api.hostname.com/v1/courses
- 更新课程资源(全部)
[PUT]http://api.hostname.com/v1/courses
- 更新课程资源(部分)
[PATCH]http://api.hostname.com/v1/courses
- 删除课程资源
[DELETE]http://api.hostname.com/v1/courses
- 获取指定id的课程下的实验资源列表
[GET]http://api.hostname.com/v1/courses/id/experiments
- 获取课程资源列表(分页查询)
[GET]http://api.hostname.com/v1/courses?query=&page=2&per_page=100
由上述例子可以看出,RESTful用url
来表示一个资源(列表),用HTTP method
来表示对资源的增删改查,用http请求参数
来对访问的资源作进一步限定。一些实际应用中公认的设计优良的的RESTful API可以参考github和leancloud。
RESTful设计准则
按上述几个方面划分,RESTful设计需要符合如下准则:
一、url
RESTful架构中的url代表的是一个资源。url一般需要符合如下要求:
- url中最好加入API的版本号信息;
- url中尽量用名词表示资源;
- url中尽量用名词的复数;
- url中一般会加入可选的参数(如
id
),表示对资源限制条件; - url中可按需加入过滤信息(如
?q=&page=2&per_page=100
、?sortby=name&order=asc
、?type=1
等);
二、http method
RESTful中用到的http method如下:
- // 常用
- GET (SELECT) :获出资源(一项或多项)。
- POST (CREATE) :新建一个资源。
- PUT (UPDATE) :更新资源(客户端提供改变后的完整资源)。
- PATCH (UPDATE) :更新资源(客户端只提供待改变部分的属性)。
- DELETE (DELETE) :删除资源。
- // 不常用
- HEAD:获取资源的元数据。
- OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
三、http status code
RESTful API返回的响应结果中,其http状态码应该按照http规范对响应结果的状态进行表示。常见的状态码与提示信息如下:
- 200 OK – [GET] 操作成功
- 201 CREATED – [POST/PUT/PATCH] 新建/修改数据成功
- 204 NO CONTENT – [DELETE] 删除数据成功
- 400 INVALID REQUEST – [POST/PUT/PATCH] 请求的数据有误
- 404 NOT FOUND – [*] 资源不存在
- 500 INTERNAL SERVER ERROR – [*] 服务器发生错误
四、other
- 对于4xx的错误情况,需要将错误的信息返回,比如
{"error":"没有权限!"}
; - 返回的结果尽量使用json格式;
- 最好添加身份验证,如
OAuth 2.0
,或api_key
; - 最好做到Hypermedia,即在返回结果中提供指向该API的说明文档链接或其他相关API的链接。