REST API

问题

​ 最近在项目中单独负责一个组件的开发,这个组件的输出是通过api的方式输出。虽然接口不多,也就15个api左右,但是越往后写就越感觉不太对劲。在和同时联调沟通的时候也发现了很多的问题。一直都想要好好总结下,趁着今天下班早有时间就反思一下吧。

​ 我总结了目前我发现的这个项目的一些问题

  1. API风格混乱
  2. API设计不好,不能更加友好的支持API升级
  3. 返回状态码的滥用
  4. 接口返回数据结构不一致
  5. 接口太碎片化
  6. 由于是go语言写的,基本每个接口都用到了defer

​ 站在现在的角度来看,其实这个组件的api是想当失败,可以说是不忍直视。当然有一小部分原因是项目紧急的缘故。但是不可否认的是主要还是因为我的原因才导致了这样的结果。所以我决定新开一个分支,在下班时间重构这个组件的API。虽然这个新重构后的API上线的可能性不大(因为好多项目已经集成了该组件,改动起来花费的资源很大)。但也算是对自己的一个交代吧。

​ 自己算了算之前也参与过三个项目相关业务API的开发。但是都是在别人的基础上进行开发,看到别人没有过多的去关注这些东西。所以自己也就自然而然的没有过多的去思考,就顺着那种思路开发下去了。总之该来的还是会来的。这次的更改可能对这个组件起不了多大的作用。但是希望能够给自己敲响警钟,避免下次出现同样的问题。

REST API的一些规范

实现REST API标准比较好的例子就是https://developer.github.com/v3/#current-version

  1. 在API中指定版本

    一种是可以放在url中,另外一种就是将版本放在HTTP请求头中。还是放在url中比较方便

  2. url中不能出现动词,名词也应该使用复数

    因为RESTful面向的都是资源,所以在url中不能包含动词。

  3. 对资源的操作都是用HTTP动词

    常用到的HTTP动词

    动词 作用 返回结果
    GET 从服务器获取资源 获取单个资源对象或者资源对象数组
    POST 新建资源 新生成的资源对象
    PUT 更新整个对象,需要客户端提供完整的对象 更新后的资源对象
    PATCH 更新对象的某个部分,需要客户端提供更新的部分 更新后的资源对象
    DELETE 删除整个对象 返回一个空文档

一些例子

```bash
GET /zoos:列出所有动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
```
  1. 过滤信息

    一些例子

    ?limit=10:指定返回记录的数量
    ?offset=10:指定返回记录的开始位置。
    ?page=2&per_page=100:指定第几页,以及每页的记录数。
    ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
    ?animal_type_id=1:指定筛选条件
    

    其中 GET /zoo/ID/animals 与 GET /animals?zoo=ID都是REST的风格。一直都以为只有第一种才是

  2. 状态码

    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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    
  3. 返回结果

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

    个人认为这个在公司这种项目中是可以省略的,毕竟公司项目中的API都是面向特定的用户,而且有安全限制,不会把所有的API都暴露出去。

  5. API的用户认证使用OAuth 2.0框架

    这个单独拿出来写一写

其实RESTful规范也不多,在实际中除非有特殊情况,都要尽量的遵守规范。

参考链接:

http://www.ruanyifeng.com/blog/2014/05/restful_api.html

https://docs.microsoft.com/zh-cn/azure/architecture/best-practices/api-design