RESTful架构

参见:https://www.cnblogs.com/alex3714/articles/6808013.html

一.介绍
1.起源:

从某种意义上来说,网站即软件,并且是1种新型的软件;这种"互联网软件"采用B/S模式,建立在分布式体
系上,通过互联网进行通信.具有高延时(High Latency)/高并发(High Concurrency)等特点

网站开发,完全可以采用软件开发的模式;但是在传统上,软件和网络是2个不同的领域,很少有交集:软件
开发主要针对单机环境,网络则主要研究系统间的通信;随着互联网的兴起,这2个领域开始融合;现在我们
必须考虑:如何开发在互联网环境中使用的软件

RESTful架构,就是目前最流行的1种互联网软件架构:它结构清晰,符合标准,易于理解,扩展方便,所以正
得到越来越多网站的采用

在这里插入图片描述

REST这个词,最早是在Roy Thomas Fielding的博士论文中被提出的,当时是2000年
这篇论文一经发表,就引起了关注,并立即对互联网开发产生了深远的影响(部分原文见下)
This dissertation explores a junction on the frontiers of two research disciplines in computer science: software and networking. Software research has long been concerned with the categorization of software designs and the development of design methodologies, but has rarely been able to objectively evaluate the impact of various design choices on system behavior. Networking research, in contrast, is focused on the details of generic communication behavior between systems and improving the performance of particular communication techniques, often ignoring the fact that changing the interaction style of an application can have more impact on performance than the communication protocols used for that interaction. My work is motivated by the desire to understand and evaluate the architectural design of network-based application software through principled use of architectural constraints, thereby obtaining the functional, performance, and social properties desired of an architecture.
Fielding将论文中的互联网软件的架构原则定名为REST(Representational State Transfer),可译
为"表现层状态转换";如果1个架构符合REST原则,就称为RESTful架构;原则为:
①每个URI代表1种资源
②Client和Server间,传递这种资源的某种表现层
③Client通过四个HTTP动词,对Server上的资源进行操作,实现"表现层状态转化"

2.资源(Resources):
URI与URL的区别参见:https://blog.csdn.net/qq_32595453/article/details/80563142

REST中的"表现层"省略了定语,"表现层"实际上指的是"资源(Resources)的表现层"
所谓"资源",就是网络上的1个实体,或者说具体的信息,可以是1段文本/1张图片/1首歌/1种服务
可以用1个URI(统一资源标识符)指向1个资源,每个资源对应1个特定的URI
要获取某个资源,访问它的URI即可,因此URI就成了每个资源的地址或标识符
所谓"上网",就是通过调用资源的URI,与互联网上一系列的资源进行互动

3.表现层(Representation):

"资源"是1种信息实体,可以有多种外在表现形式,把"资源"具体呈现出的形式,叫做它的"表现层"
比如,文本可以用txt格式/HTML格式/XML格式/JSON格式表现,也可以采用二进制格式
URI只代表资源的实体,不代表它的形式,有些网址最后会有".html"等后缀,严格来说,这是不必要的
因为这个后缀表示格式,属于"表现层"的范畴,而URI应只代表资源的“位置”
"资源"的具体表现形式,应在HTTP请求头中用Accept/Content-Type字段指定

4.状态转换(State Transfer):

访问1个网站,就代表了Client和Server的1个互动过程,在这个过程中,必定会涉及数据和状态的变化
HTTP协议是1个无状态协议,这意味着,所有状态都保存在Server
因此,如果Client想要操作Server,必须通过某种手段,让服务器端发生"状态转换"
而这种转化是建立在表现层之上的,所以就是"表现层状态转换"

Client操作的方法只能是HTTP协议,也就是HTTP协议里4个表示操作方式的动词:GET/POST/PUT/DELETE
它们分别对应4种操作:GET-获取资源,POST-新建/更新资源,PUT-更新资源,DELETE-删除资源

二.Restful API设计指南
1.协议:

API与用户的通信协议,总是使用HTTPs协议

2.域名:

应该尽量将API部署在专用域名之下:
https://api.example.com
如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下: 
https://example.org/api/

3.版本(Versioning):

按照规范,严格来说"版本号"应被放在请求头里:因为不同的版本,可理解成同一资源的不同表现形式
所以应该采用同1个URI;版本号可在HTTP请求头的Accept字段中进行区分:
  Accept: vnd.example-com.foo+json; version=1.0
  Accept: vnd.example-com.foo+json; version=1.1
  Accept: vnd.example-com.foo+json; version=2.0
Github采用这种做法;但这么做不如放入URL方便直观,因此多数开发者还是会把版本号放在URL中:
  https://api.example.com/v1/

4.路径(Endpoint):

又称"终点"(endpoint),表示API的具体网址

在RESTful架构中,每个网址代表1种资源(resource),所以网址中不能有动词
而只能有名词,并且所用的名词往往与数据库的表格名对应
一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应使用复数
举例来说,有个API提供动物园的信息,以及各种动物和雇员的信息,则路径设计如下:
  https://api.example.com/v1/zoos
  https://api.example.com/v1/animals
  https://api.example.com/v1/employees

5.HTTP动词:

"资源"表示1种实体,所以URL中应该只包含名词,而动词应该放在HTTP协议中
如某个URI是/posts/show/1,其中show是动词,正确的写法应该是/posts/1,然后用GET方法表示show
如果某些动作是HTTP动词表示不了的,就应该把动作做成1种资源
比如网上汇款,从账户1向账户2汇款500元,错误的URI是:
  POST /accounts/1/transfer/500/to/2
正确的写法是把动词transfer改成名词transaction,资源不能是动词,但可以是1种服务:
  POST /accounts/transaction
  from=1&to=2&amount=500.00

对于资源的具体操作类型,由HTTP动词表示,常用的HTTP动词有4个(括号里是对应的SQL命令):
  GET(SELECT):从服务器取出资源
  POST(CREATE):在服务器新建/更新1个资源
  PUT(UPDATE):在服务器更新资源(客户端提供变后的完整资源)
  DELETE(DELETE):从服务器删除资源
还有3个不常用的HTTP动词:
  PATCH(UPDATE):在服务器更新资源(客户端提供改变后的属性)
  HEAD:获取资源的元数据,如名称/大小/格式
  OPTIONS:获取资源的哪些属性可由客户端改变的信息

一些例子:
GET /zoos:列出所有动物园
POST /zoos:新建1个动物园
GET /zoos/<ID>:获取某个指定动物园的信息
PUT /zoos/<ID>:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/<ID>:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/<ID>:删除某个动物园
GET /zoos/<ID>/animals:列出某个指定动物园的所有动物
DELETE /zoos/<ID>/animals/<ID>:删除某个指定动物园的指定动物

6.过滤信息(Filtering):

如果记录数量很多,服务器不可能都将它们都返回给用户;API应提供参数,进行过滤
下面是一些常见的参数:
  ?limit=10:指定返回记录的数量
  ?offset=10:指定返回记录的开始位置
  ?page=2&per_page=100:指定第几页,及每页的记录数
  ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排列顺序
  ?animal_type_id=1:指定筛选条件

参数的设计允许存在冗余,即允许API路径偶尔和URL参数有重复
如GET /zoo/ID/animals与GET /animals?zoo_id=ID的含义是相同的

7.状态码(Status Codes):
全部状态码参见:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

服务器向用户返回的状态码和提示信息,用于帮助分析和调试;常见的状态码见下:
  #方括号中是该状态码对应的HTTP动词,"*"表示所有HTTP动词
  #加"^"表示该操作是幂等的(Idempotent),即任意多次执行该操作产生的影响与执行1次相同
  ^200 OK-[GET]:服务器成功返回用户请求的数据
  201 CREATED-[POST/PUT/PATCH]:用户新建或修改数据成功
  202 Accepted-[*]:表示1个请求已经进入后台排队(异步任务)
  204 NO CONTENT-[DELETE]:用户删除数据成功
  ^400 INVALID REQUEST-[POST/PUT/PATCH]:用户的请求有错误,服务器没有进行操作
  401 Unauthorized-[*]:表示用户没有权限(令牌/用户名/密码错误)
  403 Forbidden-[*]:表示用户得到了授权(与401错误相对),但访问被服务器拒绝
  ^404 NOT FOUND-[*]:用户的请求针对的是不存在的记录,服务器没有进行操作
  406 Not Acceptable-[GET]:用户请求的格式不可得(比如用户请求JSON格式,但只有XML格式)
  410 Gone-[GET]:用户请求的资源是被永久删除且不会再得到的
  422 Unprocesable entity-[POST/PUT/PATCH]:当创建1个对象时,发生1个验证错误
  500 INTERNAL SERVER ERROR-[*]:服务器发生错误,用户将无法判断发出的请求是否成功

8.错误处理(Error Handling):

如果状态码是4xx,就应该向用户返回错误信息(一般是JSON)
最基本的形式是将error作为键,错误信息作为值:
{
    error: "Invalid API key"
}
更完善的错误信息还应该包括错误标识码和说明文档的链接(用于说明解决方法)

9.返回结果:

针对不同操作,服务器向用户返回的结果应符合以下规范:
  GET /collection:返回资源对象的列表(数组)--[dict,dict,dict]
  GET /collection/resource:返回单个资源对象--dict
  POST /collection:返回新生成的资源对象--dict
  PUT /collection/resource:返回完整的资源对象--dict
  PATCH /collection/resource:返回完整的资源对象--dict
  DELETE /collection/resource:返回1个空文档

10.Hypermedia API:

RESTful API最好做到Hypermedia,即在返回结果中提供链接
这个链接连向其他API方法,使用户不查文档也知道下1步应该做什么
比如,当用户向api.example.com这个根目录发出请求,会得到这样1个文档:
{"link": {
  "rel":  "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title":  "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}
上面代码表示:文档中有1个link属性,用户读取这个属性就知道下1步该调用什么API了
rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址)
href表示API的路径,title表示API的标题,type表示返回类型
Hypermedia API的设计被称为HATEOAS,Github的API就是这种设计
访问api.github.com会得到1个所有可用API的网址列表
{
  "current_user_url": "https://api.github.com/user",
  "authorizations_url": "https://api.github.com/authorizations",
                                  ...
}
如果想获取当前用户的信息,应访问api.github.com/user,然后得到如下结果:
{
  "message": "Requires authentication",
  "documentation_url": "https://developer.github.com/v3"
}
上面代码表示:服务器给出了提示信息以及文档的网址

11.其他
(1)API的身份认证应该使用OAuth 2.0框架。
(2)服务器返回的数据格式,应该尽量使用JSON,避免使用XML

三.Django-REST-framework
参见:https://www.cnblogs.com/alex3714/articles/7131523.html
官方文档:https://www.django-rest-framework.org/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值