You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从request库迁移至node-fetch后出现504网关超时错误求助

问题:node-fetch替换request后出现504 Gateway Timeout错误

原本使用request库的代码(无async/await)运行正常,改用node-fetch结合async/await重写后出现504 Gateway Timeout错误,请求帮忙排查。相关代码如下:

const fetch = require("node-fetch").default;
let iApi = express.Router();

iApi.post("/update/:name/:value", async (req, res) => {
    const name = req.params["name"];
    const value = req.params["value"];

    const headers = { ...req.headers };
    const url = `${process.env.URL}/name/${name}/value/${value}`;

    const options = {
        url: url,
        method: "post",
        headers: headers,
        gzip: true,
    };

    //if (process.env.NODE_ENV === "development") {
      //  options.agent = agent;
    //}

    // request(options, function(err, response, body) {
        // handleResponseNoBody(err, response, body, res, url)
    // })
    const response = await fetch(url, options);
    if (response.status == 200) {
        logger.info({
            ...LOG_DEFAULTS,
            endpoint: url,
            methodName: "update",
            description:
                "update",
            c_id: req.cId,
            res,
            req,
        });
        const data = await response.json();
        res.send(data);

    } else {
        res.status(response.status).send(JSON.parse(data));
    }
});
解决方案

问题出在混用了request和node-fetch的参数格式,以及部分请求配置的细节差异,以下是修正后的代码和关键修改说明:

修正后的代码

const fetch = require("node-fetch").default;
let iApi = express.Router();

iApi.post("/update/:name/:value", async (req, res) => {
    const name = req.params["name"];
    const value = req.params["value"];

    // 过滤可能引发冲突的请求头,避免上游服务器拒绝
    const headers = {...req.headers};
    delete headers.host;
    delete headers["content-length"];

    const url = `${process.env.URL}/name/${name}/value/${value}`;

    const options = {
        method: "POST", // 遵循HTTP方法大写规范
        headers: headers,
        compress: true, // node-fetch标准的压缩处理,替代request的gzip: true
        // 开发环境需要agent的话取消注释,确保agent已正确初始化
        // agent: process.env.NODE_ENV === "development" ? agent : undefined
    };

    try {
        const response = await fetch(url, options);
        // 统一解析响应body,避免分支中变量未定义
        const data = await response.json();
        
        if (response.status === 200) {
            logger.info({
                ...LOG_DEFAULTS,
                endpoint: url,
                methodName: "update",
                description: "update",
                c_id: req.cId,
                res,
                req,
            });
            res.send(data);
        } else {
            res.status(response.status).send(data);
        }
    } catch (err) {
        // 捕获请求超时、网络错误等异常
        logger.error({
            ...LOG_DEFAULTS,
            endpoint: url,
            methodName: "update",
            error: err.message,
            c_id: req.cId,
        });
        res.status(504).send({error: "请求超时或上游服务不可用"});
    }
});

关键修改点

  • 参数格式修正:node-fetch的初始化对象不需要url字段,url直接作为第一个参数传入,原代码中options.url是request的专属参数格式,会导致node-fetch配置错误
  • 压缩处理替换:将request的gzip: true替换为node-fetch标准的compress: true,它会自动处理gzip压缩的响应
  • 请求头过滤:移除了host、content-length等可能引发冲突的请求头,避免上游服务器因为头信息异常拒绝请求
  • 异常处理补充:添加try/catch捕获请求过程中的网络错误、超时等异常,避免未处理的崩溃
  • 响应逻辑修正:统一解析响应body,else分支不再使用未定义的data变量
  • Agent配置恢复:如果开发环境依赖自定义Agent,取消注释相关代码,request可能依赖这个Agent处理长连接或代理,注释后可能导致超时

内容的提问来源于stack exchange,提问作者shoes_on

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 06:00:17