Node.js代理至仅支持HTTP 1.1的上游及Azure容器应用Envoy问题处理
解决方案
a) 无法修改Envoy配置时,避免其发送分块编码响应
由于无法直接调整Envoy配置,可通过Express代理层处理响应,将分块编码的响应转换为带Content-Length头的完整响应,规避分块传输导致的ECONNRESET问题:
- 缓存完整响应后转发:使用流缓存工具(如
concat-stream)将上游的分块响应完整缓存为Buffer,重新计算并设置Content-Length头后转发给客户端,中等大小文件(>200kb)场景下内存压力可控:
const concat = require('concat-stream'); const httpProxy = require('http-proxy'); const proxy = httpProxy.createProxyServer({}); app.use('/proxy', (req, res) => { proxy.web(req, res, { target: 'https://your-upstream-envoy-url' }); proxy.on('proxyRes', (proxyRes, req, res) => { // 移除分块编码相关响应头 delete proxyRes.headers['transfer-encoding']; // 缓存完整响应并转发 proxyRes.pipe(concat((data) => { res.setHeader('Content-Length', data.length); res.end(data); })); }); });
- 修改请求头触发完整响应:在代理请求时添加
Connection: close头,部分场景下Envoy会优先返回带Content-Length的完整响应而非分块:
app.use('/proxy', (req, res) => { req.headers.connection = 'close'; proxy.web(req, res, { target: 'https://your-upstream-envoy-url' }); });
b) 让Node.js正确处理分块编码的代理请求
针对http-proxy优化配置,确保其能正确处理Envoy返回的分块响应:
- 强制使用HTTP/1.1通信:Envoy不支持HTTP/1.0,显式配置代理使用HTTP/1.1发送请求:
const http = require('http'); const httpProxy = require('http-proxy'); const proxy = httpProxy.createProxyServer({ target: 'https://your-upstream-envoy-url', agent: new http.Agent({ keepAlive: true, protocolVersion: 1.1 }) });
- 正确传递分块编码标识:保留
Transfer-Encoding头,移除冲突的Content-Length头,让Node.js流自动处理分块传输:
proxy.on('proxyRes', (proxyRes, req, res) => { if (proxyRes.headers['transfer-encoding']) { delete proxyRes.headers['content-length']; } });
- 延长超时时间避免提前断开:
ECONNRESET常因超时触发,调整代理超时参数:
const proxy = httpProxy.createProxyServer({ target: 'https://your-upstream-envoy-url', proxyTimeout: 30000, // 30秒超时,按需调整 timeout: 30000 });
- 监听错误事件优雅处理中断:捕获
ECONNRESET错误,返回友好响应:
proxy.on('error', (err, req, res) => { if (err.code === 'ECONNRESET') { res.status(503).send('服务暂时不可用'); } else { res.status(500).send('代理错误'); } });
内容的提问来源于stack exchange,提问作者Brendan
相关产品推荐
相关产品推荐

