RESTful API 设计风格

REST介绍

REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序,即表现层状态转换,如果一个架构符合REST原则,我们就称它为Restfull架构。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。简单来说REST是一种系统架构设计风格(而非标准),一种分布式系统的应用层解决方案。
目的:Client和Server端进一步解耦。

其主要包括如下方面:
  1. 资源Resourseces
    rest的名称“表现层状态转换”,省略了主语。“表现层”其实指的是“资源”(Resources)的“表现层”。
    所谓资源,就是网络上一个实体,可以是一段文本,一张图片,一首歌,一种服务,总之就是具体存在的。
    可以用URI统一资源定位符指向它,每种资源对应一个特定的URI,要获取这个资源,访问它的URI即可。
    URI成了每一个资源的地址或独一无二的识别符。
  2. 表现层Representation
    “资源”是一种信息实体,它可以有多种外在表现形式,我们把”资源“具体呈现出来的形式,叫做它的”表现“,
    比如文本可以用txt格式,也可以用HTML、XML、JSON格式表现,甚至可以采用二进制;图片可以用JPG、PNG格式表现。
    URI只代表资源的实体,不代表它的形式,严格地说,有些网址“.html”后缀名是不必要的,因为这个后缀名表示格式,
    属于“表现层”范畴,而URI应该只代表“资源”的位置。它的具体表现形式,应该在HTTP请求的头部信息中用Accept和Content-Type字段指定,
    这2个字段才是对“表现层”的描述。
状态转换(State Transfer)

访问一个网站,就代表了客户端和服务器的交互过程,在这过程中涉及到数据和状态的变化。
互联网通信协议HTTP协议,是无状态协议,这意味着所有状态都保存在服务器端,因此如果客户端想要操作服务器,必须
通过某种手段,让服务器端发生“状态转换”,而这种转换是建立在变现层智商的,所以就是“表现层状态转换”。
客户端用到的手段,只能是HTTP协议,具体来说,就是HTTP协议里,四个表示操作方式的动词:GET、POST、PUT、DELETE
分别对应四种基本操作:GET获取资源,POST新建资源(也可更新资源),PUT用来更新资源,DELETE用来删除资源。
综上,其实RESTful架构就是:
(1)每一个URI代表一种资源;
(2)客户端和服务器之间,传递这种资源的某种表现层;
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现“表现层状态转换”。

RESTful架构设计规范:

  • URI中最好不出现动词
  如显示文章:
    野生写法:/article/show/1/
    正规写法:/article/1/
  如果必须要动词,此时动词需要看作为一个服务,如银行转账,从账户1向账户2汇款500元
  野生写法:POST /accounts/1/transfer/500/to/20
  正规写法:
     POST /transaction HTTP/1.1
     Host: 127.0.0.1
     from=1&to=2&amount=500.00
  • URL中不出现版本号
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo
http://www.example.com/app/2.0/foo  

因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI,版本号可以在HTTP请求头信息
的Accept字段中进行区分。
a.协议API最好使用https;
b.域名 尽量使用专用API域名,如api.baidu.com
c.路径,又称为endpoint,表示API的具体资源,在restful架构中,每个URI
代表一种资源,所以URI中的名词需要和实际功能对应;

HTTP动词

对于资源的具体操作类型,由HTTP动词表示。
常用动词

    GET(select) 获取资源
    POST (create)创建资源
    PUT (update)更新资源(客户端提供改变后的完整资源)
    DELETE (delete)删除资源
    PATCH(update) 更新资源(客户端提供改变的属性)

不常用的HTTP动词:

    HEAD 获取资源的元数据;
    OPTIONS 获取信息,关于资源的那些属性是客户端可以改变的;
过滤信息

如果记录的数量很多,服务器需要分段返回给用户,API应该提供参数,过滤返回结果,如下:

     ?limit=10指定返回的记录数量
     ?offset=10指定反馈记录的开始位置
     ?page=2&per_page=100指定第几页,以及每页的记录数量
     ?sortby=name&order=asc指定返回的结果按那个属性进行排序,以及如何排序
     ?animal_type_id=1 指定筛选条件
状态码

服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。

200 (“OK”) 用于一般性的成功返回, 不可用于请求错误返回
    201 (“Created”) 资源被创建
    202 (“Accepted”) 用于Controller控制类资源异步处理的返回,仅表示请求已经收到。对于耗时比较久的处理,一般用异步处理来完成
    204 (“No Content”) 此状态可能会出现在PUT、POST、DELETE的请求中,一般表示资源存在,但消息体中不会返回任何资源相关的状态或信息。
    301 (“Moved Permanently”) 资源的URI被转移,需要使用新的URI访问
    302 (“Found”) 不推荐使用,此代码在HTTP1.1协议中被303/307替代。我们目前对302的使用和最初HTTP1.0定义的语意是有出入的,应该只有在GET/HEAD方法下,客户端才能根据Location执行自动跳转,而我们目前的客户端基本上是不会判断原请求方法的,无条件的执行临时重定向
    303 (“See Other”) 返回一个资源地址URI的引用,但不强制要求客户端获取该地址的状态(访问该地址)
    304 (“Not Modified”) 有一些类似于204状态,服务器端的资源与客户端最近访问的资源版本一致,并无修改,不返回资源消息体。可以用来降低服务端的压力
    307 (“Temporary Redirect”) 目前URI不能提供当前请求的服务,临时性重定向到另外一个URI。在HTTP1.1中307是用来替代早期HTTP1.0中使用不当的302
    400 (“Bad Request”) 用于客户端一般性错误返回, 在其它4xx错误以外的错误,也可以使用400,具体错误信息可以放在body中
    401 (“Unauthorized”) 在访问一个需要验证的资源时,验证错误
    403 (“Forbidden”) 一般用于非验证性资源访问被禁止,例如对于某些客户端只开放部分API的访问权限,而另外一些API可能无法访问时,可以给予403状态
    404 (“Not Found”) 找不到URI对应的资源
    405 (“Method Not Allowed”) HTTP的方法不支持,例如某些只读资源,可能不支持POST/DELETE。但405的响应header中必须声明该URI所支持的方法
    406 (“Not Acceptable”) 客户端所请求的资源数据格式类型不被支持,例如客户端请求数据格式为application/xml,但服务器端只支持application/json
    409 (“Conflict”) 资源状态冲突,例如客户端尝试删除一个非空的Store资源
    412 (“Precondition Failed”) 用于有条件的操作不被满足时
    415 (“Unsupported Media Type”) 客户所支持的数据类型,服务端无法满足
    500 (“Internal Server Error”) 服务器端的接口错误,此错误于客户端无关
错误处理(Error handling)

如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。

{
    error: "Invalid API key"
}
返回结果:
针对不同的操作,server向用户返回的结果应该符合如下规范
GET 返回资源对象的列表或单个资源
POST 返回新生的资源对象
PUT 返回完整的资源对象
PATCH 返回完整的资源对象
DELETE 返回空文档,并告知结果   
Hypermedia API

RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
比如,当用户向api.example.com的根目录发出请求,会得到这样一个文档。

{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}

上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。

Hypermedia API的设计被称为HATEOAS。Github的API就是这种设计,访问api.github.com会得到一个所有可用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"
}

上面代码表示,服务器给出了提示信息,以及文档的网址。

其他

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

web应用模式分两种:
  1. 前后端不分离:
    在前后端不分离模式中,前端页面看到的效果都是后端页面渲染或者重定向,也就是后端控制前端的展示,前后端耦合度很高,这种模式比较适合纯网页应用,但是在目前移动互联网时代,可能对接的有APP,各种小程序等,可能并不需要后端返回一个HTML网页,而仅仅需要数据本身,所以后端原本返回网页的接口不适用APP应用。

    这个可以看我之前写的DJango博客就可以知道,每次返回时都是使用render 或者redirect来返回的,需要带上HTML页面和参数。

  2. 前后端分离:
    在前后端分离模式中,后端只要返回前端所需要的数据,不需要渲染HTML页面,不再控制前端效果,只要前端用户看到
    什么效果,从后端请求的数据如何加载到前端中,由前端自己决定,无论哪种前端所需要数据基本相同,后端仅需开发一套
    逻辑对外提供数据即可,在前后端分离的应用模式中,前端与后端耦合度相对较低。

在前后端分离的应用模式中,我们通常将后端开发的每一视图都成为一个接口,或者API,前端通过访问接口来对数据进行增删改查。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 去年有段时间得空,就把谷歌GAE的API权威指南看了一遍,收获颇丰,特别是在自己几乎独立开发了公司的云数据中心之后...
    骑单车的勋爵阅读 20,431评论 0 41
  • 前言:最近两年很火爆的网络框架Retrofit,使用它的时候,查看文档会告诉你,要求后台的服务器哥们必须符合RES...
    AWeiLoveAndroid阅读 94,807评论 10 93
  • 一、什么是API? API(Application Programming Interface,应用程序编程接口)...
    Fairy_妍阅读 62,536评论 2 42
  • 一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式。”但是在要求详细讲述它所提出的各个约束,以及如...
    时待吾阅读 3,408评论 0 19
  • 朦胧中,我又回到外婆家的木楼了,外婆穿着藏蓝色围裙,坐在窗户旁边缝一件扯破的外衫,看不清针脚只好拿起来离眼睛很近很...
    离魂吟魄阅读 384评论 6 3