RESTful API风格

数据大
• 阅读 7193

任何对外提供服务的应用都绕不开API的发布,你的API可能是这个样子:

www.baidu.com/api/v1/getUsername?id=1
或者
www.baidu.com/app/index.php?r=info/user/getUsername&id=1

如果答案是YES,那么用句很潮的话,我们可以说你的API很不RESTful

API风格

首先要说,不管你的API属于哪种风格,只要能够满足工作需要,就足够了。API格式并不存在绝对的标准,只存在不同的设计风格。

API设计包含两部分:请求和响应。
请求包含:请求URL、请求方法、请求头部信息等。
响应包含:响应体和响应头部信息。

一个请求URL的组成:

https://www.baidu.com:443/app/index.php?r=info/user/getUsername&id=1#tag
# 请求方法:GET
# 请求协议:protocal: https
# 请求端口:port: 443
# 请求域名:host: www.baidu.com
# 请求路径:pathname: /app/index.php
# 查询字符串:search: r=info/user/getUsername&id=1
# 页面书签:hash: #tag

根据URL组成部分:请求方法、请求路径和查询字符串,我们有几种常见的API风格。比如当删除id=1的作者编写的类别为2的所有文章时:

# 纯请求路径
GET www.baidu.com/articles/delete/authors/1/categories/2
# 一级使用路径,二级以后使用查询字符串
GET www.baidu.com/articles/delete/author/1?category=2
# 纯查询字符串
GET www.baidu.com/deleteArticles?author=1&category=2
# RESTful风格
DELETE www.baidu.com/articles?author=1&category=2

前面三种都是GET请求,主要的区别在于多个查询条件时怎么传递查询字符串,有的通过使用解析路径,有的通过解析传参,有的两者混用。同时在描述API功能时,可以使用article/delete,也可以使用deleteArticles

而第四种RESTful API最大的区别在于行为动词DELETE的位置,不在url里,而在请求方法中。

RESTful设计风格

REST(Representational State Transfer 表现层状态转移)是一种软件架构风格、设计风格,而不是标准。主要用于客户端和服务端的API交互,它的优势在于更简洁、清晰、可读性强。

REST的主要特点是:

  1. 客户端和服务端是无状态的,任意请求都包含了处理需要的所有信息,同时服务端的变更对客户端是透明的。
  2. 资源用URI(Universal Resource Identifier 通用资源标识)来表示,通过请求方法来指明操作类型:GET/POST/PUT/DELETE

无状态是最重要的特性,大部分的Client-Server,Brower-Server也都能很好的支持。第2点则是我们需要去关注的。

REST URL

表现层状态转移(REST)是一个大的概念,也不好理解,我的理解就是在URL的定义上能够清楚的表示其请求含义。它的核心思路就是动词+宾语:

DELETE www.baidu.com/api/v1/articles?author=1&category=2
# 动词 DELETE,表示要进行的操作是删除,即状态转移
# 宾语 articles,表示文章这种资源URI,推荐用复数,即表现层
# 定语 author=1&category=2,表示具体是什么资源
# 版本 api/v1,这个能够帮助我们更好的进行版本的升级,同时不影响原有的请求

我们用articles来指明资源类型,用author=1&category=2来在确定具体的资源,用GET/POST/PUT/DELETE来指明要进行的增删改查操作。

这种风格相比于/api/deleteArticles,声明的方法数量只有1/4,各个接口之间的风格也更加统一,调用起来更加清晰。

同时这种方法能够保证浏览器常规能访问的到的GET请求对资源来说是安全的。比如别人给我们发送了一个链接:/deleteArticle?id=1,我们绝对不会希望随便点击一下就会跳转到浏览器访问,然后误删了这个资源。

响应状态码

除了请求URL有要求,在响应时也有一些要求。我们知道状态码有:

  • 1xx: 请求相关信息
  • 2xx: 操作成功
  • 3xx: 重定向
  • 4xx: 客户端错误
  • 5xx: 服务端错误

所有的状态码 共有100多种,涵盖了绝大多数常见的网络场景,而且是网络通用的定义规范和解释,因此我们应该尽可能使用精确的状态码。

当前有一些不太恰当的做法是即便请求出错,依然使用200状态码,转而将错误信息包含在响应体中,或者响应使用纯文本导致无法和正常数据一样标准化解析,如:

httpCode: 200
response: {
    status: 1,
    msg: '请求无权限'
}
# 或:
httpCode: 200
response: '请求无权限'

但我们其实可以用更精确的状态码403代表权限不足,所以合适的响应结果应该是:

# 异常时
httpCode: 403,
httpErrorMsg: '请求无权限'
# 正常时:
httpCode: 200,
response: {
    status: 0,
    msg: '',
    data: []
}

总结

RESTful是一种API设计风格,并不是一种强制规范和标准,它的特点在于请求和响应都简洁清晰,可读性强。

我们主要关注几点:

  1. 无状态
  2. 请求URL = 动作(GET/POST/PUT/DELETE)+ 资源
  3. 响应使用精确的状态码和JSON格式数据

参考资料

  1. RESTful API 最佳实践: http://www.ruanyifeng.com/blo...
  2. RESTful: https://baike.baidu.com/item/...
  3. 怎样用通俗的语言解释REST,以及RESTful?: https://www.zhihu.com/questio...
  4. Status Code Definitions: https://www.w3.org/Protocols/...
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
3年前
List的Select 和Select().tolist()
List<PersondelpnewList<Person{newPerson{Id1,Name"小明1",Age11,Sign0},newPerson{Id2,Name"小明2",Age12,
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这