调用 API 时,很多问题不是接口本身坏了,而是请求头 Header 没配对。
最常见的两个 Header 是:
Authorization:告诉服务器"我是谁、有没有权限"Content-Type:告诉服务器"我提交的 Body 是什么格式"
如果这两个字段写错,经常会遇到:
401 Unauthorized403 Forbidden415 Unsupported Media Type- 后端收不到参数
- Postman 能通,浏览器代码不通
这篇按实际配置流程讲清楚:Header 写在哪里、Authorization 怎么填、Content-Type 怎么选,以及在 Postman、Apifox、curl、fetch、Axios 里如何验证。
1. 一个完整 API 请求长什么样?
先看一个典型的 POST JSON 请求:
POST /users HTTP/1.1
Host: api.example.com
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Accept: application/json
{"name":"Tom","age":18}
可以把它拆成三部分:
请求行:POST /users HTTP/1.1
请求头:Authorization、Content-Type、Accept
请求体:{"name":"Tom","age":18}
也就是说:
POST /users表示请求方法和接口路径Authorization、Content-Type、Accept是 Header- 最后一行 JSON 是 Body,也就是提交的数据
一个很重要的原则:
Header 放请求元信息,不放业务参数。
例如:
- 用户名、年龄、订单号:通常放在 URL Query 或 Body
- Token、Body 格式、期望返回格式:通常放在 Header
不要把业务 JSON 参数塞进 Header。
2. Header 的基本写法
HTTP Header 本质上是一组键值对:
Header-Name: Header Value
常见写法:
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Accept: application/json
写 Header 时建议遵守这些规则:
-
Header 名通常不区分大小写,但建议使用常见写法
例如
Content-Type、Authorization -
多个 Header 分多行写
不要把多个 Header 硬拼成一行
-
Header 是元信息,不是 Body
不要把 JSON 参数写到 Header 里
-
以接口文档为准
文档要求传
X-API-Key,就不要擅自改成Authorization
不同工具中的位置如下:
| 工具 | Header 配置位置 |
|---|---|
| Postman / Apifox | Headers 表格 |
| curl | -H 参数 |
| JavaScript fetch | headers 对象 |
| Axios | 请求配置里的 headers |
| 环境变量方式 | 代码里读取 API_TOKEN、API_BASE_URL 等变量后写入 Header |
3. Authorization 请求头怎么写?
Authorization 用于鉴权。
它的作用可以理解为:
告诉服务端:当前请求是谁发起的,是否有权限访问这个接口。
最常见的写法是 Bearer Token:
Authorization: Bearer YOUR_TOKEN
这里要注意几个细节:
Bearer和 token 中间必须有一个空格YOUR_TOKEN要替换成真实 token- 通常不要写成
Bearer <abc123>,除非文档明确要求带尖括号 - 不要复制多余的引号、换行符、前后空格
- 不要把 token 放到 URL 查询参数里
错误示例:
Authorization: BearerYOUR_TOKEN
问题:Bearer 后面缺少空格。
错误示例:
Authorization: "Bearer YOUR_TOKEN"
问题:有些接口会把引号也当成 Header 值的一部分。
推荐写法:
Authorization: Bearer abc123
4. 常见鉴权 Header 类型
不同平台的鉴权方式不完全一样,并不是所有接口都使用 Authorization: Bearer xxx。
| 类型 | 示例 | 常见场景 |
|---|---|---|
| Bearer Token | Authorization: Bearer xxx |
OAuth2、JWT、登录后访问接口 |
| Basic Auth | Authorization: Basic base64(username:password) |
简单账号密码认证、内部系统 |
| API Key Header | X-API-Key: xxx |
开放平台、第三方 API |
| 签名认证 | Authorization: 签名结果 |
云厂商 API、金融类 API |
有些接口文档可能要求:
X-API-Key: YOUR_API_KEY
或者:
Token: YOUR_TOKEN
这种情况下不要自行改成:
Authorization: Bearer YOUR_API_KEY
除非文档明确支持。
签名认证也要特别注意。某些云厂商或企业接口会把签名结果放到 Authorization 中,但它和普通 Bearer Token 不是一回事。
签名认证通常还会涉及:
- 时间戳
- 请求路径
- 请求方法
- Body 哈希
- Secret Key
- 签名算法
不能只复制一个 Header 就认为完成鉴权,需要按对应接口文档生成签名。
5. Content-Type 请求头怎么写?
Content-Type 用来说明请求 Body 的格式。
例如 Body 是 JSON:
{"name":"Tom","age":18}
那么 Header 应该写:
Content-Type: application/json
常见对应关系如下:
| Body 类型 | Content-Type | 常见场景 |
|---|---|---|
| JSON | application/json |
REST API 中常见的 POST / PUT |
| 表单键值对 | application/x-www-form-urlencoded |
登录表单、传统表单提交 |
| 文件上传 | multipart/form-data |
上传图片、上传文件 |
| 纯文本 | text/plain |
发送纯文本 |
| XML | application/xml 或 text/xml |
老系统、企业接口 |
判断原则很简单:
Body 是什么格式,
Content-Type就写什么格式。
例如你发送的是 JSON:
{"name":"Tom","age":18}
就写:
Content-Type: application/json
如果发送的是表单:
username=tom&password=123456
就写:
Content-Type: application/x-www-form-urlencoded
不要 Body 是表单,却写:
Content-Type: application/json
否则后端可能解析不到参数。
6. GET 请求需要 Content-Type 吗?
通常不需要。
因为 Content-Type 描述的是请求 Body 的格式,而 GET 请求一般没有 Body。
例如:
GET /users?id=1 HTTP/1.1
Host: api.example.com
Authorization: Bearer YOUR_TOKEN
这种请求通常不需要:
Content-Type: application/json
很多新手会给所有请求都加上 Content-Type: application/json,大多数时候不一定直接报错,但并不推荐。
原因包括:
- GET 通常没有 Body,不需要声明 Body 格式
- 某些接口会对多余 Header 做校验
- 浏览器环境下,某些 Header 可能触发 CORS 预检
如果接口文档明确要求 GET 也传某个 Header,则按文档来。
7. Content-Type 和 Accept 的区别
Content-Type 和 Accept 很容易混淆。
它们分别描述两个方向:
Content-Type: application/json
Accept: application/json
含义如下:
| Header | 含义 |
|---|---|
Content-Type |
我发给服务器的数据是什么格式 |
Accept |
我希望服务器返回什么格式 |
例如提交 JSON,并希望服务端也返回 JSON:
Content-Type: application/json
Accept: application/json
如果接口没有特殊要求,很多 API 不写 Accept 也会默认返回 JSON。
但如果文档明确要求:
Accept: application/json
建议按文档填写。
8. Postman / Apifox 中如何配置 Header?
在 Postman 或 Apifox 中,进入请求的 Headers 面板,按 Key / Value 填写即可。
示例:
| Key | Value |
|---|---|
Authorization |
Bearer YOUR_TOKEN |
Content-Type |
application/json |
Accept |
application/json |
也可以写成文本理解:
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Accept: application/json
如果你在 Body 中选择了:
raw + JSON
Postman 通常会自动添加:
Content-Type: application/json
如果你在 Authorization 面板选择了 Bearer Token,也可能自动生成:
Authorization: Bearer xxx
所以调试时要检查:
- 是否重复添加了两个
Authorization - 是否重复添加了两个
Content-Type - 是否还残留旧 token
- token 前后是否有空格
- Header 名是否拼写错误
- Body 类型是否和
Content-Type一致
9. curl 中如何添加 Header?
curl 使用 -H 添加请求头。
示例:POST JSON 请求
curl -X POST "https://api.example.com/users" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Tom","age":18}'
说明:
-X POST指定请求方法-H添加 Header-d指定请求 BodyContent-Type要和-d的内容格式一致
如果 -d 是 JSON 字符串:
-d '{"name":"Tom","age":18}'
就使用:
Content-Type: application/json
如果发送表单键值对:
curl -X POST "https://api.example.com/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=tom&password=123456"
就不要继续写:
Content-Type: application/json
否则后端可能按 JSON 解析,导致参数为空。
10. JavaScript fetch 中如何配置 Header?
fetch 中的 Header 写在 headers 对象里。
示例:
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Tom', age: 18 })
})
重点有四个:
headers是对象- JSON 请求要设置
Content-Type: application/json - Body 要用
JSON.stringify()转成 JSON 字符串 - 不要把 JavaScript 对象直接塞进
body
错误示例:
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: { name: 'Tom', age: 18 }
})
问题在于:
body: { name: 'Tom', age: 18 }
这里传的是 JavaScript 对象,不是 JSON 字符串。
推荐写法:
body: JSON.stringify({ name: 'Tom', age: 18 })
另外,不建议把生产环境 token 直接硬编码在前端源码里。
11. Axios 中如何配置 Header?
Axios 的 Header 写在请求配置中。
示例:
axios.post(
'https://api.example.com/users',
{ name: 'Tom', age: 18 },
{
headers: {
Authorization: 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
}
)
结构可以理解为:
axios.post(url, data, config)
对应关系:
| 参数 | 含义 |
|---|---|
url |
请求地址 |
data |
请求 Body |
config.headers |
请求头 |
Axios 在发送普通对象时,通常会按 JSON 处理,并设置合适的 Content-Type。
不过新手阶段建议先显式写出来,方便理解完整请求结构。
真实项目中,token 通常不会每个接口手写一遍,而是通过请求拦截器统一添加。
示例:
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
需要注意:
- 前端保存 token 要考虑安全风险
- 高权限、长期有效的密钥不适合放在前端
- 需要保护的密钥更适合放在服务端
12. 使用环境变量管理 Token 和 Endpoint
在项目中,不建议把 token、API 地址直接写死在代码里。
更常见的做法是使用环境变量。
例如:
API_BASE_URL=https://api.example.com
API_TOKEN=YOUR_TOKEN
API_MODEL=your-model-name
代码中读取后再组装请求:
const baseURL = process.env.API_BASE_URL
const token = process.env.API_TOKEN
fetch(`${baseURL}/users`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Tom', age: 18 })
})
这样做的好处是:
- 本地、测试、生产环境可以使用不同配置
- token 不容易散落在业务代码中
- Endpoint 变更时更容易统一调整
- 配合部署平台时更容易管理密钥
但要注意:
- 不要把包含真实 token 的
.env文件提交到公开仓库 - 不要在日志中完整打印
Authorization - 不要把高权限密钥放在前端构建产物里
- 具体变量名以项目约定或接口文档为准
13. API Endpoint、模型名和鉴权要分开看
在配置 API 时,很多人会把 Endpoint、模型名、Header 混在一起。
实际排查时建议拆开:
13.1 Endpoint
Endpoint 是请求地址,例如:
https://api.example.com/users
它决定请求发到哪里。
常见错误:
- 域名写错
- 路径少了版本号
- 多写或少写
/ - 把测试环境和生产环境混用
13.2 Authorization
Authorization 决定你有没有权限:
Authorization: Bearer YOUR_TOKEN
常见错误:
- token 为空
- token 过期
Bearer拼错Bearer后缺少空格- 复制了多余引号或换行符
13.3 Content-Type
Content-Type 决定后端如何解析 Body:
Content-Type: application/json
常见错误:
- JSON Body 配了表单类型
- 表单 Body 配了 JSON 类型
- 文件上传时手动乱写
multipart/form-data; boundary=...
13.4 模型名或业务参数
如果某些接口需要模型名、业务类型、用户 ID 等参数,它们通常属于 Body 或 Query,而不是 Header。
例如:
{
"model": "your-model-name",
"messages": []
}
这类字段是否需要、叫什么名字,应以具体接口文档为准。
14. 文件上传时 Content-Type 怎么处理?
文件上传通常使用:
Content-Type: multipart/form-data
但在浏览器、Postman、Axios 这类工具里,很多情况下不建议手动写完整的 Content-Type。
原因是文件上传需要 boundary,例如:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryxxx
这个 boundary 通常由浏览器或请求库自动生成。
如果你手动写死:
Content-Type: multipart/form-data
反而可能导致后端无法正确解析文件。
一般做法是:
- Postman / Apifox:Body 选择
form-data - 浏览器:使用
FormData - Axios:传入
FormData,让请求库处理边界
示例:
const formData = new FormData()
formData.append('file', file)
axios.post('https://api.example.com/upload', formData, {
headers: {
Authorization: 'Bearer YOUR_TOKEN'
}
})
这里没有手动写 Content-Type,让 Axios 或浏览器自动处理。
15. 常见报错排查:401、403、415
Header 配错后,最常见的报错可以按下面顺序排查。
| 报错 | 常见原因 | 排查方向 |
|---|---|---|
401 Unauthorized |
没传 token、token 过期、Bearer 格式错误 | 检查 Authorization |
403 Forbidden |
token 有效但权限不够 | 检查账号、角色、接口权限 |
415 Unsupported Media Type |
Content-Type 不被支持 |
改成接口文档要求的类型 |
| 后端收不到参数 | Body 和 Content-Type 不匹配 |
JSON 配 JSON,表单配表单 |
| CORS 预检失败 | 自定义 Header 或 Authorization 触发预检 | 后端允许对应 Header、Method、Origin |
16. 401 Unauthorized 怎么排查?
遇到 401 Unauthorized,优先看鉴权。
检查点:
Authorization: Bearer YOUR_TOKEN
逐项确认:
- 是否真的传了
Authorization Bearer是否拼写正确Bearer后面是否有空格- token 是否过期
- token 是否复制完整
- 是否误带了引号、换行、尖括号
- 当前接口是否要求的不是 Bearer,而是
X-API-Key
可以先用 curl 验证:
curl "https://api.example.com/users" \
-H "Authorization: Bearer YOUR_TOKEN"
如果 curl 也返回 401,通常说明 token、权限或 Header 格式有问题。
如果 curl 正常,浏览器代码不正常,则继续检查 CORS 或前端请求代码。
17. 403 Forbidden 怎么排查?
403 Forbidden 和 401 不一样。
一般可以这样理解:
401:你是谁,服务端无法确认403:知道你是谁,但你没有权限
常见原因:
- 当前账号没有接口权限
- token 权限范围不够
- 使用了错误环境的 token
- 签名权限不足
- 接口限制了访问来源或角色
排查方式:
- 确认 token 对应的账号
- 确认账号是否有接口权限
- 确认调用的是测试环境还是生产环境
- 如果是签名认证,检查签名范围和权限配置
18. 415 Unsupported Media Type 怎么排查?
415 Unsupported Media Type 通常和 Content-Type 有关。
例如接口只支持 JSON:
Content-Type: application/json
但你发送了:
Content-Type: text/plain
就可能返回 415。
排查步骤:
- 查看接口文档要求的
Content-Type - 查看实际请求 Header
- 查看 Body 是否和 Header 匹配
- 使用 Postman 或 curl 复现
- 如果是文件上传,检查是否错误手写了
boundary
JSON 请求推荐组合:
Content-Type: application/json
{"name":"Tom","age":18}
表单请求推荐组合:
Content-Type: application/x-www-form-urlencoded
name=Tom&age=18
19. Postman 能通,浏览器代码不通怎么办?
这是很常见的问题。
如果 Postman 能请求成功,但浏览器里失败,不一定是 Header 写错,可能是浏览器跨域限制。
尤其当前端请求带有:
Authorization: Bearer YOUR_TOKEN
或者自定义 Header:
X-API-Key: xxx
浏览器可能会先发送一个 OPTIONS 预检请求。
后端需要正确返回允许信息,例如:
Access-Control-Allow-Origin: https://your-frontend.example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type
如果后端没有允许 Authorization 或 Content-Type,浏览器会拦截请求。
排查思路:
- 打开浏览器 DevTools
- 查看 Network 面板
- 看是否有
OPTIONS请求失败 - 看响应头中是否允许了对应 Header
- 后端补充 CORS 配置
注意:
CORS 是浏览器安全机制,Postman 不受同样限制,所以 Postman 能通不代表浏览器一定能通。
20. 安全与最佳实践
Header 配置不仅要能跑通,也要注意安全。
尤其是 Authorization 中的 token,一旦泄露,可能等同于登录态泄露。
建议遵守这些规则:
- 不要把 token 放在 URL 中
不推荐:
https://api.example.com/users?token=xxx
推荐:
Authorization: Bearer YOUR_TOKEN
- 不要把真实 token 提交到 GitHub
包括:
- 源码
.env- README
- 示例截图
- 接口调试记录
- 不要在日志中完整打印 Authorization
不推荐:
Authorization: Bearer eyJhbGciOi...
可以打码:
Authorization: Bearer eyJhbGci...
- 尽量使用 HTTPS
token 应该通过 HTTPS 传输,避免明文暴露。
- 前端不要保存高权限长期密钥
前端代码最终会暴露给用户,不适合保存高权限、长期有效的密钥。
如果需要保护密钥,更推荐:
前端 -> 自己的后端 -> 第三方 API
由服务端保管密钥并转发请求。
21. 新手配置 API Header 的推荐流程
如果你正在接一个新接口,可以按这个流程来:
第一步:确认接口地址
https://api.example.com/users
确认:
- 域名
- 路径
- API 版本
- HTTP 方法
第二步:确认鉴权方式
查看文档要求的是哪一种:
Authorization: Bearer xxx
或:
X-API-Key: xxx
不要自己猜 Header 名。
第三步:确认 Body 格式
如果 Body 是 JSON:
{"name":"Tom","age":18}
就配置:
Content-Type: application/json
如果是表单:
name=Tom&age=18
就配置:
Content-Type: application/x-www-form-urlencoded
第四步:用 Postman 或 curl 先验证
curl 示例:
curl -X POST "https://api.example.com/users" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Tom","age":18}'
先保证最小请求能通。
第五步:再迁移到代码中
fetch 示例:
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Tom', age: 18 })
})
Axios 示例:
axios.post(
'https://api.example.com/users',
{ name: 'Tom', age: 18 },
{
headers: {
Authorization: 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
}
)
22. FAQ
22.1 Header 名大小写有影响吗?
HTTP Header 名通常不区分大小写。
也就是说:
content-type: application/json
和:
Content-Type: application/json
语义上通常是一样的。
但为了可读性和通用习惯,建议写成:
Content-Type
Authorization
22.2 token 应该放 Header 还是 URL?
一般建议放 Header:
Authorization: Bearer YOUR_TOKEN
不建议放 URL:
https://api.example.com/users?token=xxx
因为 URL 更容易出现在:
- 浏览器历史记录
- 服务器日志
- 代理日志
- 监控系统
- 截图和分享链接
泄露风险更高。
22.3 可以同时写 Authorization 和 Content-Type 吗?
可以,而且很常见。
例如:
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
它们解决的是两个不同问题:
Authorization:鉴权Content-Type:说明请求 Body 格式
两者不冲突。
22.4 Content-Type 是 application/json 时,Body 怎么写?
Body 应该是合法 JSON 字符串:
{"name":"Tom","age":18}
在 JavaScript 中要这样写:
body: JSON.stringify({ name: 'Tom', age: 18 })
不要直接写:
body: { name: 'Tom', age: 18 }
22.5 Authorization 和 Cookie 有什么区别?
两者都可以表示登录态,但机制不同。
Authorization 通常由客户端主动写入 Header:
Authorization: Bearer xxx
Cookie 更多用于浏览器会话,浏览器会根据域名自动携带:
Cookie: sessionid=xxx
具体使用哪种方式,取决于系统设计和接口文档。
总结
API Header 配置可以先记住三件事:
- 需要鉴权时,先看文档要求的是
Authorization、X-API-Key,还是其他自定义 Header - 只要请求有 Body,就让
Content-Type和 Body 格式保持一致 - 请求失败时,按
401、403、415分别排查 token、权限和 Body 类型
对新手来说,不需要一开始背所有 Header 字段。先把 Authorization、Content-Type、Accept 这几个最常见字段搞清楚,再结合 Postman、curl、fetch、Axios 验证,请求调试会顺很多。
