zhangsanshi / issue-blog

It's a blog rather than issue
0 stars 0 forks source link

API 书写规范 #23

Open zhangsanshi opened 7 years ago

zhangsanshi commented 7 years ago

API 书写规范

如果没什么必要,请不要破坏 约定

ok,从一个例子说起

请求阶段

{
  url: '/api/person/:id',
  describe: '一个清晰的描述同样很重要,用来干嘛的,和哪些页面相关',
  method: 'post',
  params: {
    type: 'a',
    type2: 'b',
  },
  data: {
    sex: 1,
    age: 12,
    ageStr: '12',
    birthday: 1481441364804,
    child: [],
    attr: {},
    attrStr: '{}'
  },
}

解析

url 是链接的主体部分,:id 代表了这个值是动态获取

method 是请求的方法,一般是 getpostputdelete等等

paramsurlsearch 部分,拼接到 url 后, 即: /api/person/:id?type=a&type2=b

data 是需要发送的参数,这部分是放在请求 body 中的,这里也有需要注意的点:

  1. attr 的值是一个 JSON 对象,如果你需要的是一个序列化的 JSON 对象,请写成 attrStr 对应的形式, 前端的处理方案是 JSON.stringify({}),对于 Array 同理

特别说明

原则上,后端如果从 url 部分读取了 id, 就不应该从 paramsdata 再次读取id, 而事实上我遇到过,遇到的情况是会从 paramid,读不到 id 去拿列表的数据,读到 id 就去干别的事情。 这说明了啥,说明了一个 API 可以干两件不同的事情,所以可不可以这么推断,所有的 API 都可以通过一个链接解决,只需要给不同的 params,这种设计表面上是有了所谓了灵活性,实际上是不能再糟糕的设计了

其他方面

  1. Content-Type

    目前是application/x-www-form-urlencoded;charset=utf-8, 默认的 form (enctype)表单的值也是这个,

    对于 form 有文件的,需要是这个 multipart/form-data

    对于越来越多的前端框架来说,默认的是这个 application/json,但是后端目前不能解析,需要手动配置 header, 改成第一种,同时手动拼接 data

    还有一种,参见链接

    这里多写一点东西

    • application/x-www-form-urlencoded;charset=utf-8 类型, 发送到服务端的格式是 x=1&b=2&c[]=1&c[]=2 或者 x=1&b=2&c[0]=1&c[1]=2

    • multipart/form-data

      
      ------WebKitFormBoundaryMb9nnUlXLKUn49G9
      Content-Disposition: form-data; name="a"

    1 ------WebKitFormBoundaryMb9nnUlXLKUn49G9 Content-Disposition: form-data; name="b"

    2 ------WebKitFormBoundaryMb9nnUlXLKUn49G9--

    同时 header 部分是

    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryMb9nnUlXLKUn49G9

  2. 下载链接

    这个也有值得说的地方

    有时候下载链接仅仅是一个 a 标签跳转即可,但需要注意的是错误处理方面

    有时候是返回数据,让前端拼接下载,这个时候需要在 data 里给足详情

数据返回阶段

目前已有约定

{
    data: [],   // 根据具体业务需求,返回数据
    code: 200, // 返回状态码
    message: ''// 返回文本提示信息
}

code 码

200 正常请求
403 未登录
401 权限不足
406 业务级错误
409 参数错误

解析

  1. code 这个作用很明显,不理解的人仅仅会得知是一个数字,自己人会知道代表的含义,同时 message 作为补充用来提醒用户

  2. message 返回信息

  3. data 返回数据

特别说明

上面三个即可解决绝大部分的问题,但是data 这里未规定,但是有一些东西需要补充的,这里和前端尤为相关, 来一个例子

{
  time1: '1481441364',
  child: ['a', 'b'],
  childObj: {1: 'a', 2: 'b'},
}

childArraychildObj 是对象, 在 PHP 里,貌似都是 Array,但需要分清楚 childchildObj 的区别,尤其是对于 key 是数字的情况

time1unix 时间戳,这个属性的问题有两个:

  1. unix 时间戳 是按秒算的,首先需要明确告知前端 time1unix 时间戳,在交流这个数据的时候,什么时候用 unix 时间戳,什么时候用其他格式的,同时做好约定,不要这个接口我用这种类型的,下个接口就换了,或者过段时间就忘了。。。

  2. 时间戳是 Number 类型的吧,事实上我遇到过 'false''0' 类型的返回值,处理起来很繁琐,本来可以很简单的解决的问题,导致写了一大堆代码,有些项目采用了 typescript,因为有类型约束,导致问题更严重,虽然不知道在 js 中,这些约束报错不。。。

  3. ageNumber 类型的,倾向于写成 Number 类型,而不是 ageStr,在 js

    (!!'0') === true
    (!!0) === false

其他方面

  1. 希望后端有个通用的处理流程,我感觉很多数据还是手工转的,一不注意,写出的代码就不符合约定了,比如出来个 'false' 之类的。

  2. 接口尽量定义的规范一些。。。虽然有时间不规范很省事啊

  3. 希望能统一交流语言吧,很多人还描述不清自己想要什么数据,写又写不出来。。。不如现在就用此做个规范吧。

讨论

  1. 前端接手 API 的时候,其实已经比较迟了,而且做页面会遇到各种问题,后端可不可先写文档,然后再编程,前端遇到问题,可以及时更改思路?

  2. 接上一个,后端的文档是 JSON 格式,后面可以实现一个 mock服务器,来生成数据,方便前端测试?

  3. API 文档的保存问题,聊天记录里?PM 里?wiki里?还是专门写一个服务管理?

  4. API 文档能否生成的问题,毕竟手写还是有点累的。

zhangsanshi commented 7 years ago

对于上面的 code 码,最近有了新的看法,我们过段时间是否看得懂 code 码是什么,所以, code 码应该是两个对象。 第一个对象:

{
   OK: '200',
   PARAMS_ERROR: '409'
}

这个对象是在程序中使用,这里用英文表示错误,对应的是错误码。 第二个:

{
 200: '正常'
}

这里可以放在结果中返回,也可以留给前端查找,甚至可以在线下暴露出服务,这样的话,后端定义好错误类型,前端可以很方便的知道是什么错误,告知后端对应的状态码。 后端代码中使用的时候就是CODE.OK CODE.PARAMS_ERROR,这样代码看起来就很清晰了