什么是REST
- REST与技术无关,代表的是一种软件架构风格.REST全称是Representational State Tranfer, 表征性状态转移.
- REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用的转变装态
- 所有的数据,不管是通过网络获取还是增删改查的数据都是资源, 将一切数据视为资源是REST区别其他架构风格的最本质属性
- 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)
RESTful API设计规范
-
API与用户的通信协议,总是使用HTTPS协议
-
域名
- https://example.org/api/ (推荐使用)
- https://api.example.com (存在跨域问题)
-
版本
- URL, 添加版本号,如:https://api.example.com/v1/
- 版本号放在请求头中
-
method
-
GET :从服务器取出资源(一项或多项)
-
安全且幂等
-
获取表示
-
变更时获取表示(缓存)
-
200(OK) - 表示已在响应中发出
-
204(无内容) - 资源有空表示
-
301(Moved Permanently) - 资源的URI已被更新
-
303(See Other) - 其他(如,负载均衡)
-
304(not modified)- 资源未更改(缓存)
-
400 (bad request)- 指代坏请求(如,参数错误)
-
404 (not found)- 资源不存在
-
406 (not acceptable)- 服务端不支持所需表示
-
500 (internal server error)- 通用错误响应
-
503 (Service Unavailable)- 服务端当前无法处理请求
-
-
POST :在服务器新建一个资源
-
不安全且不幂等
-
使用服务端管理的(自动产生)的实例号创建资源
-
创建子资源
-
部分更新资源
-
如果没有被修改,则不过更新资源(乐观锁)
-
200(OK)- 如果现有资源已被更改
-
201(created)- 如果新资源被创建
-
202(accepted)- 已接受处理请求但尚未完成(异步处理)
-
301(Moved Permanently)- 资源的URI被更新
-
303(See Other)- 其他(如,负载均衡)
-
400(bad request)- 指代坏请求
-
404 (not found)- 资源不存在
-
406 (not acceptable)- 服务端不支持所需表示
-
409 (conflict)- 通用冲突
-
412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
-
415 (unsupported media type)- 接受到的表示不受支持
-
500 (internal server error)- 通用错误响应
-
503 (Service Unavailable)- 服务当前无法处理请求
-
-
PUT :在服务器更新资源(客户端提供改变后的完整资源)
-
不安全但幂等
-
用客户端管理的实例号创建一个资源
-
通过替换的方式更新资源
-
如果未被修改,则更新资源(乐观锁)
-
200 (OK)- 如果已存在资源被更改
-
201 (created)- 如果新资源被创建
-
301(Moved Permanently)- 资源的URI已更改
-
303 (See Other)- 其他(如,负载均衡)
-
400 (bad request)- 指代坏请求
-
404 (not found)- 资源不存在
-
406 (not acceptable)- 服务端不支持所需表示
-
409 (conflict)- 通用冲突
-
412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
-
415 (unsupported media type)- 接受到的表示不受支持
-
500 (internal server error)- 通用错误响应
-
503 (Service Unavailable)- 服务当前无法处理请求
-
-
PATCH :在服务器更新资源(客户端提供改变的属性)
-
DELETE :从服务器删除资源
-
不安全但幂等
-
删除资源
-
200 (OK)- 资源已被删除
-
301 (Moved Permanently)- 资源的URI已更改
-
303 (See Other)- 其他,如负载均衡
-
400 (bad request)- 指代坏请求
-
404 (not found)- 资源不存在
-
409 (conflict)- 通用冲突
-
500 (internal server error)- 通用错误响应
-
503 (Service Unavailable)- 服务端当前无法处理请求
-
-
-
路径,一切都是资源, 均用名词表示(可以复数)
-
过滤, 通过在url上传参的形式传递搜索条件
- https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
- https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
- https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
- https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
- https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
状态码
-
1 开头: 服务器正在处理
-
2 开头: 服务器处理成功
-
3 开头: 重定向
-
4 开头: 客户端错误
-
5开头 : 服务器错误
在返回的数据中携带状态码
URl设计上的技巧
-
使用
_
或者-
让URL可读性更好 -
使用
/
表示资源层级关系 -
使用
?
过滤资源 -
使用
,
或者;
表示同级资源关系GitHub使用
…
来表示同级关系
基于Django实现
路由
urlpatterns = [
url(r'^users/$', views.Users.as_view()),
url(r'^users2/$', views.user2),
]
视图
import json
def user2(request):
if request.method=='GET':
dic = {'status':200,'name': 'lqz2', 'age': 18}
return HttpResponse(json.dumps(dic))
elif request.method=='POST':
dic = {'status': 200, 'msg': '修改成功'}
return JsonResponse(dic)
class Users(View):
def get(self, request):
dic = {'status':200,'name': 'lqz', 'age': 18}
return HttpResponse(json.dumps(dic))
def post(self, request):
dic = {'status': 200, 'msg': '修改成功'}
return JsonResponse(dic)
常见问题:
POST和PUT用于创建资源时有什么区别?
POST和PUT在创建资源的区别在于,所创建的资源的名称(URI)是否由客户端决定。 例如为我的博文增加一个java的分类,生成的路径就是分类名/categories/java,那么就可以采用PUT方法。不过很多人直接把POST、GET、PUT、DELETE直接对应上CRUD,例如在一个典型的rails实现的RESTful应用中就是这么做的。
我认为,这是因为rails默认使用服务端生成的ID作为URI的缘故,而不少人就是通过rails实践REST的,所以很容易造成这种误解。
客户端不一定都支持这些HTTP方法吧?
的确有这种情况,特别是一些比较古老的基于浏览器的客户端,只能支持GET和POST两种方法。
在实践上,客户端和服务端都可能需要做一些妥协。例如rails框架就支持通过隐藏参数_method=DELETE来传递真实的请求方法, 而像Backbone这样的客户端MVC框架则允许传递_method传输和设置X-HTTP-Method-Override头来规避这个问题。