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

Node.js:HTTP服务用request模块返回请求内容报错求助

你的需求完全可行!附错误修复方案

嗨,首先明确:你的需求是完全可以实现的,本质就是做一个简单的反向代理——把客户端发来的请求转发到目标URL,再把目标URL返回的内容原样(或加工后)回传给客户端。

接下来帮你排查ERR_STREAM_WRITE_AFTER_END这个错误,主要踩了几个坑:


错误根源拆解

  1. 全局变量导致请求冲突:你用了out_res = res但没加let/const声明,这会让out_res变成全局变量。如果同时有多个客户端发请求,后面的请求会覆盖前面的out_res,结果就是某个请求的响应流被多次调用end(),直接触发ERR_STREAM_WRITE_AFTER_END。
  2. 响应头写法错误:out_res.writeHead(200, {res}); 这里第二个参数应该是标准的响应头对象(比如{'Content-Type': 'text/html'}),你直接传{res}会生成一个无效的响应头,可能引发流状态异常。
  3. 缺失错误处理:如果make_request里的请求失败(比如目标URL挂了),你没做任何错误处理就直接写响应,也可能导致响应流异常终止。

修复后的完整代码

我帮你重构了代码,解决了上述问题,同时优化了逻辑:

const http = require("http");
const request = require("request");
// 替换成你实际要转发的目标URL
const TARGET_URL = "https://example.com"; 

const server = http.createServer((req, res) => {
  // 直接在请求回调里处理,避免全局变量冲突
  make_request((err, proxyRes, body) => {
    // 先处理请求错误的情况
    if (err) {
      res.writeHead(500, {'Content-Type': 'text/plain'});
      res.write(`转发请求出错: ${err.message}`);
      return res.end();
    }

    // 转发目标URL的响应头,过滤掉不需要的Connection头
    const responseHeaders = {...proxyRes.headers};
    delete responseHeaders['Connection'];
    
    // 写入正确的状态码和响应头
    res.writeHead(proxyRes.statusCode, responseHeaders);
    // 把目标URL返回的内容写给客户端
    res.write(body);
    res.end();
  });
});

function make_request(callback) {
  request(TARGET_URL, callback);
}

// 启动服务器,加上回调确认启动状态
server.listen(8080, () => {
  console.log('服务器已启动,监听端口8080');
});

额外小贴士

  • request模块已停止维护:request在2020年就废弃了,建议换成更现代的库,比如axios或者node-fetch(Node.js 18及以上版本已经内置fetch,不用额外安装)。给你个node-fetch的示例:
    const http = require("http");
    const fetch = require('node-fetch'); // Node.js <18需要执行npm install node-fetch
    const TARGET_URL = "https://example.com";
    
    const server = http.createServer(async (req, res) => {
      try {
        const proxyRes = await fetch(TARGET_URL);
        const body = await proxyRes.text();
        
        const responseHeaders = {...proxyRes.headers};
        delete responseHeaders['Connection'];
        
        res.writeHead(proxyRes.status, responseHeaders);
        res.write(body);
        res.end();
      } catch (err) {
        res.writeHead(500, {'Content-Type': 'text/plain'});
        res.write(`转发请求出错: ${err.message}`);
        res.end();
      }
    });
    
    server.listen(8080, () => {
      console.log('服务器已启动,监听端口8080');
    });
    
  • 支持动态转发:如果需要根据客户端请求的路径(比如http://localhost:8080/api/user)动态转发到目标URL的对应路径,可以用req.url拼接,比如const fullTargetUrl = TARGET_URL + req.url。

内容的提问来源于stack exchange,提问作者NeoZoom.lua

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:37:49