RESTful架构原则与规范

版权声明:欢迎转载,转载请标明来源 https://blog.csdn.net/weixin_41973131/article/details/84875332

前言

欢迎关注驿外残香 | HC的博客
RESTful架构作为当前最流行的互联网架构,得到了越来越多的互联网公司的青睐。一个结构清晰,符合规范,易于拓展的架构原则能够使得团队的开发更加规范化,且作为一个API也更加容易被团队成员或者大众开发者使用。

内涵

REST:(Resource) REpresentational State Transfer

翻译为:表现层状态转化

@Ivony老师对此概括为:URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作。

  • Resource:一个资源就是网络上的一个实体,可以是一份文档、一张图片、一种服务等等,资源是实体的概念性映射,而不是实体本身;相当于图片是资源,而放在本机中确切有的一张图片则是资源实体。每一个URI对应一个网络资源,通过访问特定的URI来操作特定的资源。

  • Transfer:资源在网络中以某种表现形式进行状态转移

  • Repersentational:表现层,代表资源的某种表现形式,比如JSON,XML,JPEG等

  • State Transfer:状态转化又称转态,通过HTTP动词实现。

    • “互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在客户端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。”

tip:资源不仅仅与数据库表产生联系,并且也可以指代某项存储数据或者服务。比如用户认证授权时即是对Session资源进行操作,进行银行转账时可以视为对transaction进行操作。

原则

  • Server提供的RESTful API中,URL只使用名词来指定资源(推荐使用复数),原则上不使用动词。
  • 用HTTP协议里的动词来实现资源的CRUD
    • GET:获取资源
    • POST:新建资源
    • PUT:更新资源(客户端提供改变后的资源)
    • PATCH:更新资源(客户端提供改变的资源)
    • DELETE:删除资源
    • HEAD:获取资源的元数据(不常用)
    • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的(不常用)
    • 有些客户端只能使用GETPOST这两种方法,服务器必须接受POST模拟其他三种方法。此时客户端发出的HTTP请求,要加上X-HTTP-Method-Override属性覆盖POST
  • 使用HTTP Status Code 传递Server的状态信息
  • 保证HEAD和GET方法是安全的,不会对资源状态有所改变
  • 资源的地址推荐采用嵌套结构
  • 文档跟API一定同步修改,甚至需要先修改文档

解析URL

格式:协议://域名/版本/路径?过滤信息

  • 协议:一般使用HTTPS协议
  • 版本:应将API的版本号放入URL,为了能够兼容旧版本的API
  • 路径:又叫终点,一般来说,路径所用的名词往往跟数据库的表格名对应
  • 过滤信息:如果记录数量很多,API应该提供参数过滤返回结果。多级URL最好除了第一级其他级别都用查询字符串表达
    • ?limit=10:指定返回记录的数量
    • ?offset=10:指定返回记录的开始位置
    • ?page=2&per_page=100:指定第几页,以及每页的记录数
    • ?sortby=name&order=asc:指定返回结果按照哪个属性排序以及排序顺序
    • ?animal_type_id=1:设置筛选条件

服务器返回信息

  • 状态码(Status Code):服务器应向用户返回的状态码和提示信息

    • 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    • 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    • 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    • 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] 当创建一个对象时,发生一个验证错误。
    • 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
  • 错误处理(Error handling):如果状态码是4XX,应该向用户返回出错信息

    {
    	"error":"Invalid API key"    
    }
    
  • 返回结果(Response):API返回的数据格式应该是一个JSON对象,并且发生错误时不要返回200状态码。针对不同操作,服务器向用户返回的结果应该符合以下规范

    • GET /collection:返回资源对象的列表(数组)
    • GET /collection/resource:返回单个资源对象
    • POST /collection:返回新生成的资源对象
    • PUT /collection/resource:返回完整的资源对象
    • PATCH /collection/resource:返回完整的资源对象
    • DELETE /collection/resource:返回一个空文档

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"
}

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

注意事项:

理解RESTful架构 --阮一峰一文中指出:

另一个设计误区,就是在URI中加入版本号。

因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI。版本号可以在HTTP请求头信息的Accept字段中进行区分(参见Versioning REST Services):

RESTful API 最佳实践 --阮一峰一文则指出:

应该将API的版本号放入URL。

https://api.example.com/v1/

另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。

前者为2011年版本,后者为2014年版本。

可能是每个时间段的现状或理解不同而造成的差异。

且目前GitHub API已采用将API的版本号放入URL

故应以后者为准。

存在问题:

  1. 在复杂的系统上,复杂的业务要操作很多种资源的时候URL应该如何体现?当一个资源操作涉及多个数据库表的时候该如何设计URL?

    如果有对该问题有思路的欢迎留言评论。

参考:

RESTful API 设计指南

优秀REST风格 API的设计原则

知乎上覃超的回答

RESTful API 最佳实践 --阮一峰

理解RESTful架构 --阮一峰

猜你喜欢

转载自blog.csdn.net/weixin_41973131/article/details/84875332