整理全网优秀的API接口设计及相关优秀的接口管理、在线文档生成工具

时间:2024-02-23 15:41:31

一、优秀的接口设计


在日常开发中,总会接触到各种接口。前后端数据传输接口,第三方业务平台接口。一个平台的前后端数据传输接口一般都会在内网环境下通信,而且会使用安全框架,所以安全性可以得到很好的保护。这篇文章重点讨论一下提供给第三方平台的业务接口应当如何设计?我们应该考虑哪些问题?

img

主要从以上三个方面来设计一个安全的API接口。

1.1 安全性问题

安全性问题是一个接口必须要保证的规范。如果接口保证不了安全性,那么你的接口相当于直接暴露在公网环境中任人蹂躏。

1.1.1 调用接口的先决条件-token

获取token一般会涉及到几个参数appidappkeytimestampnoncesign。我们通过以上几个参数来获取调用系统的凭证。

appidappkey可以直接通过平台线上申请,也可以线下直接颁发。appid是全局唯一的,每个appid将对应一个客户,appkey需要高度保密。

timestamp是时间戳,使用系统当前的unix时间戳。时间戳的目的就是为了减轻DOS攻击。防止请求被拦截后一直尝试请求接口。服务器端设置时间戳阀值,如果请求时间戳和服务器时间超过阀值,则响应失败。

nonce是随机值。随机值主要是为了增加sign的多变性,也可以保护接口的幂等性,相邻的两次请求nonce不允许重复,如果重复则认为是重复提交,响应失败。

sign是参数签名,将appkeytimestampnonce拼接起来进行md5加密(当然使用其他方式进行不可逆加密也没问题)。

token,使用参数appidtimestampnoncesign来获取token,作为系统调用的唯一凭证。token可以设置一次有效(这样安全性更高),也可以设置时效性,这里推荐设置时效性。如果一次有效的话这个接口的请求频率可能会很高。token推荐加到请求头上,这样可以跟业务参数完全区分开来。

1.1.2 使用POST作为接口请求方式

一般调用接口最常用的两种方式就是GET和POST。两者的区别也很明显,GET请求会将参数暴露在浏览器URL中,而且对长度也有限制。为了更高的安全性,所有接口都采用POST方式请求。

1.1.3 客户端IP白名单

ip白名单是指将接口的访问权限对部分ip进行开放。这样就能避免其他ip进行访问攻击,设置ip白名单比较麻烦的一点就是当你的客户端进行迁移后,就需要重新联系服务提供者添加新的ip白名单。设置ip白名单的方式很多,除了传统的防火墙之外,spring cloud alibaba提供的组件sentinel也支持白名单设置。为了降低api的复杂度,推荐使用防火墙规则进行白名单设置。

1.1.4 单个接口针对ip限流

限流是为了更好的维护系统稳定性。使用redis进行接口调用次数统计,ip+接口地址作为key,访问次数作为value,每次请求value+1,设置过期时长来限制接口的调用频率。

1.5 记录接口请求日志

使用aop全局记录请求日志,快速定位异常请求位置,排查问题原因。

1.1.6 敏感数据脱敏

在接口调用过程中,可能会涉及到订单号等敏感数据,这类数据通常需要脱敏处理,最常用的方式就是加密。加密方式使用安全性比较高的RSA非对称加密。非对称加密算法有两个密钥,这两个密钥完全不同但又完全匹配。只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。

1.2 幂等性问题

幂等性是指任意多次请求的执行结果和一次请求的执行结果所产生的影响相同。说的直白一点就是查询操作无论查询多少次都不会影响数据本身,因此查询操作本身就是幂等的。但是新增操作,每执行一次数据库就会发生变化,所以它是非幂等的。

幂等问题的解决有很多思路,这里讲一种比较严谨的。提供一个生成随机数的接口,随机数全局唯一。调用接口的时候带入随机数。第一次调用,业务处理成功后,将随机数作为key,操作结果作为value,存入redis,同时设置过期时长。第二次调用,查询redis,如果key存在,则证明是重复提交,直接返回错误。

1.3 数据规范问题

1.3.1 版本控制

一套成熟的API文档,一旦发布是不允许随意修改接口的。这时候如果想新增或者修改接口,就需要加入版本控制,版本号可以是整数类型,也可以是浮点数类型。一般接口地址都会带上版本号,http://ip:port//v1/list。

1.3.2 响应状态码规范

一个牛逼的API,还需要提供简单明了的响应值,根据状态码就可以大概知道问题所在。我们采用http的状态码进行数据封装,例如200表示请求成功,4xx表示客户端错误,5xx表示服务器内部发生错误。状态码设计参考如下:

分类 描述


1xx 信息,服务器收到请求,需要请求者继续执行操作
2xx 成功
3xx 重定向,需要进一步的操作以完成请求
4xx 客户端错误,请求包含语法错误或无法完成请求
5xx 服务端错误

状态码枚举类:

public enum CodeEnum {                                                                                                                                                                          
                                                                                                                                                                                                
// 根据业务需求进行添加                                                                                                                                                                                   
SUCCESS(200,"处理成功"),                                                                                                                                                                            
ERROR_PATH(404,"请求地址错误"),                                                                                                                                                                       
ERROR_SERVER(505,"服务器内部发生错误");                                                                                                                                                                  
                                                                                                                                                                                                
private int code;                                                                                                                                                                               
private String message;                                                                                                                                                                         
                                                                                                                                                                                                
CodeEnum(int code, String message) {                                                                                                                                                            
this.code = code;                                                                                                                                                                               
this.message = message;                                                                                                                                                                         
}                                                                                                                                                                                               
                                                                                                                                                                                                
public int getCode() {                                                                                                                                                                          
return code;                                                                                                                                                                                    
}                                                                                                                                                                                               
                                                                                                                                                                                                
public void setCode(int code) {                                                                                                                                                                 
this.code = code;                                                                                                                                                                               
}                                                                                                                                                                                               
                                                                                                                                                                                                
public String getMessage() {                                                                                                                                                                    
return message;                                                                                                                                                                                 
}                                                                                                                                                                                               
                                                                                                                                                                                                
public void setMessage(String message) {                                                                                                                                                        
this.message = message;                                                                                                                                                                         
}                                                                                                                                                                                               
}                                                                                                                                                                                               

1.3.3 统一响应数据格式

为了方便给客户端响应,响应数据会包含三个属性,状态码(code),信息描述(message),响应数据(data)。客户端根据状态码及信息描述可快速知道接口,如果状态码返回成功,再开始处理数据。

响应结果定义及常用方法:

public class R implements Serializable {                                                                                                                                                        
                                                                                                                                                                                                
private static final long serialVersionUID = 793034041048451317L;                                                                                                                               
                                                                                                                                                                                                
private int code;                                                                                                                                                                               
private String message;                                                                                                                                                                         
private Object data = null;                                                                                                                                                                     
                                                                                                                                                                                                
public int getCode() {                                                                                                                                                                          
return code;                                                                                                                                                                                    
}                                                                                                                                                                                               
public void setCode(int code) {                                                                                                                                                                 
this.code = code;                                                                                                                                                                               
}                                                                                                                                                                                               
                                                                                                                                                                                                
public String getMessage() {                                                                                                                                                                    
return message;                                                                                                                                                                                 
}                                                                                                                                                                                               
public void setMessage(String message) {                                                                                                                                                        
this.message = message;                                                                                                                                                                         
}                                                                                                                                                                                               
                                                                                                                                                                                                
public Object getData() {                                                                                                                                                                       
return data;                                                                                                                                                                                    
}                                                                                                                                                                                               
                                                                                                                                                                                                
/**                                                                                                                                                                                             
* 放入响应枚举                                                                                                                                                                                        
*/                                                                                                                                                                                              
public R fillCode(CodeEnum codeEnum){                                                                                                                                                           
this.setCode(codeEnum.getCode());                                                                                                                                                               
this.setMessage(codeEnum.getMessage());                                                                                                                                                         
return this;                                                                                                                                                                                    
}                                                                                                                                                                                               
                                                                                                                                                                                                
/**                                                                                                                                                                                             
* 放入响应码及信息                                                                                                                                                                                      
*/                                                                                                                                                                                              
public R fillCode(int code, String message){                                                                                                                                                    
this.setCode(code);                                                                                                                                                                             
this.setMessage(message);                                                                                                                                                                       
return this;                                                                                                                                                                                    
}                                                                                                                                                                                               
                                                                                                                                                                                                
/**                                                                                                                                                                                             
* 处理成功,放入自定义业务数据集合                                                                                                                                                                              
*/                                                                                                                                                                                              
public R fillData(Object data) {                                                                                                                                                                
this.setCode(CodeEnum.SUCCESS.getCode());                                                                                                                                                       
this.setMessage(CodeEnum.SUCCESS.getMessage());                                                                                                                                                 
this.data = data;                                                                                                                                                                               
return this;                                                                                                                                                                                    
}                                                                                                                                                                                               
}                                                                                                                                                                                               

1.4 接口设计总结

本篇文章从安全性、幂等性、数据规范等方面讨论了API设计规范。除此之外,一个好的API还少不了一个优秀的接口文档。接口文档的可读性非常重要,虽然很多程序员都不喜欢写文档,而且不喜欢别人不写文档。为了不增加程序员的压力,推荐使用swagger或其他接口管理工具,通过简单配置,就可以在开发中测试接口的连通性,上线后也可以生成离线文档用于管理API。

二、推荐些优秀的在线文档生成工具

一些优秀的在线文档、接口文档的生成工具,需满足如下条件:

  1. 必须是开源的
  2. 能够实时生成在线文档
  3. 支持全文搜索
  4. 支持在线调试功能
  5. 界面优美

在此推荐一些满足上述条件的在线接口文档工具。

2.1 Knife4j

gitee地址:https://gitee.com/xiaoym/knife4j

推荐指数:★★★★

image-20210702093405442

Knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍。

  • 优点:基于swagger生成实时在线文档,支持在线调试,全局参数、国际化、访问权限控制等,功能非常强大。

  • 缺点:界面有一点点丑,需要依赖额外的jar包

  • 个人建议:如果公司对ui要求不太高,可以使用这个文档生成工具,比较功能还是比较强大的。

2.2 smartdoc

gitee地址:https://gitee.com/smart-doc-team/smart-doc

用户:小米、科大讯飞、1加

示例:

image-20210702093444426

smart-doc是一个java restful api文档生成工具,smart-doc颠覆了传统类似swagger这种大量采用注解侵入来生成文档的实现方法。smart-doc完全基于接口源码分析来生成接口文档,完全做到零注解侵入,只需要按照java标准注释的写就能得到一个标准的markdown接口文档。

  • 优点:基于接口源码分析生成接口文档,零注解侵入,支持html、pdf、markdown格式的文件导出。

  • 缺点:需要引入额外的jar包,不支持在线调试

  • 个人建议:如果实时生成文档,但是又不想打一些额外的注解,比如:使用swagger时需要打上@Api、@ApiModel等注解,就可以使用这个。

2.3 redoc

github地址:https://github.com/Redocly/redoc

用户:docker、redocly

示例:

image-20210702093453581

redoc自己号称是一个最好的在线文档工具。它支持swagger接口数据,提供了多种生成文档的方式,非常容易部署。使用redoc-cli能够将您的文档捆绑到零依赖的 HTML文件中,响应式三面板设计,具有菜单/滚动同步。

  • 优点:非常方便生成文档,三面板设计

  • 缺点:不支持中文搜索,分为:普通版本 和 付费版本,普通版本不支持在线调试。另外UI交互个人感觉不适合国内大多数程序员的操作习惯。

  • 个人建议:如果想快速搭建一个基于swagger的文档,并且不要求在线调试功能,可以使用这个。

2.4 yapi

github地址:https://github.com/YMFE/yapi

用户:腾讯、阿里、百度、京东等大厂

示例:

image-20210702093504332

yapi是去哪儿前端团队自主研发并开源的,主要支持以下功能:

  • 可视化接口管理

  • 数据mock

  • 自动化接口测试

  • 数据导入(包括swagger、har、postman、json、命令行)

  • 权限管理

  • 支持本地化部署

  • 支持插件

  • 支持二次开发

  • 优点:功能非常强大,支持权限管理、在线调试、接口自动化测试、插件开发等,BAT等大厂等在使用,说明功能很好。

  • 缺点:在线调试功能需要安装插件,用户体检稍微有点不好,主要是为了解决跨域问题,可能有安全性问题。不过要解决这个问题,可以自己实现一个插件,应该不难。

  • 个人建议:如果不考虑插件安全的安全性问题,这个在线文档工具还是非常好用的,可以说是一个神器,笔者在这里强烈推荐一下。

2.5 apidoc

github地址:https://github.com/apidoc/apidoc

推荐指数:★★★★☆

示例:

image-20210702093549315

apidoc 是一个简单的 RESTful API 文档生成工具,它从代码注释中提取特定格式的内容生成文档。支持诸如 Go、Java、C++、Rust 等大部分开发语言,具体可使用 apidoc lang 命令行查看所有的支持列表。

apidoc 拥有以下特点:

  1. 跨平台,linux、windows、macOS 等都支持;
  2. 支持语言广泛,即使是不支持,也很方便扩展;
  3. 支持多个不同语言的多个项目生成一份文档;
  4. 输出模板可自定义;
  5. 根据文档生成 mock 数据;
  • 优点:基于代码注释生成在线文档,对代码的嵌入性比较小,支持多种语言,跨平台,也可自定义模板。支持搜索和在线调试功能。

  • 缺点:需要在注释中增加指定注解,如果代码参数或类型有修改,需要同步修改注解相关内容,有一定的维护工作量。

  • 个人建议:这种在线文档生成工具提供了另外一种思路,swagger是在代码中加注解,而apidoc是在注解中加数据,代码嵌入性更小,推荐使用。

2.6 showdoc(记得好像开始收费了)

github地址:https://github.com/star7th/showdoc

用户:超过10000+互联网团队正在使用

示例:

image-20210702093600033

ShowDoc就是一个非常适合IT团队的在线文档分享工具,它可以加快团队之间沟通的效率。

它都有些什么功能:

  1. 响应式网页设计,可将项目文档分享到电脑或移动设备查看。同时也可以将项目导出成word文件,以便离线浏览。
  2. 权限管理,ShowDoc上的项目有公开项目和私密项目两种。公开项目可供任何登录与非登录的用户访问,而私密项目则需要输入密码验证访问。密码由项目创建者设置。
  3. ShowDoc采用markdown编辑器,点击编辑器上方的按钮可方便地插入API接口模板和数据字典模板。
  4. ShowDoc为页面提供历史版本功能,你可以方便地把页面恢复到之前的版本。
  5. 支持文件导入,文件可以是postman的json文件、swagger的json文件、showdoc的markdown压缩包,系统会自动识别文件类型。
  • 优点:支持项目权限管理,多种格式文件导入,全文搜索等功能,使用起来还是非常方便的。并且既支持部署自己的服务器,也支持在线托管两种方式。

  • 缺点:不支持在线调试功能

  • 个人建议:如果不要求在线调试功能,这个在线文档工具值得使用。

2.7 Apizza(极客专属的接口协作管理工具)

官网地址:http://www.apizza.net/

2.7.1 主要功能

  1. api跨域调试量身定制的chrome插件,本地,在线接口,都可以调。

  2. 云端存储,企业安全版支持本地数据中心。

  3. 一键分享,与团队共享你的API文档。

  4. 支持Postman,Swagger格式 导入Postman/Swagger Json 生成文档。

  5. 导出离线文档,部署本地服务器。

  6. api Mock 根据文档自动生成返回结果,提供独立URL方便前端测试。

  7. 支持多种文档 http接口文档,markdown说明文档。

Apizza接口文档工具有一个很大不足的地方,那是Apizza个人免费版有人数限制,所有超过8人的团队如果想免费用,你是不用考虑Apizza的。如果你看到有文章或公众号上说Apizza是免费的,那简直是胡扯,他肯定没用过。当然如果你不缺钱,可以付费开通企业版。我们团队也是用了半年多Apizza,后来由于人员增加,Apizza里又无法再新添加新成员,迫使我们不得不放弃Apizza。

2.8 APIJSON

Gitee地址:https://gitee.com/Tencent/APIJSON

推荐指数:★★★★

  • APIJSON 是一种专为 API 而生的 JSON 网络传输协议 以及 基于这套协议实现的 ORM 库。 为简单的增删改查、复杂的查询、简单的事务操作 提供了完全自动化的万能 API。

  • 能大幅降低开发和沟通成本,简化开发流程,缩短开发周期。

  • 适合中小型前后端分离的项目,尤其是 BaaS、Serverless、互联网创业项目和企业自用项目。

  • 通过万能的 API,前端可以定制任何数据、任何结构。

  • 大部分 HTTP 请求后端再也不用写接口了,更不用写文档了。

  • 前端再也不用和后端沟通接口或文档问题了。再也不会被文档各种错误坑了。

  • 后端再也不用为了兼容旧接口写新版接口和文档了。再也不会被前端随时随地没完没了地烦了。

2.8.1 特点功能

对于前端

  • 不用再向后端催接口、求文档
  • 数据和结构完全定制,要啥有啥
  • 看请求知结果,所求即所得
  • 可一次获取任何数据、任何结构
  • 能去除重复数据,节省流量提高速度

对于后端

  • 提供通用接口,大部分 API 不用再写
  • 自动生成文档,不用再编写和维护
  • 自动校验权限、自动管理版本、自动防 SQL 注入
  • 开放 API 无需划分版本,始终保持兼容
  • 支持增删改查、复杂查询、跨库连表、远程函数等

2.8.2 APIJSON 接口展示

img

2.9 其他一些接口管理神器

由于 API 在软件开发过程中如此关键,那么对 API 的管理就显得格外重要。通过 API 管理工具和平台能够大大简化 API 管理的难度和复杂度。下面列举了一些* API 管理工具和平台,可供您参考。

2.9.1 API Umbrella

API Umbrella 是用于管理 API 和微服务的*开源工具之一。通过为不同的域授予不同的管理员权限,它可以使多个团队使用同一个 Umbrella。该平台还提供速率限制,API 密钥,缓存,实时分析和 Web 管理界面等功能。

2.9.2 Gravitee.io

Gravitee.io 是一个用于管理 API 的开源平台,这个工具是灵活的并且是轻量级的。它具有开箱即用的功能,例如速率限制,IP 过滤,跨域资源共享,即插即用选项,具有基于 OAuth2 和 JSON Web 令牌策略的开发者门户,负载平衡等。

但是,此 API 管理工具的主要功能是能够生成细粒度的报告以理解 API 的数据是如何使用的。

2.9.3 APIman.io

APIman.io 是由 Red Hat 引入的一个* API 管理平台,这个平台在 GitHub 中可以找到,为后端开发人员提供了很多便利。这包括:

快速运行 具有可分离策略引擎的基于策略的治理 异步功能 增强的结算和分析选项 REST API 可用性的管理 限速,还有其他

2.9.4 WSO2 API 管理器

WSO2 API Manager 是一个完整的生命周期 API 管理平台,可以随时随地运行。可以在企业内部和私有云上执行 API 的分发和部署。除此之外,它还提供了一些其他的便利。其中一些是:

高度定制化 管理策略易用, 为 SOAP 或 RESTful API 设计和原型的可能性, 更好的访问控制和货币化设施等

2.9.5 Kong Enterprise

Kong 是一种广泛采用的开源微服务 API 工具,它使开发人员能够快速,轻松,安全地管理一切。它的企业版带有许多特性和功能,例如:

开源插件的可用性 一键式操作 通用语言基础架构功能 强大的可视化监控功能 常规软件运行状况检查 OAuth2.0 权限,以及 更广泛的社区支持

2.9.6 Tyk.io

Tyk.io 用 Go 编程语言编写,也是公认的开源 API 网关。

它带有开发者门户,详细的文档,用于 API 分析的仪表板,API 的速率限制,身份验证以及各种其他此类规范,可帮助组织专注于微服务环境和容器化。但是,其基于商业的服务仅适用于付费版本。

2.9.7 Fusio

Fusio 是另一个开源 API 管理工具,开发人员可以使用它从不同的数据类型创建和维护 REST API。它具有高效的生命周期管理功能,例如用于管理控制的后端仪表板,详细的文档,用于传入请求的 JSON 验证以及满足用户权限的范围处理。

而且,此 APIM 平台会自动生成 OAI 和 RAML 要求,并根据定义的架构创建自定义的客户端 SDK。

2.9.8 Apigility

Apigility 由 Zend 框架设计和维护,是考虑用于 API 管理的下一个开源框架。该平台创建并展示其代码的 JSON 表示形式。它还为他们提供了不同的版本控制选项,以及通过 OAuth2 进行身份验证的简便性和包含 API 蓝图的文档。

API 接口管理,这 15 种开源工具助你管理 API Apigility

2.9.9 SwaggerHub

SwaggerHub 被 40 多个组织考虑用于管理 API,它也是最好的开源 API 管理工具之一。

该平台为后端开发领域的设计人员和开发人员提供了广泛的选择。它为他们提供了强大而直观的编辑器,可在保持设计一致性的同时提供更高的效率和速度。

此外,它还提供了智能错误反馈,语法自动完成和多种样式验证器可用性的机会。

2.9.10 API Axle

在 Exicon 的支持下,API Axle 是另一种开源,简单且轻量级的代理,为开发人员提供了很多好处,例如:实时分析 强大的身份验证, 记录 API 流量以进行统计和报告, 易于创建和管理 API 密钥,以及 支持 REST API 设计以及 Go,PHP 和 Node.js 库的使用。

2.9.11 IBM Bluemix API

该 API 管理工具使开发人员可以使用 200 多种软件和中间件模式来为混合云构建可移植且兼容的应用程序。它还提供各种预先构建的服务和强大的机制,用于调节 API 访问,管理多个 API 版本,维持速率限制以及跟踪性能指标和所涉及的每个 API 的分析。

2.9.12 Repose

Repose 是一个开源的 RESTful 中间件平台,在不断变化的 API 市场中起着举足轻重的作用。该平台为组织提供了各种 API 处理功能,包括身份验证,API 验证,速率限制和 HTTP 请求日志记录。

该 API 管理平台旨在提供格式正确且经过验证的信任下游请求的下游服务。而且,它本质上具有高度可扩展性和可扩展性,这意味着开发人员可以根据不断增长的需求轻松地使用它。

2.9.13 SnapLogic 企业集成云

SnapLogic 是一个不错的集成平台即服务(iPaaS)工具,可帮助组织获取,维持和增长其客户群。其具备的特征是:

它是快速的,多点的,并具有可灵活满足面向批处理和实时应用程序数据集成需求的选项。它具有可扩展的体系结构,其运行方式类似于 Web 服务器,但也提供了拥抱多功能性的选项。它还带有创新的数据流解决方案,鼓励组织将著名的 SaaS 应用程序如 SugarCRM 和 Salesforce)添加到其传统流程中。

2.9.14 DreamFactory

DreamFactory API 管理平台是下一个项目要考虑的最好的免费开源工具之一,其受欢迎的原因如下:

它为开发人员提供了无需手动编写 API 即可进行移动应用程序开发的方法。

它使他们能够将任何 SQL / NoSQL 数据库,外部 HTTP / SOAP 服务或文件存储系统集成到 DreamFactory 环境中,并自动获得全面,灵活,完全文档化且随时可用的 REST API。除了访问用于分页,复杂过滤器,虚拟外键,相关表联接等的 API 参数之外,该平台还为 SQL 数据库提供了详细的 REST API。

DreamFactory API 管理平台的另一个独特功能是,它可以立即将 JSON 请求转换为 SOAP,反之亦然。此外,该平台还以易于管理的形式提供了高度安全的用户管理,SSO 身份验证,CORS,JSON Web 令牌,SAML 集成,API 端点上基于角色的访问控制,OAuth 和 LDAP。API 接口管理,这 15 种开源工具助你管理 API DreamFactory

2.9.15 3Scale

最后但并非最不重要的一点是,3Scale 是此 API 管理工具列表的补充。

API 管理工具由 Red Hat 拥有,它使大小型企业都可以通过以下功能轻松安全地管理其 API:

它采用了一个分布式的云层来集中 API 程序的控制。这样可以更轻松地控制分析,可访问性,开发人员工作流程,获利等。

由于它托管在分布式云托管层上,因此具有高度的灵活性和可扩展性。

3Scale API 的 OpenShift 集成功能使您能够以自动化且封闭的方式运行高性能应用程序。这个完整的生命周期 API 管理平台使开发人员可以随时计划,设计,应用,发布,管理,分析,优化和淘汰您的 API,以提供卓越的体验。

它具有通过 Web 或移动应用程序轻松共享组织数据,服务和内容的功能。最重要的是,3scale API 管理平台为您提供了将各种加密,身份验证和授权协议注入开发环境的机会。这使后端开发公司能够为其目标用户群提供适合他们的高度安全的移动应用程序体验。

上面共享的所有 API 管理工具都是开源的,有望成为技术堆栈的有益补充。但是,为了确保您选择最适合自己的业务应用程序的需求,我们接下来将介绍一些有关选择 API 管理工具的技巧。

三、第三方API接口测试问题反馈文档

站在第三方技术人员的角度去思考他们需要什么信息来辅助他们定位问题。

  • 文档说明解释了为什么发这份文档给他们
  • 问题反馈记录汇总记录了所有可能存在问题的接口,因为有时候处理接口并不是一次性就能完善的,需要不断的协调并进行修改,文档的目的也是为了记录我们处理接口问题的过程,做留档。
  • 接口地址用于说明我们测试这个接口的时候是用了这样的url,可以让第三方技术人员判断我们是不是测错接口了。
  • 测试人员用于第三方技术人员直接于测试人员联系并做出解释。
  • 测试时间记录的测试发生的时间,方便他们查找日志文档。
  • 请求方式请求头部信息请求参数可以让第三方技术人员快速判断测试人员是否按照接口要求进行测试,此外请求猜数也方便第三方技术人员自己测试进行问题复现。
  • 响应状态码则直接告诉他们接口有没有通。
  • 实际返回值预期返回值可以让第三方技术人员进行对比我们想要得到什么样的数据。
  • 问题描述记录我们发现什么问题以及希望解决什么样的问题。

img

img

  • 个人网站:https://www.lovebetterworld.com/
  • 往后余生,只想分享一些干货,分享一些工作,学习当中的笔记、总结,并帮助需要帮助的任何人,关注我,大家一起来学习吧!

image-20210128093936368