刚接触 API 的时候,很多问题看起来都像“接口坏了”:

  • Postman 能通,前端代码不通;
  • 明明返回了 200,业务却失败了;
  • Token 带了,还是 401 或 403;
  • URL 看起来没错,结果一直 404;
  • 请求偶尔成功,偶尔超时,不知道该怪前端还是后端。

后来我发现,排查 API 问题时,最重要的不是一上来背 REST、OAuth、GraphQL 这些概念,而是先把一件事想清楚:

一次 API 请求从客户端发出去,到服务端返回结果,中间到底经过了哪些环节?

这条链路搞清楚之后,再看 API 文档里的 Endpoint、Method、Headers、Params、Body、Response、Error Codes,就不会那么懵了。

这篇文章按一次真实请求的排查思路来拆:请求怎么构造、网络怎么走、服务端怎么处理、响应怎么判断,以及新手最容易踩的坑。


先说结论:API 不是 Postman,也不是某个工具

API 可以简单理解成:软件和软件之间约定好的“沟通入口”。

调用 API,本质上就是你按照对方约定好的规则,发一个请求过去:

  • 请求哪个地址;
  • 用什么请求方法;
  • 参数放在哪里;
  • 身份信息怎么带;
  • 请求体是什么格式;
  • 返回结果怎么解析。

比如查询天气,可能是这样一个请求:

GET https://api.example.com/weather?city=shanghai
Authorization: Bearer your_token
Accept: application/json

这段请求表达的意思是:

  • GET:我要获取数据;
  • https://api.example.com/weather:我要访问天气接口;
  • city=shanghai:我要查上海;
  • Authorization:这是我的身份凭证;
  • Accept:我希望返回 JSON。

Postman、curl、浏览器里的 fetch,只是发起 API 请求的不同方式。API 本身不是 Postman。


我通常怎么验证一个接口:先跑一个最小请求

排查 API 问题时,不建议一上来就把业务代码、页面交互、状态管理都带进去。

我更习惯先用一个最小请求验证接口本身:

curl -X GET "https://api.example.com/weather?city=shanghai" \
  -H "Authorization: Bearer your_token" \
  -H "Accept: application/json"

如果服务端正常,可能会返回:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "city": "shanghai",
  "weather": "cloudy",
  "temperature": 26
}

这个最小验证至少能帮你确认几件事:

  1. URL 是否能访问;
  2. Method 是否正确;
  3. Token 是否有效;
  4. 服务端是否能返回预期格式;
  5. 问题是不是出在业务代码或浏览器环境里。

如果 curl 和 Postman 都失败,大概率先看接口参数、认证、服务端状态。

如果 curl / Postman 成功,但浏览器失败,就要重点看 CORS、前端请求头、预检请求、跨域策略。


一次 API 请求实际经过了哪些步骤

很多新手会觉得:“我点了 Send,不就是发出去然后返回 JSON 吗?”

实际上,中间通常会经过这么一条链路:

代码 / Postman / curl 构造请求
        ↓
解析 URL,准备 Method、Headers、Params、Body
        ↓
DNS 解析域名,找到服务器 IP
        ↓
建立 TCP 连接,HTTPS 还要进行 TLS 握手
        ↓
发送 HTTP 请求
        ↓
API 网关 / 负载均衡 / 服务器接收请求
        ↓
鉴权:检查 API Key、Token、签名或 Cookie
        ↓
路由:根据路径和 Method 找到处理函数
        ↓
参数校验:检查必填项、格式、权限
        ↓
执行业务逻辑:查数据库、调用第三方服务、计算结果
        ↓
生成 HTTP 响应:状态码、响应头、响应体
        ↓
客户端接收响应,解析 JSON,处理成功或失败

所以,接口失败不一定是“代码写错了”。

它可能卡在:

  • DNS 解析;
  • HTTPS 握手;
  • 网关转发;
  • Token 校验;
  • 路由匹配;
  • 参数校验;
  • 数据库查询;
  • 第三方服务调用;
  • 响应解析;
  • 浏览器跨域限制。

排查时如果不按链路看,很容易在错误方向上浪费时间。


请求到底由哪些部分组成

一次 API 请求通常由这些部分组成:

部分作用示例常见错误
URL指定访问哪个资源https://api.example.com/weather域名或路径写错
Method表示执行什么动作GET、POST方法选错,返回 405
Path Params路径里的资源 ID/users/123ID 放错位置
Query Params查询、筛选、分页条件?city=shanghai&page=1参数名写错
Headers补充说明和身份信息Authorization、Content-Type忘记带 Token
Body提交给服务端的数据JSON、表单数据JSON 格式不对
Cookies浏览器里的会话信息session_id=xxx过期或跨域问题
Timeout最多等待多久5 秒、10 秒请求一直卡住

这里最容易混的是 Path Params、Query Params 和 Body。

Path Params:资源是谁

GET /users/123

这里的 123 一般是 Path Params,表示“编号为 123 的用户”。

Query Params:怎么查

GET /users?page=1&role=admin

这里的 page=1 和 role=admin 是 Query Params,用来描述分页和筛选条件。

Body:提交什么数据

比如创建订单:

POST https://api.example.com/orders
Content-Type: application/json
Authorization: Bearer your_token

{
  "product_id": 1001,
  "quantity": 2
}

这里的 JSON 就是 Body,表示你要提交给服务端的数据。

一个简单判断:

  • 指定某个资源:多半放 Path Params;
  • 查询、筛选、分页:多半放 Query Params;
  • 创建、修改、提交复杂数据:多半放 Body。

当然,最终以 API 文档为准。


GET、POST、PUT、PATCH、DELETE 怎么选

常见 HTTP Method 可以先这样理解:

Method常见用途示例
GET获取数据查询天气、获取用户列表
POST创建数据或提交操作创建订单、登录
PUT整体替换资源替换用户完整资料
PATCH局部修改资源修改用户昵称
DELETE删除资源删除一条评论

新手可以先记住一句话:

查数据通常用 GET,提交或创建通常用 POST,整体更新用 PUT,局部修改用 PATCH,删除用 DELETE。

但真实项目里,不是所有接口都会严格按 REST 风格设计。

所以实际调用时,最可靠的做法还是看文档。文档让你用 POST,就不要因为“感觉是查询”擅自改成 GET。

否则很可能直接拿到:

HTTP/1.1 405 Method Not Allowed

Headers 经常被忽略,但很多问题都出在这里

请求头 Headers 里经常会出现这些字段:

Content-Type: application/json
Accept: application/json
Authorization: Bearer your_token
User-Agent: MyApp/1.0
X-Request-Id: req-202501010001

它们大概表示:

  • Content-Type:我发过去的 Body 是什么格式;
  • Accept:我希望服务端返回什么格式;
  • Authorization:我的身份凭证;
  • User-Agent:是谁在发请求;
  • Cookie:浏览器场景下的会话信息;
  • X-Request-Id:请求追踪 ID,排查问题时很有用。

一个典型错误是:POST JSON 时忘记设置 Content-Type。

例如:

POST https://api.example.com/orders
Authorization: Bearer your_token

{
  "product_id": 1001,
  "quantity": 2
}

如果服务端依赖 Content-Type: application/json 来解析请求体,这个请求就可能被当成格式错误。

更稳妥的写法:

POST https://api.example.com/orders
Content-Type: application/json
Authorization: Bearer your_token

{
  "product_id": 1001,
  "quantity": 2
}

另外,GET 请求通常不放 Body。POST、PUT、PATCH 更常见请求体。


服务端收到请求后,不是马上进业务逻辑

很多人排查接口时,只看“我参数传没传对”。

但服务端收到请求后,通常会先经过一堆前置步骤。

1. 网关或负载均衡

大型系统一般不会让请求直接打到某一台业务服务器上,而是先经过 API 网关或负载均衡。

这里可能发生:

  • 路由转发失败;
  • 上游服务不可用;
  • 网关超时;
  • 限流;
  • 502、503、504。

2. 鉴权和权限检查

服务端会检查:

  • API Key 是否有效;
  • Bearer Token 是否过期;
  • Cookie 是否可用;
  • 签名是否正确;
  • 当前账号是否有权限访问这个接口。

常见结果:

  • 401 Unauthorized:你是谁还没确认,或者 Token 无效;
  • 403 Forbidden:知道你是谁,但你没权限访问。

这两个状态码的排查方向不同,不要混在一起看。

3. 路由匹配

服务端会根据 Path 和 Method 找对应处理函数。

比如:

GET /weather

和:

POST /weather

在服务端可能完全是两个不同的处理逻辑。

如果路径错了,常见是 404。

如果路径对了但方法错了,常见是 405。

4. 参数校验

进入业务逻辑前,服务端通常还会校验:

  • 必填字段是否存在;
  • 字段类型是否正确;
  • 枚举值是否合法;
  • 当前用户是否能访问这份数据;
  • 分页参数是否超出限制。

这一步失败,常见是 400 或业务错误码。

5. 执行业务逻辑

真正进入业务后,可能会:

  • 查数据库;
  • 查缓存;
  • 调用第三方 API;
  • 做计算;
  • 写日志;
  • 生成响应。

所以有时你觉得“参数没问题”,但接口仍然返回 500,原因可能是数据库异常、依赖服务异常,或者服务端内部逻辑报错。


响应结果不能只看 HTTP 200

一个正常响应可能长这样:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "order_id": "A123",
  "status": "created"
}

响应通常包括三部分:

  • 状态码:HTTP 层面的结果,比如 200、404、500;
  • 响应头:说明内容格式、缓存、跨域等信息;
  • 响应体:真正的业务数据,常见是 JSON。

但这里有个坑:

HTTP 200 不一定代表业务成功。

比如服务端返回:

{
  "code": 10001,
  "message": "余额不足",
  "data": null
}

HTTP 层面可能是 200 OK,但业务层面已经失败了。

所以客户端判断成功,通常不能只写:

if (res.status === 200) {
  // success
}

至少还要看响应体里的业务字段,例如:

const res = await fetch("https://api.example.com/orders", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer your_token"
  },
  body: JSON.stringify({
    product_id: 1001,
    quantity: 2
  })
});

const data = await res.json();

if (!res.ok) {
  console.error("HTTP error:", res.status, data);
} else if (data.code && data.code !== 0) {
  console.error("Business error:", data.message);
} else {
  console.log("success:", data);
}

具体业务成功字段以接口文档为准,有的叫 code,有的叫 status,有的叫 success。


常见状态码,我会这样判断

状态码含义排查方向
200请求成功继续看业务字段是否成功
201创建成功常见于 POST 创建资源
204成功但没有响应体不要强行解析 JSON
400参数错误检查参数名、格式、必填项
401未登录或 Token 无效检查 Authorization、Token 是否过期
403没有权限检查账号权限、接口授权范围
404路径错误或资源不存在检查 URL、资源 ID
405请求方法错误看 GET/POST/PUT 是否选错
429请求太频繁检查限流规则,降低请求频率
500服务器内部错误记录请求 ID,联系服务提供方
502网关错误可能是上游服务异常
503服务不可用可能在维护、过载或临时不可用
504网关超时服务端处理太慢,或依赖服务超时

排查时不要只截一张“请求失败”的图。

更有用的是保留这些信息:

  • URL;
  • Method;
  • Query Params;
  • Headers;
  • Body;
  • HTTP 状态码;
  • 响应体;
  • 响应头;
  • 请求时间;
  • Request ID。

如果服务端日志里也有同一个 X-Request-Id,定位会快很多。


认证和权限:为什么有些 API 不能直接调

很多 API 不是公开资源,需要先证明“你是谁”。

常见认证方式有:

认证方式常见场景特点
API Key开放平台、数据接口用来简单标识调用方
Bearer Token登录后访问接口通常放在 Authorization 请求头
Basic Auth基础系统接口用户名和密码编码后发送
OAuth 2.0第三方授权登录授权流程更完整
签名鉴权支付、开放平台、政务数据按规则用密钥、时间戳、参数生成签名

Bearer Token 常见写法:

Authorization: Bearer your_token

签名鉴权会更复杂,通常要把参数、时间戳、随机数、密钥按文档规则组合,再生成签名。

这类接口不能凭感觉拼。多一个空格、参数排序不一致、时间戳格式不对,都可能导致签名失败。

安全上也要注意:

不要把私密 API Key 或密钥写在前端公开代码里,也不要提交到 Git 仓库。

这些信息一旦泄露,别人可能拿去调用你的接口额度,甚至造成更严重的安全问题。


同一个接口,用 curl、fetch、Python 分别怎么调

curl

curl -X GET "https://api.example.com/weather?city=shanghai" \
  -H "Authorization: Bearer your_token" \
  -H "Accept: application/json"

JavaScript fetch

const res = await fetch("https://api.example.com/weather?city=shanghai", {
  headers: {
    Authorization: "Bearer your_token",
    Accept: "application/json"
  }
});

const data = await res.json();

console.log(res.status);
console.log(data);

Python requests

import requests

res = requests.get(
    "https://api.example.com/weather",
    params={"city": "shanghai"},
    headers={
        "Authorization": "Bearer your_token",
        "Accept": "application/json"
    },
    timeout=10
)

print(res.status_code)
print(res.json())

如果放到 Postman 里,对应关系也很直接:

  • Method 选 GET;
  • URL 填接口地址;
  • Params 填 city=shanghai;
  • Headers 填 Authorization 和 Accept;
  • 点击 Send;
  • 看状态码、响应头和响应体。

这些工具之间没有本质区别,核心都是构造一条 HTTP 请求。


Postman 能通,浏览器代码不通,优先看 CORS

这是 API 新手非常容易遇到的问题。

典型现象是:

  • Postman 请求正常;
  • curl 请求正常;
  • 浏览器控制台报错;
  • 前端代码拿不到结果。

这时候不要马上怀疑接口挂了,先看是不是 CORS。

原因是:

浏览器有同源策略,Postman 没有浏览器的 CORS 限制。

也就是说,Postman 能请求成功,不代表前端页面一定能直接请求成功。

如果浏览器控制台出现 CORS 相关报错,可以从这些方向处理:

  1. 让 API 服务端配置允许指定域名访问;
  2. 前端不要直接请求第三方接口,而是通过自己的后端服务转发;
  3. 不要在浏览器里暴露私密 API Key;
  4. 检查请求方法和自定义 Header 是否触发了预检请求。

尤其是带 Authorization、自定义 Header、非简单请求方法时,浏览器可能会先发一个预检请求。

所以 CORS 不一定说明 API 有问题,更多时候是浏览器安全策略在正常工作。


新手最容易踩的 10 个坑

1. URL 路径写错

可能少了版本号:

/api/users
/api/v1/users

也可能少了资源名、环境域名写错、路径大小写不一致。

2. Method 选错

文档写的是 POST,你用了 GET,很可能返回:

405 Method Not Allowed

3. 参数放错位置

把 Query 参数写进 Body,或者把应该放 Body 的 JSON 拼到了 URL 后面。

排查时先看文档里的参数位置:

  • path;
  • query;
  • header;
  • body。

4. 忘记设置 Content-Type

尤其是发 JSON 的时候:

Content-Type: application/json

不写的话,服务端可能无法按 JSON 解析。

5. JSON 格式错误

比如少逗号、多逗号、字段类型不对。

{
  "product_id": 1001,
  "quantity": "2"
}

如果文档要求 quantity 是数字,而你传了字符串,就可能校验失败。

6. Token 过期

401 时不要只看“我带了 Token”。

还要看:

  • Token 是否过期;
  • Token 类型是否正确;
  • 是否少了 Bearer;
  • 是否复制时多了空格或换行;
  • 当前环境是否匹配。

7. 只看 HTTP 200,不看业务错误码

HTTP 200 只是说明 HTTP 请求成功返回,不代表业务成功。

业务判断还要看响应体。

8. Postman 能通,浏览器不通,不知道是 CORS

这类问题前面已经说过,核心是浏览器安全策略,不是 Postman 和浏览器“能力不同”。

9. 忽略分页

很多列表接口默认只返回第一页。

如果你只拿到几十条数据,不一定是数据丢了,可能是没处理分页参数:

GET /users?page=1&page_size=20

10. 没有设置超时、重试和限流

请求一慢就一直卡住,或者失败后无节制重试,都是问题。

例如 Python 里建议显式设置超时:

requests.get(url, timeout=10)

对于下单、支付、扣库存这类接口,还要特别注意幂等性。

网络失败后不能无脑重试,否则可能造成:

  • 重复下单;
  • 重复扣款;
  • 重复扣库存。

有些接口会要求传类似:

Idempotency-Key: unique-request-id

用来识别重复请求。这个一定要按文档来。


我自己的 API 排查顺序

遇到接口问题时,我一般按这个顺序走:

第一步:确认请求有没有发出去

看浏览器 Network、Postman Console、服务端日志。

重点确认:

  • URL;
  • Method;
  • Headers;
  • Query;
  • Body。

第二步:用 curl 或 Postman 做最小复现

把业务代码先拿掉,只保留最小请求。

如果最小请求失败,问题多半在接口调用本身。

如果最小请求成功,再回到代码里看请求构造和运行环境。

第三步:看 HTTP 状态码

先判断是:

  • 参数问题;
  • 认证问题;
  • 权限问题;
  • 路由问题;
  • 限流问题;
  • 服务端问题;
  • 网关问题。

第四步:看响应体业务字段

不要只盯着 200。

重点看:

  • code;
  • message;
  • data;
  • error;
  • request_id。

第五步:浏览器场景单独看 CORS

如果 Postman 能通、浏览器不通,优先看:

  • 是否跨域;
  • 服务端是否允许当前 Origin;
  • 是否允许对应 Method;
  • 是否允许自定义 Header;
  • 是否涉及 Cookie;
  • 是否有预检请求失败。

第六步:保留请求 ID

如果要找后端或服务提供方排查,最好带上:

X-Request-Id: req-202501010001

没有请求 ID,也至少提供请求时间、URL、状态码和响应体。


总结:看懂一次请求,就能看懂大多数 API 文档

API 入门不需要一开始就钻进各种复杂概念。

更重要的是先建立这条主线:

客户端构造请求
  → DNS 和连接
  → 发送 HTTP 请求
  → 服务端鉴权、路由、校验、处理
  → 返回状态码、响应头、响应体
  → 客户端解析结果并排查问题

读 API 文档时,优先看这几项:

  • Endpoint:接口地址;
  • Method:请求方法;
  • Auth:认证方式;
  • Params:路径参数和查询参数;
  • Body:请求体格式;
  • Response:响应结构;
  • Error Codes:错误码和处理方式。

当你能把一次请求从发出去到返回结果完整讲清楚,后面再学 REST、GraphQL、WebSocket、API 网关、OAuth 2.0,会轻松很多。

很多 API 问题,本质上不是“接口玄学”,而是链路里某一步没有被看见。把链路拆开,问题通常就会清楚很多。


豪爽的茄子
1 声望0 粉丝