基于http-proxy-middleware的代理添加认证令牌报错求助
解决http-proxy-middleware设置请求头时的ERR_HTTP_HEADERS_SENT错误
嘿,我刚好碰到过一模一样的问题!你遇到的Error [ERR_HTTP_HEADERS_SENT]本质是异步操作的时机没踩对——你用的request是异步回调风格的,当你在回调里去设置proxyReq的请求头时,http-proxy-middleware早已经把请求转发给目标的/rest-api了,此时请求头已经发送给对方服务器,自然没法再修改,就抛出了这个错误。
核心解决方案:把异步请求改成同步等待
http-proxy-middleware支持异步的onProxyReq函数,只要我们把它改成async函数,然后等待获取token的操作完成后,再继续设置请求头、转发请求就行。这里推荐用Promise风格的请求库(比如axios),或者把request包装成Promise,避免回调嵌套的问题。
方案1:用axios实现(更简洁)
首先安装axios:
npm install axios
然后修改你的代理配置:
const axios = require('axios'); // 你的代理配置 const myProxy = createProxyMiddleware('/my-proxy/', { target: 'http://your-rest-api-domain', // 替换成你的rest-api实际域名 changeOrigin: true, pathRewrite: { '^/my-proxy/': '/rest-api/' }, onProxyReq: async function (proxyReq, req, res) { // 检查请求头是否已有auth-token if (!req.header("auth-token")) { try { // 等待认证请求完成,拿到token const authResponse = await axios.post('/rest-api/auth', { username: "user", password: "pass" }); // 此时再设置请求头,不会触发错误 proxyReq.setHeader("auth-token", authResponse.data.token); } catch (error) { // 处理认证失败的情况,比如返回错误给客户端 console.error('获取token失败:', error); res.status(500).send('Failed to obtain authentication token'); // 终止后续代理流程 return; } } } });
方案2:继续用request(包装成Promise)
如果你不想换库,可以用Node.js的util.promisify把request转成Promise风格:
const request = require('request'); const { promisify } = require('util'); const requestPromise = promisify(request); // 你的代理配置 const myProxy = createProxyMiddleware('/my-proxy/', { target: 'http://your-rest-api-domain', changeOrigin: true, pathRewrite: { '^/my-proxy/': '/rest-api/' }, onProxyReq: async function (proxyReq, req, res) { if (!req.header("auth-token")) { try { const authResult = await requestPromise({ url: '/rest-api/auth', method: 'POST', json: { "username": "user", "password": "pass" } }); // 解析返回的token const token = authResult.body.token; proxyReq.setHeader("auth-token", token); } catch (error) { console.error('获取token失败:', error); res.status(500).send('Failed to obtain authentication token'); return; } } } });
额外优化建议
- 添加token缓存:如果每个无token的请求都去调用
/rest-api/auth,会给目标API带来不必要的压力。可以把获取到的token和过期时间存在变量里,下次请求先检查token是否有效,无效再重新获取。 - 确保auth接口路径正确:注意
/rest-api/auth的URL是否需要完整域名(比如http://your-rest-api-domain/rest-api/auth),避免请求到代理服务器本地导致404。 - 错误处理要完善:如果获取token失败,一定要主动给客户端返回错误响应,避免客户端一直处于等待状态。
内容的提问来源于stack exchange,提问作者Will




