Next.js API路由二次请求报AxiosError: socket hang up ECONNRESET如何修复?
问题:Next.js API路由首次请求正常,后续请求报错socket hang up (ECONNRESET)
我的Next.js API路由首次请求运行正常,但在不重启服务器的情况下发起后续请求时,通常会执行到打印“GO4”的步骤,随后长时间等待后抛出如下错误:
AxiosError: socket hang up at AxiosError.from (/Users/xyz/Desktop/Projects/xyz/Project/API/node_modules/axios/dist/node/axios.cjs:725:14) at RedirectableRequest.handleRequestError (/Users/xyz/Desktop/Projects/xyz/Project/API/node_modules/axios/dist/node/axios.cjs:2467:25) at RedirectableRequest.emit (node:events:525:35) at eventHandlers.<computed> (/Users/xyz/Desktop/Projects/xyz/Project/API/node_modules/follow-redirects/index.js:14:24) at ClientRequest.emit (node:events:513:28) at TLSSocket.socketOnEnd (node:_http_client:518:9) at TLSSocket.emit (node:events:525:35) at endReadableNT (node:internal/streams/readable:1359:12) at process.processTicksAndRejections (node:internal/process/task_queues:82:21) { code: 'ECONNRESET' }
对应的Next.js API路由代码如下:
import Cors from 'cors' import FormData from 'form-data'; const axios = require('axios'); const form = new FormData(); const cors = Cors({ methods: ['POST', 'GET', 'HEAD'] }) export const config = { api: { responseLimit: false } } export default async function handler(req, res) { try { const imageBuffers = []; await runMiddleware(req, res, cors); const body = JSON.parse(req.body); for (const image of body.images) { const response = await axios.get(image, {responseType: 'arraybuffer'}); if(((response.headers['content-type']).match(/(image)+\//g)).length == 0){ res.send("Invalid image URL"); } imageBuffers.push(Buffer.from(response.data, 'binary')); } form.append('...', body.title); for (const i in imageBuffers) { form.append('images', imageBuffers[i], 'Image'+i+'.jpg'); } const response = await axios.post( 'url', form, { headers: { "Content-Type": "multipart/form-data", 'Authorization': 'Bearer xyz' } } ); console.log("DATA: "+JSON.stringify(response.data)); res.send(JSON.stringify(response.data)); } catch(err) { console.log("ERROR"); console.error(err); res.send(err); } } function runMiddleware(req,res,fn) { return new Promise((resolve, reject) => { fn(req, res, (result) => { if (result instanceof Error) { return reject(result) } return resolve(result) }) }) }
修复方案
核心问题
问题出在模块级的FormData实例:const form = new FormData()定义在handler函数外部,Next.js的API路由在服务器启动后会常驻内存,第一次请求使用该form对象后,其内部的数据流状态已经改变,后续请求复用这个已被使用过的form对象,会导致表单数据异常,最终触发socket连接被重置的错误(ECONNRESET)。
具体修复步骤
- 将FormData实例移到handler内部:每次请求都创建全新的FormData对象,避免复用旧实例
- 修正无效图片URL的响应逻辑:发送错误响应后立即
return,阻止后续代码执行 - 正确设置multipart请求头:手动设置
Content-Type: multipart/form-data会丢失自动生成的boundary,应该让axios从FormData对象自动获取headers,或者使用form.getHeaders() - 优化图片类型检测逻辑:避免
match返回null时调用length方法导致报错
修改后的完整代码
import Cors from 'cors' import FormData from 'form-data'; const axios = require('axios'); const cors = Cors({ methods: ['POST', 'GET', 'HEAD'] }) export const config = { api: { responseLimit: false } } export default async function handler(req, res) { try { const imageBuffers = []; await runMiddleware(req, res, cors); const body = JSON.parse(req.body); for (const image of body.images) { const response = await axios.get(image, {responseType: 'arraybuffer'}); // 优化图片类型检测,避免match返回null报错 const isImage = response.headers['content-type']?.includes('image/'); if (!isImage) { res.send("Invalid image URL"); return; // 发送错误后终止后续执行 } imageBuffers.push(Buffer.from(response.data, 'binary')); } // 每次请求创建新的FormData实例 const form = new FormData(); form.append('...', body.title); for (const i in imageBuffers) { form.append('images', imageBuffers[i], `Image${i}.jpg`); } const response = await axios.post( 'url', form, { headers: { // 使用FormData自动生成的headers,包含正确的boundary ...form.getHeaders(), 'Authorization': 'Bearer xyz' } } ); console.log("DATA: "+JSON.stringify(response.data)); res.send(JSON.stringify(response.data)); } catch(err) { console.log("ERROR"); console.error(err); res.status(500).send(err.message); // 使用正确的状态码返回错误 } } function runMiddleware(req,res,fn) { return new Promise((resolve, reject) => { fn(req, res, (result) => { if (result instanceof Error) { return reject(result) } return resolve(result) }) }) }
内容的提问来源于stack exchange,提问作者TheProgrammer
相关产品推荐
相关产品推荐

