一声笑接口文档


title: 一声笑接口文档
date: 2019-03-03 21:44:43
tags:


Author:Leguang

E-Mail:langmanleguang@qq.com

目标

  • 接口“粒度”争取设计得足够小,争取在业务发生变化后,后台接口不需要增减,只需要前端组合接口仍然能满足新的业务需求。
  • 任何一个接口都可以获取到数据,哪怕没传参数。

要求

命名规范

一名二姓三风水,四积阴德五读书,名不正则言不顺,言不顺则事难成。软件开发其实就是门命名的艺术,所以首先定义一些规范,提出一些硬性要求,大家在命名的时候尽量多花点心思,多参考优秀的命名风格。

  • 强烈推荐参考:参考阿里巴巴Java开发手册Android开发规范iOS开发手册
  • 一个单词尽量选择5--7个字母的,这样才最优美。
  • 首字母缩写的单词尽量每个字母都用大写,例如ID。用个小写,人家还以为是一个单词。当然uri、url、urn这种除外,因为大家都知道这个是什么。
  • 规范并统一公司的基础包名与项目的关系。
  • 前后端的某些名称概念要统一用某一个单词,比如支付的统一订单,支付宝用的是order,微信用的是unifiedorder,那我们统一对订单这个概念用order这个词。再比如主机:后台用gateway,现在我们统一用host。这单词不统一很容易分裂。

uri规范

uri 表示资源,资源一般对应服务器端领域模型中的实体类,要求如下:

  • 不用大写。
  • 尽量不用横杠分隔符,万一要用,请使用中杠“-”不用下杠“_”。
  • 参数列表要encode。
  • uri中的名词表示资源集合,使用复数形式。
  • 路径仅表示资源的路径(位置),以及一些特殊的actions操作。
  • 以复数(名词)进行命名资源,不管返回单个或者多个资源。
  • 资源的路径从父到子依次如:/{resource}/{resource_id}/{sub_resource}/{sub_resource_id}/{sub_resource_property}。
  • 使用?来进行资源的过滤、搜索以及分页等。
  • 使用版本号,且版本号在资源路径之前。
  • 优先使用内容协商来区分表述格式,而不是使用后缀来区分表述格式。
  • url最好越简短越好,结果过滤,排序,搜索相关的功能都应该通过参数实现。
  • url失效则返回404 not found 或 410 gone;对迁移的API,返回 301 重定向。

JSON规范

暂时只考虑json的数据格式,要求如下:

  • 不要使用缩写。
  • 统一用驼峰命名法。
  • 不要使用“_”或者“-”。
  • 用名词复数表示集合类型。
  • 为了方便以后的扩展兼容,如果返回的是数组,强烈建议用一个包含如items属性的对象进行包裹。如:{"items":[{},{}]}
  • 建议对每个字段设置默认值(数组型可设置为[],字符串型可设置为””,数值可设置为0,对象可设置为{}),这一条是为了方便前端/客户端进行判断字段存不存在操作。
  • 建议资源使用UUID最为唯一标识。同时建议命名为id或者uid。
  • 采用UTF-8编码。
  • 数据应该拿来就能用,不应该还要进行转换操作。

草稿:JSON返回的格式是分门别类按对象来划分,还是铺大饼的形式铺开,两者利弊各异,比如url,可能一个接口中返回多个url,如果分json对象装的话,则key都可以叫url,否则的话key就得命名成xxxUrl。这个有待商议

HTTP部分

使用场景

  • App的初始化数据尽量都用http协议获取。
  • 页面的初始化数据尽量都用http协议获取。

URL结构

https://{serviceRoot}/{module}/{collection}/{id}
  • {serviceRoot} – 域名+端口号 (site URL) + 根目录
  • {module} – 模块名称
  • {collection} – 要访问的资源
  • {id} – 要访问的资源的唯一编号

公共请求头

通过Content-Type指定请求与返回的数据格式有JSON和XML,暂时我们只管json的。其中请求数据还要指定Accept。其中额外添加的请求头里的参数注意大小写。

Accept: application/json
Content-Type: application/json;charset=UTF-8
Token: token_G34G34G34G34G35G5
Application: 应用:版本
Platform: Android
Locale: zh
params 类型 是否必要 描述
Token String 这个不用解释了吧?
Application String App应用名称(名称有官方指定)与当前版本的版本名称,中间用半角冒号隔开
Platform String Android表示Android平台,iOS表示iOS平台
Locale String 用于针对接口的国际化,不同的值代表不同的语言,可以不传,不传默认表示中文简体。值和语言如下表所示:

暂时只考虑4门语言

意义
zh 中文(简体)
en 英文
ja 日文
ko 韩文

公共参数(部分公共参数建议公放到请求头里)

公共参数是指每一个接口都可能有的,为了减少篇幅,我在这里统一定义,同时后端要指定公共参数的默认值,且要保证没有传公共参数不会报错,所以需要一定的容错性,比如priceDes这个参数值,如果是用的是全部小写的,只要是不冲突,则可认为是准确的参数并且表达了按价格降序排列这个语意。常用公共参数如下:

params 类型 是否必须 描述
keyword String 用于检索,不传或者传空,表示默认,默认不检索该关键字
sort String 用于对列表排序,不传则表示默认,默认按配置顺序,asc升序,desc降序
page int 用于分页描述,不传则表示默认,默认是第1页
pageSize int 表示该页显示的条数,不传则表示默认,默认为20条

个性参数

个性参数就是除了公共参数之外的,看能否考虑统一用JSON将公共参数和个性参数浓缩成一个参数,把想要表达的参数通过json中的key-value形式传递。例如:https://api.xxx.com/both/v1/search/products?params={"extra":"你想填什么呢","token":"token_523523523","data":{"uid":"23523523523523"}} 或者考虑与业务相关的参数就用json形式包装,而与业务无关的个性参数就还是用传统的方式另立一个参数。例如:https://api.xxx.com/both/v1/search/products?limit=10&offset=10&params={"keyword":"方便面","sort":"des"}

通过商议将个性参数统一按原始的URL传参形式传递,不考虑上面所说的那种方式。

公共响应头

Content-Type:application/json; charset=utf-8
Status:200 OK

其中状态码要与公共响应体里的json中的code字段一样。

公共响应体

默认会有以下字段,不需要全部都有。

{
    "message": "居然被你查询成功了",
    "code": 200,
    "page": 0,
    "pageSize": 20,
    "first": "https://...",
    "next": "https://...",
    "previous": "https://...",
    "last": "https://...",
    "data": {
        "uid": "6565656565665"
    }
}
key 类型 是否必须 描述
message String 返回给接口调用者的描述,有可能用于显示到界面上,需要进行国际化处理
code int 这个与请求头中的状态码一致,是为了满足部分开发者的习惯
page int 分页请求中请求的当前页的页码
pageSize int 分页请求中一页的个数,默认为20
first String 分页请求中第一页的url ,如果没有则返回空字符串
next String 分页请求中下一页的url,如果没有则返回空字符串
previous String 分页请求中上一页的url,如果没有则返回空字符串
last String 分页请求中最后一页的url,如果没有则返回空字符串
data object 当前接口的具体数据由该json对象承载
uid String 对于每一个资源对象,在返回的时候,都应该返回操作这个资源对象的唯一码

HTTP动词表示操作。

常用的HTTP动词有下面五个(括号里是对应的SQL命令)。

  • GET(SELECT):从服务器取出资源(一项或多项)。
    例如:GET /zoos:列出所有动物园。
  • POST(CREATE):在服务器新建一个资源。
    例如:POST /zoos:新建一个动物园。
  • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
    例如:PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)。
  • DELETE(DELETE):从服务器删除资源。
    例如:DELETE /zoos/ID:删除某个动物园。

状态码

作为API的设计者,正确的将API执行结果和失败原因用清晰简洁的方式传达给客户程序是十分关键的一步。我们确实可以在HTTP的相应内容中描述是否成功,如果出错是因为什么,然而,这就意味着用户需要进行内容解析,才知道执行结果和错误原因。因此,HTTP响应代码可以保证客户端在第一时间用最高效的方式获知 API 运行结果,并采取相应动作。下表列出了比较常用的响应代码。
常用的http状态码及使用场景:

响应代码 代码含义
200 已创建,请求成功且服务器已创建了新的资源。
201 是否只显示处于警告状态的应用实例。
301 重定向 , 请求的网页已被永久移动到新位置。服务器返回此响应时,会自动将请求者转到新位置。
302 重定向 , 请求的网页临时移动到新位置,但求者应继续使用原有位置来进行以后的请求。302 会自动将请求者转到不同的临时位置。
304 未修改,自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。
400 错误请求 , 服务器不理解请求的语法。
401 未授权 , 请求要求进行身份验证。
403 已禁止 , 服务器拒绝请求。
404 未找到 , 服务器找不到请求的网页。
405 方法禁用 , 禁用请求中所指定的方法。
406 不接受 , 无法使用请求的内容特性来响应请求的网页。
408 请求超时 , 服务器等候请求时超时。
410 已删除 , 如果请求的资源已被永久删除,那么,服务器会返回此响应。
412 未满足前提条件 , 服务器未满足请求者在请求中设置的其中一个前提条件。
415 不支持的媒体类型 , 请求的格式不受请求页面的支持。
500 内部服务器错误。

分页

分页适用于GET类型且返回集合数据的请求,根据如下参数进行分页操作。分页返回的数据见公共响应体。

{
    "extra": "你想填什么就填什么",
    "page": 0,
    "pageSize": 20,
}
params 类型 是否必须 描述
page int 同上
pageSize int 同上

错误/异常处理

  • 不要发生了错误但给2xx响应,客户端可能会缓存成功的HTTP请求;
  • 正确设置http状态码,不要自定义;
  • Response body 提供 1) 错误的代码(日志/问题追查);2) 错误的描述文本(展示给用户)。

对第三点的实现稍微多说一点:

Java 服务器端一般用异常表示 RESTful API 的错误。API 可能抛出两类异常:业务异常和非业务异常。业务异常由自己的业务代码抛出,表示一个用例的前置条件不满足、业务规则冲突等,比如参数校验不通过、权限校验失败。非业务类异常表示不在预期内的问题,通常由类库、框架抛出,或由于自己的代码逻辑错误导致,比如数据库连接失败、空指针异常、除0错误等等。

业务类异常必须提供2种信息:

  1. 如果抛出该类异常,HTTP响应状态码应该设成什么;
  2. 异常的文本描述;
错误描述
{
    "message": "特么的又错了",
    "code": 500,
    "document": "https://developer.xxx.com/v1/errors/500",
    "exception": [
        {
            "code": "NullValue",
            "target": "PhoneNumber",
            "message": "Phone number must not be null"
        },
        {
            "code": "NullValue",
            "target": "LastName",
            "message": "Last name must not be null"
        },
        {
            "code": "MalformedValue",
            "target": "Address",
            "message": "Address is not valid"
        }
    ]
}
错误请求头
{
  "date": "Mon, 08 Jan 2018 03:07:08 GMT",
  "server": "nginx/1.10.3 (Ubuntu)",
  "connection": "keep-alive",
  "content-length": "237",
  "content-type": "application/json"
}

错误状态码(非200)

通过分析发现,接口的错误无非调用端传递给后台的信息与预期不符,其中包括公共参数和个性参数不符,不符包括缺失和内容错误(或格式错误等)两种,还有是部分特殊业务的特殊性质造成非正常结果,如:重复申请、重复签到等。经商议决定将错误码分为四大类:

错误码 类型 描述 举例
XXX int 用于描述缺少参数,同时message做出相应的辅助描述,告诉调用者到底是缺少哪个参数,这些message只有调用者看得到,用户看不到 需要a、b、c三个参数,结果只收到a和b参数,或者收到c参数,但c参数为空字符串,且c参数又是必传的,因此可返回该错误码,同时messgae中提示:缺少c参数,或者c参数不能为空
XXX int 用于描述有参数但参数错误,可能是内容错误或格式错误,同时message做出相应的辅助描述,告诉调用者到底是哪个参数错误,这些message只有调用者看得到,用户看不到 需要传a参数为String类型的11位手机号码,结果收到的是long类型,或只有10位的String,则可返回该错误码,同时message提示a参数错误
XXX int 描述某些特定业务场景,比如重复申请、重复签到等,每一个场景对应一个错误码,同时message会提示相应错误场景,这些message会给用户看到的 比如重复申请注册奖励,返回特定码,前端做出相应显示,或者跳转,或者隐藏即可
XXX int 描述某些公共功能,调用者会做出相应公共处理 比如token失效,直接跳转到登录界面

以上友好的message提示方便了我们,同时也方便了非法调用者,为阻碍非法调用,决定设置一个开关,该开关是系统自带的,根据编译环境变更,在调试阶段就用以上友好提示,在正式部署上线后就改成模糊提示。

url失效

随着系统发展,总有一些API失效或者迁移,对失效的API,返回404 not found 或 410 gone;对迁移的API,返回 301 重定向。

对于后台文档的要求

文档要求

文档要求描述详尽,尽可能的引导接口使用者理解接口设计,这样才能减少接口的改动,又能适应多变的业务。

容错性(健壮性)

考虑到如果测试或者运营中有变动,要求每一个Web页面得有容错机制,比如关停该功能,则web必须的有相应的页面展示。

国际化

此处的国际化是指语言的国际化,因此前后端都要考虑在界面的文字提示上要做国际化处理,暂时我们只做4种文字的国际化:中文(简体)、英文、日文和韩文,经商议,通过两方面来传递国际化信息:

  • 专门的locale设置接口
  • 请求头中多一个locale字段

由于有两个入口设置语言,因此有优先级处理,请求头中locale字段优先级大于locale设置接口,两者不传,默认都表示简体中文。locale接口默认为简体中文,如果有设置其他语言,则为其他语言,请求头里如果没有locale字段,则依据locale接口,如果请求头里带了locale字段,则依据请求头为准。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 小时候,因为冬天怕冷,很羡慕南国的四季如春,想象着冬天也能舒服安适得晒着暖融融的太阳,手脚不会龟裂。长大后,却庆幸...
    采采芣苡阅读 206评论 0 0
  • 夜寒风不动, 万树驻梨花。 群塔耸立度, 林梢映玉霞。 冰松见挺拔, 素柳更横插。 万壑松涛古, 飞鸣云雀舞。 2...
    飞鸿行走阅读 272评论 0 0
  • 好久没有写东西了,突然有感而发。今天早上坐地铁的时候,门旁边站着一个肚子挺大的孕妇,大概有6个月左右。我坐在靠门第...
    飞翔的山鸡阅读 207评论 0 0