笔记《细说API – 重新认识RESTful》

阅读“细说API – 重新认识RESTful”的笔记。

原文:https://insights.thoughtworks.cn/api-restful/

API在概念上和语言无关,理论上具有网络操作能力的所有编程语言都可以提供API服务。Java、PHP、Node甚至C都可以实现web API,都是通过响应HTTP请求并构造HTTP包来完成的,但是内部实现原理不同。

API在概念上和JSON和XML等媒体类型无关,JSON和XML只是一种传输或媒体格式,便于计算机解析和读取数据,因此都有一个共同特点就是具有几个基本数据类型,同时提供了嵌套和列表的数据表达方式。

API设计的目的是为了让程序可读,应当遵从简单、易用、无状态等特性,这也是为什么Restful风格流行的原因。

RESTful

REST(英文:Representational State Transfer,简称REST),RESTful是一种对基于HTTP的应用设计风格,只是提供了一组设计原则和约束条件,而不是一种标准。网络上有大量对RESTful风格的解读,简单来说Restful定义URI和HTTP状态码,让你的API设计变得更简洁、清晰和富有层次,对缓存等实现更有帮助。RESTful不是灵丹妙药,也不是银弹。

RESTful的本质是基于HTTP协议对资源的增删改查操作做出定义。理解HTTP协议非常简单,HTTP是通过网络socket发送一段字符串,这个字符串由键值对组成的header部分和纯文本的body部分组成。Url、Cookie、Method都在header中。

几个典型的RESTful API场景:

RESTful的几个注意点:

  • URL只是表达被操作的资源位置,因此不应该使用动词,且注意单复数区分

  • 除了POST和DELETE之外,其他的操作需要幂等的,例如对数据多次更新应该返回同样的内容

  • 设计风格没有对错之分,RESTful一种设计风格,与此对应的还有RPC甚至自定义的风格

  • RESTful和语言、传输格式无关

  • 无状态,HTTP设计本来就是没有状态的,之所以看起来有状态因为我们浏览器使用了Cookies,每次请求都会把Session ID(可以看做身份标识)传递到headers中。关于RESTful风格下怎么做用户身份认证我们会在后面讲到

  • RESTful没有定义body中内容传输的格式,有另外的规范来描述怎么设计body的数据结构,网络上有些文章对RESTful的范围理解有差异

URL中都是名词,所有的操作“增删改查”通过请求方式来定义,分别对应:post,delete,patch,get

JSON API

MIME 类型

JSON API数据格式已经被IANA机构接受了注册,因此必须使用application/vnd.api+json类型。客户端请求头中Content-Type应该为application/vnd.api+json,并且在Accept中也必须包含application/vnd.api+json。如果指定错误服务器应该返回415或406状态码。

好像一般都是application/json?vnd.api是什么鬼?

JSON文档结构

在顶级节点使用data、errors、meta,来描述数据、错误信息、元信息,注意data和errors应该互斥,不能再一个文档中同时存在,meta在项目实际上用的很少,只有特别情况才需要用到,比如返回服务器的一些信息。

data属性

一个典型的data的对象格式,我们的有效信息一般都放在attributes中。

应该是object的对象格式

  • id显而易见为唯一标识,可以为数字也可以为hash字符串,取决于后端实现
  • type 描述数据的类型,可以对应为数据模型的类名
  • attributes 代表资源的具体数据
  • relationships、links为可选属性,用来放置关联数据和资源地址等数据

errors属性

这里的errors和data有一点不同,一般来说返回值中errors作为列表存在,因为针对每个资源可能出现多个错误信息。最典型的例子为,我们请求的对象中某些字段不符合验证要求,这里需要返回验证信息,但是HTTP状态码会使用一个通用的401,然后把具体的验证信息在errors给出来。

Errors返回一个列表?请求的每个字段都要验证,这应该取决于产品,一个字段验证失败就不该继续下去。401是unauthorized错误,请求参数错误应该是400 Bad request。

常用的返回码

查看HTTP协议文档,文档上有几十个状态码让你无从下手,在真实环境中用到的并不多。

200 OK

200是一个最常用的状态码用来表示请求成功,例如GET请求到某一个资源,或者更新、删除某资源。 需要注意的是使用POST创建资源应该返回201表示数据被创建

201 Created

如果客户端发起一个POST请求,在RESTful部分我们提到,POST为创建资源,如果服务器处理成功应该返回一个创建成功的标志,在HTTP协议中,201为新建成功的状态。文档规定,服务器必须在data中返回id和type。 下面是一个HTTP的返回例子:

401 Unauthorized

如果服务器在检查用户输入的时候,需要传入的参数不能满足条件,服务器可以给出401错误,标记客户端错误,需要客户端自查。

400 Bad request?

415 Unsupported Media Type

当服务器媒体类型Content-Type和Accept指定错误的时候,应该返回415。

403 Forbidden

当客户端访问未授权的资源时,服务器应该返回403要求用户授权信息。

404 Not Found

这个太常见了,当指定资源找不到时服务器应当返回404。

500 Internal Server Error

当服务器发生任何内部错误时,应当返回500,并给出errors字段,必要的时候需要返回错误的code,便于查错。一般来说,500错误是为了区分4XX错误,包括任何服务器内部技术或者业务异常都应该返回500。

HATEOAS

Hypermedia As The Engine Of Application State,中文叫做超媒体应用程序状态的引擎,实际上HATEOAS算作被JSON API定义了的一部分,HATEOAS思想是既然Restful是利用HTTP协议来进行增删改查,那我们怎么在没有文档的情况下找到这些资源的地址呢,一种可行的办法就是在API的返回体里面加入导航信息,也就是links。这样就像HTML中的A标签实现了超文本文档一样,实现了超链接JSON文档。

好像twitter的API就是这么返回的。

如果在某个系统中产品和订单是一对多的关系,那我们给产品的返回值可以定义为:

从返回中我们能得到links中product的的资源地址,同时也能得到orders的地址,这样我们不需要客户端自己拼装地址,就能够得到请求orders的地址。如果我们严格按照HATEOAS开发,客户端只需要在配置文件中定义一个入口地址就能够完成所有操作,在资源地址发生变化的时候也能自动适配。

就是请求某接口后,通过返回结果就能知道后续相关的接口,无需文档。


欢迎阅读本篇文章,如有兴趣可以关注博主公众号哦: