后台API服务的宏图思虑

自小编在《写在最前》里说过,后台API的文书档案至关心珍惜要。然而,文书档案只是外在表现格局,设计才是当真的灵魂。作者在那篇博文首要介绍的就是自个儿在后台开辟进度中,设计API时的怀恋。作者只说她是思考,因为众多东西不见得是天经地义的,更不会是相对了。

 

率先,我要证明的是,作者最首若是参照上面那篇作品(以下简称最棒实行)里的观点:

 

  http://www.cnblogs.com/yuzhongwusan/p/3152526.html  [标题: RESTful
API 设计最棒实施]

 

那是壹篇翻译过来的博文,原著地址是:

 

  http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

 

上面是本人依照那篇文章的片段互补;也正是说,读者得先读1读那一篇:

 

1.
作者的接口设计中并从未形如/tickets/12/messages/伍的接口,因为在自身的财富管理中,id是大局唯一的,不需求利用1二-五这么的1道id。笔者的代表方案是:/ticket_messages/112255

 

2.
就如最好实行博文里的所提的那样,作者的List接口中也利用了诸如sort、分页等体制,寻觅那块也运用了斐然的q参数。小编还加入了include和with_total,
just_total等控制。

 

include:
那是消除优良的N+一难题的方案。例如大家定义Ticket财富,同时每一个Ticket能源绑定到(belongs_to)贰个User能源。通过调用接口/tickets能够访问Ticket列表。此时只会回到Ticket的新闻,而不会安置Ticket的全体者User的新闻,只是嵌入1个user的id字段,如下:

[
    {
         ...ticket1...,
        user_id: 1
    },

    {
         ...ticket2...,
        user_id: 2
    },
    ...
]

这边会重回N个Ticket,调用了三遍接口。别的,固然想要进一步精通各类Ticket的User的音信,需求调用N次/users/:user_id接口,如下:

  /users/1

  /users/2

    …

  /users/N

那就是家弦户诵的N+1难点。那样不仅浪费带宽,而且也说不定会潜移默化数据库查询成效。更要紧的是,这确实扩大了前者的工作量。使用include参数的格局是在接口调用中扬言要包括的子能源,通过贰回接口调用完结N+1此接口调用的效果。调用/tickets?include=user,重临的样式是:

[
    {
        ...ticket1...,
        user: {
            id: 1,
            ...user1...
        }
    },
    {
        ...ticket2...,
        user: {
            id: 2,
            ...user2...
        }
    },
    ...
]

以此正是大家后台API如今的计划款式。当中include字段能够安顿包括多少个有关能源,用逗号分隔就能够。

再作证以下这些布署的贰个小瑕疵。便是出现不等同的意况。借使回到的结果存款和储蓄在tickets中,那么首先个Ticket是tickets[0],那么未有设置include参数时,取user的id是tickets[0].user_id;当设置include=user时,取user的id是tickets[0].user.id。在取Ticket的User的id时,出现了调用的差别等,倒霉。

很对不起,我竟然未有察觉到《最好实施》里曾经有个类似字段embed了。有些概念讲重复了。

 

with_total,
just_total
:壹般的话,作者在统一筹划”列出…”的API接口时,仅仅重返的是你须要的数组。那里面包蕴能够协作的能源的总额音信。最常用的事态是做分页的时候,这么些总的数量新闻方可导出总页数,进而判断当前的请求页是不是是最后1页,从而在那儿亦可很好地灰选下1页开关。作者一同先不想增多这么的功用,因为本人觉着用瀑布流刷数据是更酷的主意,那时候通过重返三个空数组提示未有越来越诸多据就可以。仅仅再次回到一个数组,便于前端开箱即用再次回到数据,也终于叁个十分小便利吧。最终照旧增添了这几个成效,毕竟全部瀑布流的艺术并不能够完全适应前端的筹划,而且有时确实必要明白一个音信的关怀总的数量那样的音信。这时候增加多个调整参数with_toal,
just_total,它们的应用是排斥的。它们是调节字段,不用突显赋值为true,只要那个字段存在就能够。

 

例如/tickets?with_total, /tickets?with_total=true,
/tickets?with_total=false都以回来如下结果(总量存款和储蓄在total字段中,数据数组存款和储蓄在list字段中):

{
    total: 1234,
    list: [
        ...
    ]    
}

just_total仅仅重返总量音讯,抹去了list字段,今年就不要做壹些分页调控了,因为没意义。即:

{
    total: 1234
}

 

3. 筛选调节

 

所谓筛选,是指通过规范查询再次来到相配的财富。例如只回去address在’新加坡‘的User财富。《最棒实行》中是用3个近似’address=北京’那样的参数来调控原则查询。小编尚未运用那种分散的法子,而是把具备的询问相关规范都定义在cond那三个参数中。在地点的例证中,大约应该是cond={address:
‘新加坡’}。注意那里自身用了javascript语法已压缩输入,您能够把它当作等效的JSON语法。也便是说,cond参数的项目应该是二个指标,在中间定义全数的询问逻辑。更具体地说,cond参数应该是一密密麻麻的键值对,键是要布局的字段名,如address,值是相配的规则,如设置成’北京’,就是说那个字段要统统等于’北京’那几个字符串。例如在’address=北京&age=1八’那样的多字段相配的情形下,用cond语法就应该是cond={address:
‘新加坡’, age:
1八}。现在在自己的项目里作者的确也只做了这一个,诸如其余的age>1八,age<18都尚未达成。幸而前天项目规模非常小,还没用到这么些。

 

将全体查询调节封装在3个cond参数中有益接口的统1性,也便于小编联合达成。

 

唯独,接下去自身首要要说的是,那其中有坑。此坑在于,GET方法(上边所说的那3个是用来HTTP
GET
METHOD)中,未有请求体,也就不能够钦命Content-Type=application/json。在cond中定义一个键值对聚集,用json是很自然的主意,可是不可能传递json。GET方法中借使要传送参数,只好叠加在url中的query
string个中。小编不鲜明能还是无法传递json格式的数据,但自笔者实在并未有得逞过。壹般的话,query
string的格式是田野同志一=value一&田野同志二=value2&…那样的款型。有二个不成文的约定,当传递数组时,使用array[]=v1&array[]=v二&…如此的方式,当传递对象,例如地点的cond中的对象,格局是cond[address]=上海&cond[age]=1八.
这么些约定不是放之所在皆准。项目标前端选拔的是AngularJS,要是调用Resource的法未时,将上面的目的作为请求参数(小编以为那样对前者来讲是最自然的),会让后端收到的query
string那段卓殊地不健康:

{
   ..., //首先可以有分页,排序等参数
     cond: {
         address: '上海',
         age: 18
     }   
}

末段前端接纳了一种不自然的调用情势,是底下:

{
   ..., //首先可以有分页,排序等参数
     'cond[address]': '上海',
     'cond[age]': 18
}

自个儿在考虑上面两种缓解方案:

将cond参数的对象转化成JSON字符串,那样

{   ..., //首先可以有分页,排序等参数
     cond: JSON.parse({
         address: '上海',
         age: 18
     })
}

照旧利用POST方法来询问数据,接口是POST /users/query
查询条件得以用json格式写在请求体中。

前1种形式并不可能让笔者乐意,后一种落成起来相比麻烦。要处理GET /users和POST
/users/query两种情景。

 

4. 错误重临

 

笔者的陈设性里是富含出错情况的。当须要回到用户四个弄错音信的时候,首先会重返二个状态码。就好像《最棒实行》里面说的,有个别是本人确定用到的,它们是:

  • 400 Bad Request (错误的央浼) – 请求是难堪的, 比如不可能解析请求体
  • 401 Unauthorized (未授权) –
    当未有提供或提供了没用认证细节时。即便从浏览器采取API,也得以用来触发弹出贰遍验证请求
  • 40三 Forbidden (禁止访问) – 当认证成功可是认证用户无权访问该财富时
  • 40四 Not Found (未找到) – 当三个不设有的财富被呼吁时
  • 422 Unprocessable Entity (不能够处理的实体) – 出现验证错误时行使
  • 500 Internal Server Error (服务器内部错误) –
    服务器总会出现未知错误的

信任随着项目标进步,愈来愈多的地方码会用起来。

进而再次回到体中会重回三个json格式的荒谬音信。它的金科玉律是:

{
    message: 'something is wrong'
}

可是,小编更想要的样板是:

{
    code: code, //更细致的错误编号,必要时提供
    error: error, //错误消息,面向API的调用者,必要时提供
    message: message //错误消息,此消息可以让前端使用alert之类的方法显示给终端用户,必要时提供
}

做那个改动,是因为本身发觉前端有时需求推断错误的花色以做出相应的动作。此外,有时出错新闻能够很随便地归纳出面向终点用户的提示消息,但偶尔又不得不提必要API的调用者一个普及的谬误提醒。并且,API调用者和用户的关心点是不平等的。

相关文章