调试 Web API 问题的四个步骤

本文是解决 Web 服务常见问题的分步诊断指南。本文假设你已有一个 web 客户端和一个 web 服务器,并尝试让两者进行通信,但是遇到了问题。
Web 服务和其复杂性
编码是件复杂的事,一不小心就会出错。但是当你把网络通信加入进来后,除了编译器和逻辑错误外,还会出现更多的问题。
一些可能出问题的事包括:
- 网络问题导致你能不与其他服务器通信
- 另一台服务器可能因为维护而停机
- 服务器的新代码可能需要你修改调用其 API 的方式
- 你请求的数据可能不是服务器能接受的有效格式(例如尝试在业务关闭的那天进行预约)
- 用户可能没有填写所需的数据
- 你的登录信息可能丢失或者过期,需要你重新登录
所有的这些问题都可能破坏已经可用的 API,因此可以想象,让新的 API 首次运行是多么的困难。
但是,如果您遵循一个合理的诊断流程,就可以解决大多数 Web 服务问题。
诊断 API 问题
以下是我在诊断问题时学会遵循的四个步骤:
- 从请求(Request)和响应(Response)中获取信息
- 确定问题区域
- 分而治之
- 调试并解决问题

我们来依次介绍每一步。
第一步:从网络请求获取信息
诊断网络问题首先要做的就是获取发出的请求和返回的响应信息。
如果你发出的是一个不需要身份验证的 GET 请求,你可以直接在浏览器里进行,并打开浏览器的开发者工具同时选中网络(Network)选项卡。查看 Chrome 官方教程 获取关于此功能的更多信息。

Chrome 的网络工具(上图所示)允许你选择一个特定的请求并在 headers 选项卡中获取更多的详细信息,包括:
- 请求的 URL
- 请求方法
- 结果状态吗
- 请求和响应的头信息
- 请求的载荷(请求体)
预览(Preview)和响应(Response)选项卡同样提供了返回数据的更多信息,如下图:

有时你需要诊断的不是 GET 请求或者是需要身份验证的请求。在这些情况下,我喜欢使用优秀(并且免费)的 Postman 应用进行测试。

在 Postman 中,你可以指定要使用的请求方法、URL、设置你需要的标头(例如身份验证令牌),提供消息正文(确保将 application/json 类型的内容设置为 raw)。
完成后,单击“发送”将发出你的请求并在下方窗格中显示结果,你可以查看请求的状态码、响应正文和响应标头等信息。
或者,如果你的应用从代码进行调用,根据你所使用的用于发送网络请求的库,你也可以使用调试器来获取请求和响应的详细信息。但是,如果你要这样做,请务必小心,因为开发人员很容易假设他们发出的请求信息是不正确的。Postman 消除了这个问题,它允许你独立于客户端代码验证 Web 服务的行为。
查看 Postman 精彩的学习中心,了解更多如何开始使用的信息。
第二步骤:确定问题区域
现在你已经获得了问题的具体的请求和响应信息,就可以开始定位哪里出问题了。
根据我的经验,确定错误发生的位置是最有帮助的——是客户端发送了错误的请求还是服务端返回了错误的响应。一旦你可以定位到其中一侧,问题就会变得不那么棘手。

在查看请求和响应的信息时,验证请求是否正确非常重要。
下面是我经常检查的地方:
- 请求是否使用了正确的 URL?
- 是否使用了正确的请求方法? 例如,在应该执行 POST 时执行了 GET?
- 如果请求方法是 POST 或 PUT,是否包含了请求正文?
- 请求正文是否正确? 即使是像发送字符串“1”而不是数字 1 这样的问题也会产生影响。
如果你确定请求在所有方面看起来都没问题,再检查响应。 响应可以告诉您很多有关服务器如何处理请求的信息。 有两个与响应相关的非常重要的信息:响应状态码和响应正文。
使用响应状态码
响应状态码是一个从 100 到 599 的代码。作为开发人员,你最有可能看到的状态代码在 200-299 范围、400-499 范围和 500-599 范围内。
这些主要的状态代码范围中每个都有不同的含义。 200 系列状态代码通常用于没有出错的情况。 另外,400 和 500 系列状态代码都表示出现问题或请求无效。 400 系列状态代码表示服务器认为请求有问题,而 500 系列状态代码通常表示服务器出现问题。
尽管看起来头疼,但这些状态代码可以快速地把发生的问题传达给像你这样的开发者。 因此,掌握它们很重要。 通常,如果状态码不在 200-299 范围内,则说明出现了问题,如果不是显而易见的错误,就需要对其进行诊断了。
我们将在后面的第四步中介绍更多开发中见到的状态码。
使用响应正文
响应状态是一个简单的数字代码,但响应的 正文 可以是任何内容,从完全空白到简单的错误消息到复杂的 JSON 对象。 响应正文的内容取决于您使用的服务器技术(例如,其中一些会自动为无效请求生成响应)和你的 Web 服务所返回的响应数据。
当你检查响应正文时,需要检查两件事:
- 响应体是否告诉我什么有意义的内容? 例如,此响应中是否包含错误消息?
- 响应正文看起来正确吗? 如果不是,你的服务器可能有错误。 如果是,你的 API 可能工作正常,但你可能在处理 API 调用结果时出现错误。
根据你获得的响应正文,如果你怀疑你的服务器可能没有返回正确的结果,最好的办法是在你的服务器上设置断点,来分步执行并检查发送该请求时发生了什么。
第三步:分而治之
你现在应该对客户端发送给服务器的消息以及服务器返回的响应有了一个清晰的了解。
这时,你的主要目标是将问题一分为二。
由于软件系统非常复杂,因此排除某些因素并专注于其余因素可能会有所帮助。 当涉及到 Web 服务时,这个原则尤其有用。
你现在应该有足够的信息来回答下面的问题:
- 客户端是否向服务器发送了正确的消息?
- 服务器是否返回了成功的状态代码和可用的响应正文?
如果你对第一个问题的回答是否定的,那么你的问题至少来自于未发送有效请求的客户端代码。
如果您对第二个问题的回答为“否”,那么你的服务器没有正确处理来自客户端的请求,原因可能出在请求(内容或身份验证)或服务器上的错误或逻辑缺陷。 在第 4 步中查看更多详细信息来继续诊断,但通常如果状态码在 400 段中,你应该检查客户端,如果状态码在 500 段中,您应该检查服务器。
如果服务器返回 200 的状态码但数据无效,这通常表明服务器端存在逻辑问题,你应该检查服务器。
在极少数情况下,客户端发送的请求没有问题并且服务器也正确地响应了,但你的应用程序中仍然出现了问题,你可能在客户端处理响应的数据时遇到问题,应该检查那部分的代码。
第四步:调试并解决问题
这时,你已经只关注客户端或者服务器了。 恭喜,现在你的工作变得更简单了。 你后面的工作是通过调试确认问题并进行适当的修复。
不幸的是,考虑到实际工作中可能存在诸多不同的问题以及 Web 服务中有着诸多不同的状态码,这使得*我(作者)*编写调试部分的内容变得困难。
当问题复杂时,我喜欢使用图示,所以让我们看一下我创建的流程图。 此流程图从图表顶部的橙色圆角矩形开始,然后根据图表中的判断条件决定从那里开始流动。 准备好你的状态码并按照下表进行操作:

你可能需要点击来放大图片或者右键单击图片再新标签页打开,可以获得最佳查看效果。
如果你按照这个流程操作,你可能会看到一个包含你遇到的错误的蓝色方框,以及至少一个你可以采取的建议方案或额外步骤的绿色方框。
我在下方列出了一些最常见的问题以及解决问题可以采取的步骤,如果你遇到的错误不在下边的内容里,你可能需要参考 Mozilla 的[状态代码列表](https:// developer.mozilla.org/en-US/docs/Web/HTTP/Status)或进行一些网络搜索。
常见问题
让我们来看看一些常见问题的状态代码以及解决办法。
无响应/连接被拒绝
如果你的服务器根本不返回响应,你通常会收到某种形式的“无法连接到服务器”的消息。 这通常是因为你没有连接到互联网或者你的服务器没有运行。
另一个造成这种情况的原因是服务器暂停在了断点上,导致不能处理后续的请求。
确保你的互联网连接可用并且你的服务器没有卡在断点上...
200–299 状态码
如果你收到了一个200系列的状态码,这意味着服务器认为一切正常。但是,如果你正在调试并试图找出一切正常的原因,则意味着发生了以下情况之一:
- 服务器返回了 200 系列的响应,但没有返回正确的响应正文
- 服务器正在返回 200 系列响应和正确的正文,但用户侧仍显示错误
在第 1 种情况下,你应该调试服务器看它如何响应请求的,因为某种形式的逻辑错误,你的程序没有完全按照预期的情况执行。
在第 2 种情况下,你应该调试客户端处理服务端响应的代码,因为 API 看起来是工作正常的。为了发现问题,你可能需要退后一步,想想你的应用应该如何在上层工作。
400 — 无效请求
无效请求通常发生在客户端发送的信息不是服务端所预期的时候。这可能是由于遗漏了部分数据或者数字使用了字符串形式的值而不是数字,也可能是发送了无效邮政编码等等任何情况。
通常当服务端返回了 400 无效请求,响应正文里通常会告诉你请求里哪部分是无效的。同样你也可以检查一下请求正文,确保请求正文的格式有效,所有的参数都没问题并且使用了正确的数据类型。
401 — 未授权
当客户端请求的是受保护的资源,但服务器无法验证客户端的身份时,就会出现此错误。 通常,当客户端没有在请求标头中包含身份验证令牌时会出现这种情况,但如果身份验证令牌过期了,也会出现这种情况。
检查你的请求,确保你发送了正确的身份验证信息给服务端
如果你调用的是一个外部的 API,你可能需要查询他们的文档或者联系对方了解他们希望你用什么方式进行身份验证。
403 — 禁止访问
服务端不确定你的身份且需要登录才能获取资源时会出现401 未授权错误,而 403 错误是在服务端确定你的身份,但不允许该身份访问特定资源时会发生的。
可以这样想:你的服务器是一个站在非常重要的门口的保安。 一个请求走到门口,但保安拒绝其进入。 然后请求会说“你知道我是谁吗?”。 如果警卫回答“不知道”,那就是 401 未经授权。 如果守卫回答“知道,但你不能进入这里”,那就是 403 禁止访问。
403 禁止响应根本不是错误。 这种情况是你的应用程序的安全防护正在阻止对某些内容的未授权的访问。 如果你认为你应该有权访问这些内容,请仔细检查你的用户权限以及服务器对你请求的资源强制执行的权限。
404 — 资源不存在
这个是开发圈以外最常见的状态码,因为当链接无效或 URL 输入不正确时,它就会出现在浏览器的报错里。
404 Not Found 响应代码在 API 开发中以两种方式之一发生:
- 你调用了服务器上不存在的 API 接口
- 你调用了一个有效的 API 接口,请求的是一个不再存在的资源
第一种情况最为常见,第一种情况是最常见的,我们来看一下。 如果我有一个服务器支持在像 /api/menu 这样的 URL 上进行 GET 请求,然后你对 /api/menuitems 发出了 GET 请求,那么服务器就会返回 404 告诉你没有处理 /api/menuitems 的 GET 请求的接口。 在这种情况下,最好将请求的 URL 与服务器支持的 URL 进行比较。
当你尝试获取不存在的特定内容时,会发生第二种情况。 例如,如果我对 /api/products/5003 发出 GET 请求,但数据库中最大的产品编号是 250,服务器将无法找到我正在寻找的产品,并且会合理地返回一个 404 告诉我它不存在。
在这两种情况下,都应该仔细检查客户端的逻辑并确保你请求的是正确的 URL。 使用浏览器中的网络选项卡有助于验证请求的 URL 是否与您认为的一致。
405 — 不允许的方法
405 发生在服务器的一个接口支持一个特定的方法,例如 GET,但是你用了不同的方法来请求它。例如,服务器的/api/menu 接口支持 GET 请求,我向它发送了一个 DELETE 请求,我就会收到一个 405 错误。
通常,当你使用不正确的 URL 进行操作或服务器尚未实现您尝试调用的方法时,会发生 405。 仔细检查 API 并确保你的 URL 正确。
415 — 不支持的媒体类型
这个错误最有可能发生在 Postman 里。 在 Postman 中,如果忘记将请求正文的内容类型更改为 JSON,则很可能会收到 415 响应。
这是因为服务器不知道如何处理你发送的数据。确保你在 Postman 里设置了正确的内容类型。
如果你在代码里遇到了这个错误,很可能是没设置请求里的 content-type 头信息,或者把 content- type 设置成了服务器不支持的类型。然而,这不是一个经常出现的问题,所以我不会进一步讨论它。
420 / 429 — 请求过多
一些服务器支持速率限制,这是一种限制传入请求的方法,并确保特定时间跨度不会因为一个用户过多的请求导致 API 过载。
通常,如果您遇到 420 或 429 响应代码,则意味着你过于频繁地调用了服务器,并且需要减少发送的请求数量或需要升级付费级别。
更多详细信息,请查阅你的 API 文档。
其他 400 系列状态代码
有时,您会收到 400-499 之间未列出的状态码。 这往往是在使用特殊的 API 时的具体场景的错误。有关特定错误代码的信息,请参阅 Mozilla 的文档,并查阅你在使用的 API 的文档。 如果 API 由别人维护,你可能需要联系他们的支持团队。
500 — 服务器内部错误
这通常发生在尝试处理请求时服务器代码中抛出了异常时。 查看响应正文,看看它是否告诉您错误发生的位置。 您还可以在您的服务器上放置一个调试器断点并逐步执行,直到复现错误。
一旦确定了有问题的代码行,请进行修复并再次测试。
其他 500 系列状态码
有时您会得到 500 以上的响应。这些通常是由网络问题、服务器暂时离线等造成的,并且更难定位。 有关具体错误代码,请参阅 Mozilla 的文档,并根据需要咨询你的网络管理员。
第五步: 不断地重复
是的,我知道,我声称这是一个四步过程。 这是撒谎,因为当一个问题得到解决时,它可能不会是你的过程的结束。
在解决 Web 服务中的问题后,如果遇到新问题,再次测试并返回到第一步是很重要的。
软件是很复杂的,很多时候可能有不止一个问题阻止某项工作。有时,您需要按顺序解决两三个问题,然后您的应用程序才能正常工作。
如您所见,API 虽然复杂但是功能强大。它的学习曲线很陡峭,但这些技术对现代 Web 开发至关重要。
了解 API 和 API 调试是所有类型开发人员的核心技能,这就是我们在 Tech Elevator 上如此强调它的原因。
除了开发人员外,质量保证专业人员、项目/产品经理、系统管理员和技术领导等技术专业人员都需要深入了解 API 的基础知识以及它们给开发团队和开发项目带来的挑战。
简而言之,学习 API 至关重要,也是必须要做的事。 希望本指南对你有所帮助。
最初于 8 月 30 日在 killalldefects.com 上发布 , 2021.