mishe / blog

前端碰上的问题或体会
230 stars 39 forks source link

API接口规范完整版本(续) #129

Open mishe opened 8 years ago

mishe commented 8 years ago

API接口规范完整版本(续)

整体规范建议采用RESTful 方式来实施。

协议

API与用户的通信协议,总是使用HTTPs协议,确保交互数据的传输安全。

域名

应该尽量将API部署在专用域名之下。 https://api.example.com

如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。 https://example.org/api/

api版本控制

应该将API的版本号放入URL。 https://api.example.com/v{n}/ 另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。

采用多版本并存,增量发布的方式 v{n} n代表版本号,分为整形和浮点型 整形的版本号: 大功能版本发布形式;具有当前版本状态下的所有API接口 ,例如:v1,v2 浮点型:为小版本号,只具备补充api的功能,其他api都默认调用对应大版本号的api 例如:v1.1 v2.2

API 路径规则

路径又称"终点"(endpoint),表示API的具体网址。 在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。 举例来说,有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。

https://api.example.com/v1/products https://api.example.com/v1/users https://api.example.com/v1/employees

HTTP请求方式

对于资源的具体操作类型,由HTTP动词表示。 常用的HTTP动词有下面四个(括号里是对应的SQL命令)。 GET(SELECT):从服务器取出资源(一项或多项)。 POST(CREATE):在服务器新建一个资源。 PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。 DELETE(DELETE):从服务器删除资源。

下面是一些例子。

GET /product:列出所有商品 POST /product:新建一个商品 GET /product/ID:获取某个指定商品的信息 PUT /product/ID:更新某个指定商品的信息 DELETE /product/ID:删除某个商品 GET /product/ID/purchase :列出某个指定商品的所有投资者 get /product/ID/purchase/ID:获取某个指定商品的指定投资者信息

过滤信息

如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。

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

API 传入参数

参入参数分为4种类型:

地址栏参数 * restful 地址栏参数 /api/v1/product/122 122为产品编号,获取产品为122的信息 * get方式的查询字串 见过滤信息小节 请求body数据 cookie request header

cookie和header 一般都是用于OAuth认证的2种途径

返回数据

只要api接口成功接到请求,就不能返回200以外的HTTP状态。 为了保障前后端的数据交互的顺畅,建议规范数据的返回,并采用固定的数据格式封装。

接口返回模板:

{ status:0, data:{}||[], msg:’’ }

status: 接口的执行的状态

=0表示成功 <0 表示有异常 》0 表示接口有部分执行失败

Data 接口的主数据

,可以根据实际返回数组或JSON对象

Msg

当status!=0 都应该有错误信息

非Restful Api的需求

由于实际业务开展过程中,可能会出现各种的api不是简单的restful 规范能实现的,因此,需要有一些api突破restful规范原则。特别是移动互联网的api设计,更需要有一些特定的api来优化数据请求的交互。

页面级的api

把当前页面中需要用到的所有数据通过一个接口一次性返回全部数据

举例

api/v1/get-home-data 返回首页用到的所有数据

这类API有一个非常不好的地址,只要业务需求变动,这个api就需要跟着变更。

自定义组合api

把当前用户需要在第一时间内容加载的多个接口合并成一个请求发送到服务端,服务端根据请求内容,一次性把所有数据合并返回,相比于页面级api,具备更高的灵活性,同时又能很容易的实现页面级的api功能。

规范

地址:api/v1/batApi

传入参数:

data:[ {url:'api1',type:'get',data:{...}}, {url:'api2',type:'get',data:{...}}, {url:'api3',type:'get',data:{...}}, {url:'api4',type:'get',data:{...}} ]

返回数据

{status:0,msg:'', data:[ {status:0,msg:'',data:[]}, {status:-1,msg:'',data:{}}, {status:1,msg:'',data:{}}, {status:0,msg:'',data:[]}, ] }

Api共建平台

RAP是一个GUI的WEB接口管理工具。在RAP中,您可定义接口的URL、请求&响应细节格式等等。通过分析这些数据,RAP提供MOCK服务、测试服务等自动化工具。RAP同时提供大量企业级功能,帮助企业和团队高效的工作。

什么是RAP?

在前后端分离的开发模式下,我们通常需要定义一份接口文档来规范接口的具体信息。如一个请求的地址、有几个参数、参数名称及类型含义等等。RAP 首先方便团队录入、查看和管理这些接口文档,并通过分析结构化的文档数据,重复利用并生成自测数据、提供自测控制台等等... 大幅度提升开发效率。

RAP的特色

强大的GUI工具 给力的用户体验,你将会爱上使用RAP来管理您的API文档。 完善的MOCK服务 文档定义好的瞬间,所有接口已经准备就绪。有了MockJS,无论您的业务模型有多复杂,它都能很好的满足。 庞大的用户群 RAP在阿里巴巴有200多个大型项目在使用,也有许多著名的公司、开源人士在使用。RAP跟随这些业务的成行而成长,专注细节,把握质量,经得住考验。 免费 + 专业的技术支持 RAP是免费的,而且你的技术咨询都将在24小时内得到答复。大多数情况,在1小时内会得到答复。 RAP是一个可视化接口管理工具 通过分析接口结构,动态生成模拟数据,校验真实接口正确性, 围绕接口定义,通过一系列自动化工具提升我们的协作效率。我们的口号:提高效率,回家吃晚饭! rap 流程

上手视频

片源:淘宝视频 优酷

RAP学习中心

定期更新的分步骤视频教程

http://thx.github.io/RAP/study.html

参考链接 http://www.ruanyifeng.com/blog/2014/05/restful_api.html https://github.com/thx/RAP/wiki/about_cn

afc163 commented 8 years ago

/products

/users

mishe commented 8 years ago

@afc163 已改

JasinYip commented 8 years ago

为什么不用 HTTP Status Code 而是使用自己定义的一个 status?这貌似不 RESTful 吧?

mishe commented 8 years ago

api接口应该有2重状态,http status是连接本身的状态,200表示请求接收成功,没有明显的异常,但并不能表示业务代码执行完全成功,没有异常。

JasinYip commented 8 years ago

HTTP 规范有规定 HTTP Status Code 只能表示连接本身的状态吗?如果说只能表示连接本身的状态的话,那 500、404 这类算啥?连接是成功了吧?但服务器出错或者资源没找到那都不是连接本身的问题吧?照你这么说那感觉只有 502、101 这类状态码才有存在的意义……

dc769319 commented 8 years ago

写的不错

mishe commented 8 years ago

@JasinYip 503,101等http状态是有意义的,但对于前端没有太大的意义。前端要的是数据的正确,而不是接口状态的正确。

同样的500状态,可以有很多的触发情况

  1. api服务器本身的500
  2. 接口api缺少参数
  3. api nginx等同类服务的500
  4. api获取数据异常 5....各种其他的错误

如果服务端只告诉前端是500状态,前端怎么来区分当前的状态是什么情况?更何况http只有状态码,没有对前端有效的错误信息,难道要前端去分析http协议?分析500状态服务端返回的一堆对于前端无意义的数据?

JasinYip commented 8 years ago

我觉得你没理解我在说什么😓

jcevo commented 8 years ago

@JasinYip 我感觉你没有理解楼主的意思吧,按你说的只用 HTTP Status Code,

如果前端请求删除一条记录,而这条记录只是在数据库中是不存在的.这个场景你只用 HTTP Status Code,怎么通知给前端?

而楼主增加了一个业务status code来处理对应的业务请求成功与否,难道不是正确的吗?

很多时候 HTTP Status Code, 在客户端大多数 HTTP 框架下,如果是非200的,基本在框架层都被拦截掉了, 我们应用层只处理200的结果.

JasinYip commented 8 years ago

如果前端请求删除一条记录,而这条记录只是在数据库中是不存在的.这个场景你只用 HTTP Status Code,怎么通知给前端?

用 404 啊

在客户端大多数 HTTP 框架下,如果是非200的,基本在框架层都被拦截掉了,

能说一下有哪些「客户端 HTTP 框架」是会把非 200 拦截掉的吗?

iamcc commented 8 years ago

@JasinYip 我们也是用 HTTP Status Code 来表示状态的,😂,暂时还没发现无法表达的情况。

iamcc commented 8 years ago

@JasinYip @alvin87 可以看看 Githup API 的实现

mishe commented 8 years ago

@iamcc 你估计是写接口的吧,不是用接口的,接口随便写,不想被约束?

iamcc commented 8 years ago

@mishe https://api.github.com/user

只是借鉴了一下别人的经验,然后自己瞎 BB 了下,然而怎样定义 API 其实每个人都不一样,能接受就行。

JasinYip commented 8 years ago

@iamcc 你估计是写接口的吧,不是用接口的,接口随便写,不想被约束?

在讨论接口设计的时候,身份是写接口的还是用接口的有什么关系吗?我不太明白

aderan commented 8 years ago

@JasinYip 1,有一种层的概念,有些代码叫第三方库。协议层的代码由协议层的库解决,业务层的代码由业务层的封装处理。 2,有些概念叫ORM/Model/Bean,有些API确实能用,虽能实现业务需求,但会影响客户端代码美感。 3,好的设计,是兼顾或者同一前后端的代码实现,是大家都比较轻松,或者以后更轻松。

jcevo commented 8 years ago

@aderan
1.第一点赞同,能否给一个例子?概念终究要有个载体表现出来. 2.如果光有美感,而不能实现业务需求,难道只要个花瓶吗? 3.同意.

JasinYip commented 8 years ago

1,有一种层的概念,有些代码叫第三方库。协议层的代码由协议层的库解决,业务层的代码由业务层的封装处理。 2,有些概念叫ORM/Model/Bean,有些API确实能用,虽能实现业务需求,但会影响客户端代码美感。 3,好的设计,是兼顾或者同一前后端的代码实现,是大家都比较轻松,或者以后更轻松。

@aderan

能否简单直白地讨论问题?阴阳怪气的大空话没意思吧?

iamcc commented 8 years ago

@JasinYip 😂,大概大牛都这样。不过我也不反对楼主的做法,毕竟规范这种东西因团队而异,团队统一那就是规范。像我这种就只能跟风,api 参照 github,js lint 参照 airbnb,至少人家说我,我还可以说,你看,人家 xxx 也是这样干的。

mishe commented 8 years ago

考虑一下大家最容易碰到的环境: 假如你的系统有100个API,提供给app或者前端开发使用(100个接口的应用应该还是比较小的系统吧),然后每个接口都非常的有个性,开发API的服务端人员是轻松了,他可以非常个性,想怎么写就怎么写; 但作为APP和前端的感受呢,有没有想过?AJAX数据请求会有100种写法。如何来管理这些请求?如何来做数据缓存?如何做前端优化? 最严重的是,如何来维护这套系统?

mishe commented 8 years ago

有300个接口,1000个接口又是什么情况?

JasinYip commented 8 years ago

考虑一下大家最容易碰到的环境: 假如你的系统有100个API,提供给app或者前端开发使用(100个接口的应用应该还是比较小的系统吧),然后每个接口都非常的有个性,开发API的服务端人员是轻松了,他可以非常个性,想怎么写就怎么写; 但作为APP和前端的感受呢,有没有想过?AJAX数据请求会有100种写法。如何来管理这些请求?如何来做数据缓存?如何做前端优化? 最严重的是,如何来维护这套系统?

有300个接口,1000个接口又是什么情况?

这个问题有什么意义?我们在讨论的是什么是 RESTful API?是否应该只使用 HTTP Status Code 来表示状态?而不是在试图无规范化吧?

规范中一旦确定下来,大家都将会依照这个规范去做,并且每个 API 都输出文档,何来「想怎么写就怎么写」这样的行为?一万个接口又如何?

mishe commented 8 years ago

@iamcc 我是在抄袭文章?你是指这篇吗?http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api? 我的想法和他有很大交集?我只是站在前端的立场,希望后端api服务能提供restful服务,很抱歉,有太多的后端程序员不知道restful是什么,不知道jsonp是什么?

mishe commented 8 years ago

@JasinYip 看清楚了,再来BB,这是在写restful 规范吗?我只是引用了阮一峰的restful规范,主题不是restful,身为中国人,看不懂中文才是最可怕的。这篇文章不是为你这样的服务的,你也看不懂这篇文章在说的东西。

mishe commented 8 years ago

写这个完整版处于几点考虑:

  1. 补全之前文章的内容 #126 文章描述的不够清晰,不够全面,那是应急写的
  2. 规范前后端的api开发流程和规程
  3. 方便前后端开发的配合和前端的调试,加速功能的实现
  4. 优化移动端的开发模式
  5. 优化移动端开发的数据本地存储提供有效的保障
  6. 这个完整版会成为公司的一个执行标准,当然之后也会有更多的完善
iamcc commented 8 years ago

@iamcc 我是在抄袭文章?你是指这篇吗?http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api? 我的想法和他有很大交集?我只是站在前端的立场,希望后端api服务能提供restful服务,很抱歉,有太多的后端程序员不知道restful是什么,不知道jsonp是什么?

@mishe 😂,大牛别着急,我发现我们永远不在一个频道上,可能我与你的级别还是差太远。

另外一点就是,我真的不知道我哪里说你抄袭了???

mishe commented 8 years ago

另外,非restful接口,那是我在2013年就开始实施的方案,我不知道之前是否有人有提出过之类的观点和文章,如果有,那么请告之,我增加文章的引用说明。

JasinYip commented 8 years ago

@JasinYip 看清楚了,再来BB,这是在写restful 规范吗?我只是引用了阮一峰的restful规范,主题不是restful,身为中国人,看不懂中文才是最可怕的。这篇文章不是为你这样的服务的,你也看不懂这篇文章在说的东西。

你这样说就没意思了,技术撕逼是很正常的,你上升到人身攻击就不道德了,这不是一个技术人应有的态度。

这是你自己在全篇最前面说的:

整体规范建议采用RESTful 方式来实施。

所以你的接口没有设计成 RESTful 我来提出疑问这不是很正常的吗?

我也懒得说下去了,爱咋咋滴吧,你开心就好。

mishe commented 8 years ago

image

iamcc commented 8 years ago

@mishe 😂,真的很抱歉,是我的错,没说清楚,我需要解释一下。

image

首先,我发 github 的 api 地址给你是想说,github 是怎样实现的。 下面那句话是说的我自己,我只是借鉴了 github 的经验,然后在你这里自己 瞎 BB 了一下,没想到误解了,抱歉,说我自己,并不是说您。

fairjm commented 8 years ago

header的方式和v1 v2可以兼容 header里的版本不同于v1 v2

做app接口 有些时候老版本app的bug 比如app使用错后端字段 传回了不该传的参数等等 介于app老版本使用人数还很多 前端要让后端来修 就只能判断头里的版本进行特殊处理了

这个版本存在于前端了 可以说和APP版本等价 对后端透明 后端要用也主要用来修复bug

之后热替换 react native慢慢用多了 就可以轻松多了...后端就不用背app的锅了...

Zousdie commented 5 years ago

当你放弃使用HTTP状态码去表示对当前资源的请求的状态时,就已经不是restful了。

完全放弃HTTP状态码,而在response body中再自定义一套code,完全不可取

restful最大的特点是一个URI映射系统的唯一的资源,用原生的HTTP状态码去表示对资源进行不同操作的结果状态。而不是像你说的,用HTTP状态码去表示这次连接通没同。

一般的,使用HTTP状态码去区分错误类型,同时需要在response body中返回具体的错误信息; 如果业务复杂,可以定义业务错误码,针对该每一种错误类型下多种错误进行标识