调试 REST API 使用者的最佳实践

embedded/2024/9/18 12:27:20/ 标签: 测试工具, 单元测试, 集成测试

如果API反馈出意想不到的结果,该怎么办呢?这个问题是出在用户输入、API本身,还是其他完全无关的方面呢?对于 API 用户来说,调试意味着识别和修复单个 API 调用或调用序列中的问题。在很多情况下,你正在调试的代码可能不受你的控制,并且受可观察对象的支配。除了在访问 API 时可能会遇到意想不到的行为外,你还可能在解析输出或传递变量时犯错。

在本文中,我们将深入探讨更快速、更可靠地调试 REST API 的方法和原则。

什么是API调试?

调试过程旨在了解输入和输出之间的关系。大部分工作都是根据可以观察到的情况来定位问题的根本原因。如果你将来自不同提供商或访问不同资源的一系列 API 调用串联在一起,这可能会变得很棘手。

理想情况下,你会拥有一个强大的测试和监控系统,可以在出现问题时向你发出警报,并指出问题所在。但即便你不具备这种可观察性,采用一致的方法也可以减少发现和解决问题所需的时间和精力。

以下是一种识别bug的方法:

  • • 隔离 API 问题

  • • 检查状态信息

  • • 更深入地检查数据

我将在 Postman 中演示这些调试示例,但你也可以使用自己喜欢的开发工具或 API 客户端。

隔离 API 问题

第一步是隔离 API 问题,并确定问题是源于调用 API、API 本身、处理输出,还是与之完全无关。在你最喜欢的开发工具或 API 客户端中重现这个问题,以便进行更深入的检查。这样你就可以更轻松地检查和调整请求参数、标头和正文,并与反馈进行比较。如果无法可靠地辨别输入和输出之间的关系,那么问题可能不在 API 调用本身。例如,可能是第三方服务或基础设施的变更导致了意外的状况。

在 Postman 等开发工具中重现问题,以便进行更深入的检查

如果要将 API 调用导入到 Postman中,可以粘贴 cURL 命令作为原始文本。您还可以使用代理采集一系列调用,以便重放或录制。

查看状态信息

当你与 API 对话时,服务器会返回一个 HTTP 状态代码,表示你的 API 请求的状态。状态代码和错误信息由 API 提供商决定,因此它们的意义和准确性各不相同。但大多数 API 提供商都遵循既定惯例,即使用状态代码的第一位数字来定义响应的类别。例如,状态代码为 400 表示客户端出现问题。这意味着你可以更新请求以潜在地解决该问题。状态代码为 500 表示服务器有问题。除了验证你访问的是正确的资源并稍后检查外,你能做的不多,除非你也是 API 提供商。

假设服务器反馈了可靠的状态信息,这是我们追踪bug源头的第一条线索。以下是一些常见的客户端错误代码,以及遇到这些错误时可以采取的措施:

400 错误请求:查找语法错误,如错别字或错误的 JSON 主体。

401 未授权:请确认您对目标资源是否有有效的身份验证凭据,并检查标题值的语法。

403 禁止:检查您的权限和范围,以确保您有权访问该资源。

418 我是一个茶壶: 可能表示请求是提供商不想处理的请求,如自动查询。

429 请求太多:查看文档以了解速率限制或稍后再试。

HTTP 状态代码 400 表示客户端出错

更深入地检查数据

下一步是深入挖掘并验证您的假设。你可以验证每个请求的格式和每个响应的解析是否正确。当你通过一系列API调用传递数据时,你还可以验证变量是否被正确定义和引用。

以下是处理 HTTP API 时常见的问题:

  • • 格式不正确的JSON:新用户在发送 JSON 主体时经常会犯一些错误。在JSON 字符串中的单引号是无效的,因此请确保将字符串和属性名用双引号括起来。此外,JSON 不支持注释,所以要么缩小注释,要么就别添加注释。

  • • 序列化数据:REST API 经常以 JSON 对象的形式存储和发送数据。为使数据正常传输,请确保使用 JSON.stringify() 对数据进行编码,并使用 JSON.parse() 对数据进行解码。此外,服务器可能会要求你设置一个 Content-Type 标头,其值为 application/json。进一步检查后,如果看到类似 [object Object] 或 Unexpected token 等值,则表明序列化和反序列化不当。

  • • 类型转换:在准备发送请求或解析响应时,可以将数值从一种类型转换为另一种类型。根据编程语言的不同,对字符串进行数学计算可能会失败,但将数值转换为数字后,就可以处理数据了。

  • • 提取信息:一旦使用JSON.parse()得到反序列化JSON响应,就可以使用句点点或括号符号访问属性,并在数组中循环。如果你试图访问复杂结构中的深层嵌套信息,可能需要逐步将其分解,以便精确地引用该信息,并确保不会深入到研究未定义的内容中。

  • • 身份验证与授权:身份验证验证用户的身份,授权则确认用户拥有访问资源的权限。如果请求中包含了正确的授权标头,但仍无法访问资源,请再次仔细地检查与凭证相关的权限和范围。

  • • 内容类型标头:Content-Type 和 Accept 标头有助于客户端和服务器之间的内容协商。Content-type请求标头告诉服务器客户端发送的信息类型。另一方面,Accept请求标头告诉服务器客户端可以理解的内容类型。有些API需要特定的请求标头,并且只适用于与特定的内容类型配合使用。

对于这些常见错误,你可以依靠语法加亮显示、检查程序和其他检查功能来来提供更多的问题可见性。开发人员控制台还能为应用程序的网络调用和日志语句提供更多可见性,以便进一步帮助你隔离输入、输出以及从一个调用到另一个调用的数据传递问题。例如,如果你有一连串同步或异步调用序列,记录关键节点的值或设置条件断点可以帮助你快速定位问题。在整个调用执行过程中使用 console.log() 等控制台语句可以进一步验证解析输出的假设。

使用控制台来查看网络调用、调用执行顺序和变量值

调试策略的类型

有许多调试策略可以缩小问题原因的范围。这些策略大致可以分为三大类。

暴力破解策略

如果你对系统的可观察性有限,这意味着你需要调整和记录一切。在整个 API 调用序列的某些点添加策略性日志语句可能会有所帮助。然而,由于解释日志数据需要花费更多的时间,日志数量的收益正在递减。

回溯策略

这种策略是指从第一次观察到错误的点开始回溯,以找到根本原因。同样,你可以从显示您所期望的行为的 API 调用开始,然后逐步查看后续调用,直到找到bug为止。当你对可能导致问题的原因有了合理的假设时,这种策略就会很有效,但当错误远离根本原因时,这种策略就不那么有效了。

分而治之策略

在复杂的系统中,将系统分成较小的部分可以让你更容易发现问题。二分搜索就是这种策略的一个例子,你可以在较长的调用序列中间输入日志语句或断点。如果在断点处没有出现缺陷,则对下半部分的调用重复这一过程,依此类推。另一种策略是使用模拟服务器来隔离被测系统。你可以依靠模拟响应来实现外部依赖关系,或为你的方案提供一个起点。

进入调试思维模式

经过一段时间后,如果只关注了问题但并没有取得实质性的进展,可能会适得其反,因为你会"只见树木,不见森林"。以下策略可以帮助你获得更有效的调试思维模式。

  • • 橡胶鸭式调试:向他人阐述问题和假设,这可能能够帮助你转换自己的视角,迫使你放慢速度,明确地陈述你的假设。

  • • 从集中模式切换到分散模式:切换到一种不同的活动,比如远足,这能够让你的大脑进入不同的状态。当你的大脑被动地建立新的连接,可能会产生创造性的见解,这就是分散的学习模式。这就是为什么你在洗澡时或刚睡醒时会有最好的想法的原因之一。

调试时省时省力又省心

无论你是刚接触 REST API,还是经验丰富的老手,采用一致且有条不紊的方法进行调试都能节省时间和心力。你所选择的调试策略取决于系统的可观察性。如果你的系统已通过预定义的日志和堆栈跟踪进行了广泛的监控,你就可以快速发现问题,并可能能够立即发现bug。如果没有这些措施,你可以简化问题以缩小搜索范围,并利用其中一些调试策略来提高可见性。


http://www.ppmy.cn/embedded/94838.html

相关文章

探索Java并发编程

1. 引言 1.1 并发编程的重要性 并发编程是Java开发中的核心领域,它关乎程序的性能和响应能力。在多核处理器时代,充分利用系统资源,编写高效、可扩展的多线程程序变得尤为重要。并发编程让应用程序能够同时执行多个任务,提高效率…

Linux SystemV(共享内存(*)、消息队列、信号量)

个人主页:仍有未知等待探索-CSDN博客 专题分栏: Linux 目录 ​编辑 一、共享内存 1、原理 理解: 2、操作具体理解 1.概括 2.创建共享内存 共享内存的生命周期? key是什么? 进程怎么知道,共享内存是…

Vlog学习记录03:手机拍拍拍

点击上方蓝字关注狂神说 有很多人加我问课程,我想我要说明一下:这个系列文章仅仅是我自己的学习心得笔记,我不出什么拍摄课程,也没那个专业能力。在这个自媒体时代,我觉得这是每个人都要掌握的生活技能而已&#xff0c…

java中RSA分段加解密及Data must not be longer than异常处理

谈到RSA非对称加密,作为开发的我们第一想到的是安全,几乎不会被破解,以及公钥加密,私钥解密这些。在Java代码中,我们常使用一些现成的工具类如hutool中提供的工具类、网上在线的或者博客上的RSAUtils工具类来实现公钥私…

快乐数 | LeetCode-203 | 一个简单的数学题!| Floyd判圈算法练习题 | 哈希集合 | 数学

🙋大家好!我是毛毛张! 🌈个人首页: 神马都会亿点点的毛毛张 📌如果不知道Floyd判圈算法这道题做起来一点也不快乐!🎈前置知识:图解Floyd判圈算法 | 判断链表或者迭代函数是否有环…

《SQL 中复杂条件多表关联查询的性能优化秘籍》

在当今数据驱动的时代,数据库的操作和查询性能对于企业的业务运营至关重要。当面对复杂的业务逻辑和大规模的数据时,实现复杂条件的多表关联查询并确保高效的性能成为了数据库开发者和管理员面临的重要挑战。 多表关联查询是在关系型数据库中获取全面和…

Android 13 使用 cmd media_session 命令调节音量

基于 Android 13 , cmd media_session usage : console:/ # cmd media_session usage: media_session [subcommand] [options]media_session dispatch KEYmedia_session list-sessionsmedia_sessio…

【模电笔记】——信号的运算和处理电路(含电压比较器)

tips:本章节的笔记已经打包到word文档里啦,建议大家下载文章顶部资源(有时看不到是在审核中,等等就能下载了。手机端下载后里面的插图可能会乱,建议电脑下载,兼容性更好且易于观看),…

代码随想录算法训练营第三十五天|背包问题理论基础、携带研究材料、分割等和子集

背包问题理论基础 1.背包问题概述 01背包:有n种物品,每种物品只有一个; 完全背包:有n种物品,每种物品有无限个; 多重背包:有n种物品,每种物品的个数各不相同。 2. 01背包 有n件…

红黑树(RBTree)

RBTree 1. 红黑树的概念和性质2. 红黑树的实现2.1 结点的定义2.2 插入2.3 判断红黑树2.4 其他接口 3. 迭代器4. 完整代码RBTree.htest.cpp 1. 红黑树的概念和性质 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以…

简单的docker学习 第13章 CI/CD与Jenkins(下)

第13章 CI/CD 与 Jenkins 13.13 自由风格的 CI 操作(最终架构) 前面的架构存在的问题是,若有多个目标服务器都需要使用该镜像,那么每个目标服务器都需要在本地构建镜像,形成系统资源浪费。若能够在 Jenkins 中将镜像相撞构建好并推送到 Har…

搭建高可用OpenStack(Queen版)集群(十)之部署分布式存储Ceph

一、Ceph知识点学习 Ceph知识点学习:https://www.cnblogs.com/happy-king/p/9207509.html 二、部署分布式存储Ceph 一)设置yum源 在全部控制与计算节点设置epel与ceph yum源 epel源:repo安装包下载_开源镜像站-阿里云 ceph源:cep…

B树和B+树的插入、删除

1. B树 1.1 B树的定义 树也称树,它是一颗多路平衡查找树。我们描述一颗树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,用字母表示阶数。当取时,就是我们常见的二叉搜索树。 一颗阶的树定义如下: 每…

vim中跳转头文件

在 Vim 中&#xff0c;你可以通过以下几种方式跳转到系统头文件的定义&#xff1a; 1. 使用 gf 命令 在 Vim 中&#xff0c;将光标移动到头文件的名称上&#xff08;例如 #include <iostream>&#xff09;。按 gf&#xff08;goto file&#xff09;&#xff0c;Vim 会尝…

JaCoCo 命令行界面 (CLI) 详细分析与总结

概述 JaCoCo 提供了一个命令行界面&#xff0c;允许用户在命令行中执行基本操作。命令行工具及其所有依赖项打包在 jacococli.jar 中&#xff0c;并随 JaCoCo 下载提供。执行这些工具需要 Java 1.5 或更高版本。 注意事项 虽然提供了 instrument 命令&#xff0c;但 JaCoCo …

【C++ Primer Plus】学习笔记 5【指针 上】

文章目录 前言一、指针和自由存储空间1. 声明和初始化指针2. 指针的危险3. 指针和数字4. 使用 new 来分配内存5. 使用 delete 释放内存6. 使用 new 来创建动态数组1.使用new创建动态数组2.使用动态数组 二、指针、数组和指针算术1. 指针小结1.声明指针2.给指针赋值3.对指针解除…

Micrometer Tracing和Zipkin实现链路追踪

一、为什么使用链路追踪 在微服务框架中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错误都会引起整个…

PCDN管道收益项目详谈二运营商资管图

如何高效利用运营商资管图&#xff1a;避免宽带安装陷阱&#xff0c;优化网络性能 上一期我们讨论了如何通过谈判技巧和心理洞察与运营商打交道&#xff0c;轻松获批数百条宽带。错过的朋友可以回顾一下。今天&#xff0c;我们要深入探讨运营商的资产管理系统&#xff08;简称…

【STM32 FreeRTOS】时间延时函数

相对延时&#xff1a;指每次延时都是从任务执行函数vTaskDelay()开始&#xff0c;延时指定的时间结束。 绝对延时&#xff1a;指每隔指定的时间&#xff0c;执行一次调用vTaskDelayUntil()函数的任务。换句话说&#xff1a;任务以固定的频率执行。 void StartMyTask1(void *a…

在原生未启用kdump的BCLinux 8系列服务器上启用kdump及报错处理

本文记录了在原生未启用kdump的BCLinux 8系列操作系统的服务器上手动启用kdump服务及报错处理的过程。 一、问题描述 BCLinux 8系列操作系统&#xff0c;系统初始化安装时未启用kdump服务&#xff0c;手动启动时报以下“No memory reserved for crash kernel”或“ConditionK…