admin 管理员组文章数量: 888297
2024年2月21日发(作者:windows找不到文件mongodb)
l说明
1.1简介
REST(Representational State Transfer 通常被翻译为“表述性状态传输”或者“表述性状态转移”)是RoyFielding提出的一个描述互联系统架构风格的名词。为什么称为REST?Web本质上由各种各样的资源组成,资源由URI 唯一标识。浏览器(或者任何其它类似于浏览器的应用程序)将展示出该资源的一种表现方式,或者一种表现状态。如果用户在该页面中定向到指向其它资源的链接,则将访问该资源,并表现出它的状态。这意味着客户端应用程序随着每个资源表现状态的不同而发生状态转移,也即所谓 REST。
简单地来说REST它是一种使用URL来定位资源,使用HTTP请求描述操作的Web服务规范。REST主要包括以下几方面:
(1) REST是一组架构约束条件和原则,而满足这些约束条件和原则的应用程序就是RESTful。
(2)REST的目标是构建可扩展的Web Service,它是一种更简单的SOAP(Simple Object Access Protocol)协议以及以WSDL为基础的WebService的替代。
(3)REST采用的是HTTP协议并通过HTTP中的GET、POST、PUT、DELETE等动词收发数据。
(4) REST希望通过HTTP来完成对数据的元操作,即传统的CRUD(Create、Read、Update、Delete)分别对应GET、POST、PUT、DELETE,这样就统一了数据操作的接口,实现在不同平台上提供一套相同的服务。
(5) REST是一种面向服务的、分布式的API设计风格。
RESTful API的开发和使用,无非是客户端向服务器发请求(request),以及服务器对客户端请求的响应(response)。所以RESTful架构风格具有统一接口的特点,即:使用不同的http方法表达不同的行为:
请求方法
GET(SELECT)
方法说明
从服务器取出资源(一项或多项)
POST(CREATE) 在服务器新建一个资源
PUT(UPDATE)
PATCH(UPDATE
在服务器更新资源(客户端提供完整资源数据)
在服务器更新资源(客户端提供需要修改的资源数据)
DELETE(DELETE) 从服务器删除资源
1. 2优劣分析
在很久以前,工作时间长的同学肯定经历过使用velocity语法来编写html模板代码,也就是说我们的前端页面放在服务器端那边进行编译的,更准确的可以理解为 "前后端没有进行分离",那么在那个时候,页面、数据及模板渲染操作都是放在服务器端进行的,但是这样做有一个很大的缺点是: 后期维护比较麻烦,前端开发人员还必须掌握velocity相关的语法。因此为了解决这个问题慢慢就出现了前后端分离的思想: 即后端负责数据接口, 前端负责数据渲染, 前端只需要请求下api接口拿到数据,然后再将数据显示出来。因此后端开发人员需要设计api接口,因此为了统一规范: 社区就出现了 RESTful API 规范,其实该规范很早就有的,只是最近慢慢流行起来,RESTful API 可以通过一套统一的接口为所有web相关提供服务,实现前后端分离。
前后端说明:
1.1前后端不分离
在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高。
这种应用模式比较适合纯网页应用,但是当后端对接App时,App可能并不需要后端返回一个HTML网页,而仅仅是数据本身,所以后端原本返回网页的接口不再
适用于前端App应用,为了对接App后端还需再开发一套接口。
请求的数据交互如下图:
1.2前后端分离
在前后端分离的应用模式中,后端仅返回前端所需的数据,不再渲染HTML页面,不再控制前端的效果。
至于前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端自己决定,网页有网页的处理方式,App有App的处理方式,但无论哪种前端,所需的数据基本相同,后端仅需开发一套逻辑对外提供数据即可。
在前后端分离的应用模式中 ,前端与后端的耦合度相对较低。在前后端分离的应用模式中,我们通常将后端开发的每个视图都称为一个接口,或者API,前端通过访问接口来对数据进行增删改查。
对应的数据交互如下图 :
1.3 RESTful架构优点列表
(1)前后端分离,减少流量;
(2)安全问题集中在接口上,由于接受json格式,防止了注入型等安全问题;
(3)前端无关化,后端只负责数据处理,前端表现方式可以是任何前端语言(android,ios,html5);
(4)前端和后端人员更加专注于各自开发,只需接口文档便可完成前后端交互,无需过多相互了解;
(5)服务器性能优化:由于前端是静态页面,通过nginx便可获取,服务器主要压力放在了接口上;
2.通用说明
2.1协议
使用http协议,如果有安全方面的担忧,或者数据异常重要可以使用https
2.2编码
统一使用utf8编码
2.3域名
使用独立的api二级域名:
如果已经存在二级域名,建议使用的形式
2.4版本控制
所有的版本号都放入url,并且使用标准版本号格式,前面加小写的v:
/v1
版本号格式说明:通用的为主版本号.次版本号.修订版本号;当然,可以根据自己实际需求调整,针对某些小型项目,直接主版本号,不包含次版本号和修订版本号。版本号从v1开始。
l设计原则
3.1总则
1. 每一个URI代表一种资源;
2. 同一种资源有多种表现形式(xml/json);
3. 所有的操作都是无状态的。
4. 规范统一接口。
5. 返回一致的数据格式。
6. 可缓存(客户端可以缓存响应的内容)。
3.2规范细则
3.2.1 URI规范
1) uri末尾不需要出现斜杠/
2) 在uri中使用斜杠/是表达层级关系的。
3) 在uri中可以使用连接符-, 来提升可读性。
比如 /xx-yy 比 /xx_yy中的可读性更好。
4) 在uri中不允许出现下划线字符_.
5) 在uri中尽量使用小写字符。
6) 在uri中不允许出现文件扩展名. 比如接口为 /xxx/api, 不要写成
/xxx/ 这样的是不合法的。
7) 在uri中使用复数形式。
在RESTful架构中,每个uri代表一种资源,因此uri设计中不能使用动词,只能使用名词,并且名词中也应该尽量使用复数形式。使用者应该使用相应的http动词 GET、POST、PUT、PATCH、DELETE等操作这些资源即可。
那么在我们未使用RESTful规范之前,我们是如下方式来定义接口的,形式是不固定的,并且没有统一的规范。比如如下形式:
/api/getallUsers; // GET请求方式,获取所有的用户信息
/api/getuser/1; // GET请求方式,获取标识为1的用户信息
/api/user/delete/1 // GET、POST 删除标识为1的用户信息
/api/updateUser/1 // POST请求方式 更新标识为1的用户信息
/api/User/add // POST请求方式,添加新的用户
如上我们可以看到,在未使用Restful规范之前,接口形式是不固定的,没有统一的规范,下面我们来看下使用RESTful规范的接口如下,两者之间对比下就可以看到各自的优点了。
/api/users; // GET请求方式 获取所有用户信息
/api/users/1; // GET请求方式 获取标识为1的用户信息
/api/users/1; // DELETE请求方式 删除标识为1的用户信息
/api/users/1; // PATCH请求方式,更新标识为1的用户部分信息
/api/users; // POST请求方式 添加新的用户
如上我们可以看到,增删改成我们都是使用同一个api接口,只是请求的方式 GET(查询)、POST(新增)、DELETE(删除)、PACTH(部分更新)来代表的是增删改查操作的方式。然后开发获取到该请求的header头部信息,就可以知道是什么方式来请求数据的了。
3.2.2请求规范
在很多系统中,几乎只用 GET 和 POST 方法来完成了所有的接口操作;这个行为类似于全用 DIV 来布局。实际上,我们不只有GET 和 POST 可用,在 REST 架构中,有以下几个重要的请求方法:GET,POST,PUT,PATCH,DELETE。这几个方法都可以与对数据的 CRUD 操作对应起来。
【Read】,资源的读取,用 GET 请求;比如:
GET /api/users ( 表示读取用户列表)
GET 应当实现为一个安全方法。用于获取数据而不应该产生副作用。
【Created】,资源的创建,用 POST 方法;
POST 是一个非幂等的方法,多次调用会造成不同效果;
幂等(Idempotent):如果对服务器资源的多次请求与一次请求造成的副作用是一样的的话,那这个请求方法可以被认为是幂等。
比如下面的请求会在服务器上创建一个 name 属性为 'John Snow' 的用户;多次请求就会创建多个这样的用户。
POST /api/users
{
"name": "John Snow"
}
【Update】,资源的更新。用于更新的 HTTP 方法有两个,PUT 和 PATCH。
他们都应当被实现为幂等方法,即多次同样的更新请求应当对服务器产生同样的副作用。
PUT 和 PATCH 有各自不同的使用场景:
PUT 用于更新资源的全部信息,在请求的 body 中需要传入修改后的全部资源主体;
而 PATCH 用于局部更新,在 body 中只需要传入需要改动的资源字段。
设想服务器中有以下用户资源 /api/users/123
{
"id": 123,
"name": "Original",
"age": 20
}
当我们往后台发送更新请求时,PATCH 和 PUT 造成的效果是不一样。
PUT /api/users/123
{
"name": "PUT Update"
}
上述 PUT 请求操作后的内容是:
{
"id": 123,
"name": "PUT Update"
}
可以观察到,资源原有的 age 字段被清除掉了。
而如果改用 PATCH 的话,
PATCH /api/users/123
{
"name": "PATCH Update"
}
更新后的内容是:
{
"id": 123,
"name": "PATCH Update",
"age": 20
}
请求中指定的 name 属性被更新了,而原有的 age 属性则保持不变。
PATCH 的作用在于如果一个资源有很多字段,在进行局部更新时,只需要传入需要修改的字段即可。否则在用 PUT 的情况下,你不得不将整个资源模型全都发送回服务器,造成网络资源的极大浪费。
【Delete】,资源的删除,相应的请求 HTTP 方法就是 DELETE。这个也应当被实现为一个幂等的方法。如:
DELETE /api/users/123
用于删除服务器上 ID 为 123 的资源,多次请求产生副作用都是,是服务器上
ID 为 123 的资源不存在。
安全性和幂等性说明:
1. 安全性:不会改变资源状态,可以理解为只读的;
2. 幂等性:执行1次和执行N次,对资源状态改变的效果是等价的。
.
GET
POST
PUT
DELETE
安全性 幂等性
√
×
×
×
√
×
√
√
安全性和幂等性均不保证反复请求能拿到相同的response。以 DELETE 为例,第一次DELETE返回200表示删除成功,第二次返回404提示资源不存在,这是允许的。
3.2.3相关参数命名规范
空字段
接口遵循“输入宽容,输出严格”原则,输出的数据结构中空字段的值一律为 null
国际化
(1)语言标签
RFC 5646 (BCP 47) 规定的语言标签的格式如下:
language-script-region-variant-extension-privateuse
1. language:这部分使用的是 ISO 639-1, ISO 639-2, ISO 639-3, ISO 639-5
中定义的语言代码,必填
1. 这个部分由 primary-extlang 两个部分构成
2. primary 部分使用 ISO 639-1, ISO 639-2, ISO 639-3, ISO 639-5
中定义的语言代码,优先使用 ISO 639-1 中定义的条目,比如汉语 zh
3. extlang 部分是在某些历史性的兼容性的原因,在需要非常细致地区别 primary 语言的时候使用,使用 ISO 639-3 中定义的三个字母的代码,比如普通话 cmn
4. 虽然 language 可以只写 extlang 省略 primary 部分,但出于兼容性的考虑,还是建议加上 primary 部分
2. script: 这部分使用的是 ISO 15924 (Wikipedia) 中定义的语言代码,比如简体汉字是 zh-Hans ,繁体汉字是 zh-Hant 。
3. region: 这部分使用的是 ISO 3166-1 (Wikipedia) 中定义的地理区域代码,比如 zh-Hans-CN 就是中国大陆使用的简体中文。
4. variant: 用来表示 extlang 的定义里没有包含的方言,具体的使用方法可以参考 RFC 5646 。
5. extension: 用来为自己的应用做一些语言上的额外的扩展,具体的使用方法可以参考 RFC 5646 。
6. privateuse: 用来表示私有协议中约定的一些语言上的区别,具体的使用方法可以参考 RFC 5646 。
其中只有 language 部分是必须的,其他部分都是可选的;不过为了便于编写程序,建议设计接口时约定语言标签的结构,比如统一使用
language-script-region 的形式( zh-Hans-CN, zh-Hant-HK 等等)。
语言标签是大小写不敏感的,但按照惯例,建议 script 部分首字母大写,
region 部分全部大写,其余部分全部小写。
有一点需要注意,任何合法的标签都必须经过 IANA 的认证,已通过认证的标签可以在这个网页查到。此外,网上还有一个非官方的标签搜索引擎。
(2)时区
客户端请求服务器时,如果对时间有特殊要求(如某段时间每天的统计信息),则可以参考 IETF 相关草案 增加请求头 Timezone 。
Timezone: 2016-11-06 23:55:52+08:00;;Asia/Shanghai
具体格式说明:
Timezone: RFC3339 约定的时间格式;POSIX 1003.1 约定的时区字符串;tz
datebase 里的时区名称
客户端最好提供所有字段,如果没有办法提供,则应该使用空字符串
如果客户端请求时没有指定相应的时区,则服务端默认使用最后一次已知时区或者 UTC 时间返回相应数据。
(3)时间格式
时间格式遵循 ISO 8601(Wikipedia) 建议的格式:
日期 2014-07-09
•
•
•
•
•
时间 14:31:22+0800
具体时间 2007-11-06T16:34:41Z
持续时间 P1Y3M5DT6H7M30S (表示在一年三个月五天六小时七分三十秒内)
时间区间 2007-03-01T13:00:00Z/2008-05-11T15:30:00Z 、
2007-03-01T13:00:00Z/P1Y2M10DT2H30M 、
P1Y2M10DT2H30M/2008-05-11T15:30:00Z
重复时间 R3/2004-05-06T13:00:00+08/P0Y6M5DT3H0M0S (表示从2004年5月6日北京时间下午1点起,在半年零5天3小时内,重复3次)
货币名称
货币名称可以参考 ISO 4217(Wikipedia) 中的约定,标准为货币名称规定了三个字母的货币代码,其中的前两个字母是 ISO 3166-1(Wikipedia) 中定义的双字母国家代码,第三个字母通常是货币的首字母。在货币上使用这些代码消除了货币名称(比如 dollar )或符号(比如 $ )的歧义。
3.2.4 Filter过滤规范
如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。为集合提供过滤、排序、选择和分页等功能。下面是一些常见的参数。
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?pageNumber=2&perSize=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
animal_type_id=1:指定筛选条件
参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复。比如,GET
/zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的
注:
①移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。
②为了将总数发给客户端,使用订制的HTTP头: X-Total-Count.
3.2.5返回结果规范
3.2.5.1返回结果为统一的json格式
RESTful规范中的请求应该返回统一的数据格式。对于返回的数据,一般会包含如下字段:
1) code: http响应的状态码。
2) status: 包含文本, 比如:'success'(成功), 'fail'(失败), 'error'(异常)
HTTP状态响应码在500-599之间为 'fail'; 在400-499之间为 'error', 其他一般都为 'success'。 对于响应状态码为 1xx, 2xx, 3xx 这样的可以根据实际情况可要可不要。
当status的值为 'fail' 或 'error'时,需要添加 message 字段,用于显示错误信息。
3) data: 当请求成功的时候, 返回的数据信息。 但是当状态值为 'fail' 或
'error' 时,data仅仅包含错误原因或异常信息等。
返回成功的响应JSON格式一般为如下:
{
"code": 200,
"status": "success",
"data": [{
"userName": "tugenhua",
"age": 31
}]
}
返回失败的响应json格式为如下:
{
"code": 401,
"status": "error",
"message": '用户没有权限',
"data": null
}
3.2.5.2返回结果应该包含状态码
客户端的每一次请求,服务器都必须给出回应。回应包括 HTTP 状态码和数据两部分。
HTTP 状态码就是一个三位数,分成五个类别。
1xx:相关信息
2xx:操作成功
3xx:重定向
4xx:客户端错误
5xx:服务器错误
这五大类总共包含100多种状态码,覆盖了绝大部分可能遇到的情况。每一种状
态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,所以服务器应该返回尽可能精确的状态码。
API 不需要1xx状态码,以下为其他四类状态码的精确含义。
6.2.2 2xx 状态码
200状态码表示操作成功,但是不同的方法可以返回更精确的状态码。
GET: 200 OK
POST: 201 Created
PUT: 200 OK
PATCH: 200 OK
DELETE: 204 No Content
上面代码中,POST返回201状态码,表示生成了新的资源;DELETE返回204状态码,表示资源已经不存在。
此外,202 Accepted状态码表示服务器已经收到请求,但还未进行处理,会在未来再处理,通常用于异步操作。下面是一个例子。
HTTP/1.1 202 Accepted
{
"task": {
"href": "/api/company/job-management/jobs/2130040",
"id": "2130040"
}
}
6.2.3 3xx 状态码
API 用不到301状态码(永久重定向)和302状态码(暂时重定向,307也是这个含义),因为它们可以由应用级别返回,浏览器会直接跳转,API 级别可以不考虑这两种情况。
API 用到的3xx状态码,主要是303 See Other,表示参考另一个 URL。它与302和307的含义一样,也是"暂时重定向",区别在于302和307用于GET请求,而303用于POST、PUT和DELETE请求。收到303以后,浏览器不会自动跳转,而会让用户自己决定下一步怎么办。下面是一个例子。
HTTP/1.1 303 See OtherLocation: /api/orders/12345
6.2.4 4xx 状态码
4xx状态码表示客户端错误,主要有下面几种。
400 Bad Request:服务器不理解客户端的请求,未做任何处理。
401 Unauthorized:用户未提供身份验证凭据,或者没有通过身份验证。
403 Forbidden:用户通过了身份验证,但是不具有访问资源所需的权限。
404 Not Found:所请求的资源不存在,或不可用。
405 Method Not Allowed:用户已经通过身份验证,但是所用的 HTTP 方法不在他的权限之内。
410 Gone:所请求的资源已从这个地址转移,不再可用。
415 Unsupported Media Type:客户端要求的返回格式不支持。比如,API
只能返回 JSON 格式,但是客户端要求返回 XML 格式。
422 Unprocessable Entity :客户端上传的附件无法处理,导致请求失败。
429 Too Many Requests:客户端的请求次数超过限额。
6.2.5 5xx 状态码
5xx状态码表示服务端错误。一般来说,API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了。
500 Internal Server Error:客户端请求有效,服务器处理时发生了意外。
503 Service Unavailable:服务器无法处理请求,一般用于网站维护状态。
3.2.5.3返回结果中提供帮助链接
RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。注:Github就是这么做的
返回体结构:
{"link":
{
"document":" /docs#zoos",
"href":"/zoos",
"title":"List of zoos",
"type":"application/rmat+json"
}
}
4.接口管理
4.1接口归档与维护
(1)接口文档应该建立独立的文件夹保存并定期维护;
(2)接口应该使用类似RAP接口管理工具录入并定期维护。
4.2接口可测试性
接口应该可以通过postman等工具进行测试。
版权声明:本文标题:Restful API接口规范_V1 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1708487923h525605.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论