Google OAuth令牌获取报错:401与ERR_HTTP_HEADERS_SENT问题排查
问题分析与解决方案
核心问题1:Google OAuth Token请求格式错误
你的代码存在两个关键请求格式问题,这是触发401 Unauthorized的根本原因:
- Google的
/token端点要求授权码交换的参数通过x-www-form-urlencoded格式的请求体发送,而非URL查询参数 - Axios调用参数顺序错误:
axios.post的第二个参数是请求数据,第三个才是包含headers的配置对象,你误将headers当作第二个参数传递
核心问题2:错误处理引发重复响应
catch块中throw new Error(error)会把原始错误对象包装成新Error,既丢失了原始错误详情,还可能导致Express错误中间件重复向客户端发送响应,触发ERR_HTTP_HEADERS_SENT。
修正后的代码
import qs from 'qs'; import axios from 'axios'; public async getGoogleOAuthTokens({ code }: { code: string }): Promise<GoogleTokensResult> { const rootURL = 'https://oauth2.googleapis.com/token'; const values = { code, client_id: GOOGLE_AUTH_CLIENT_ID, client_secret: GOOGLE_AUTH_CLIENT_SECRET, redirect_uri: GOOGLE_AUTH_REDIRECT_URL, grant_type: 'authorization_code', }; try { // 将参数通过x-www-form-urlencoded格式的请求体发送 // 修正Axios参数顺序:data在前,配置对象在后 const res = await axios.post<GoogleTokensResult>(rootURL, qs.stringify(values), { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }); return res.data; } catch (error: any) { // 直接抛出原始错误,保留完整错误信息 console.error('Google OAuth Token请求失败:', error.response?.data || error.message); throw error; } }
额外修复:解决ERR_HTTP_HEADERS_SENT
检查你的Express错误中间件,确保只在响应未发送时才发送错误响应:
// error.middleware.ts示例 export const errorMiddleware = (err: any, req: Request, res: Response, next: NextFunction) => { // 先判断响应是否已发送,避免重复发送 if (res.headersSent) { return next(err); } res.status(err.response?.status || 500).json({ message: err.response?.data?.error_description || err.message || '服务器错误', }); };
为什么之前正常现在报错?
大概率是Google调整了OAuth端点的参数校验规则,之前错误的请求格式(参数放URL)可能被宽松处理,现在严格执行了规范,导致401错误触发。
内容的提问来源于stack exchange,提问作者Anshul Verma
相关产品推荐
相关产品推荐

