一、速览:Surge 是个什么样的项目

入门

Surge 是一个基于 JavaScript 的轻量级网络调试与请求转发工具,核心思路是拦截 HTTP/HTTPS 请求,按规则修改请求头、参数或响应内容,再转发到目标服务器。它常用于接口联调、Mock 数据、绕过前端签名校验、抓包分析等场景。

这个项目的定位很明确:不追求做全功能的代理软件,而是提供一个可编程的请求处理管道,让你用 JavaScript 脚本控制每一个请求的走向。相比 Charles 或 Fiddler 这类图形化抓包工具,Surge 更贴近「写代码处理请求」的工作流。

如果你经常写爬虫、调试前后端联调问题,或者需要快速给某个接口造数据,Surge 能省下不少重复劳动。它的代码量不大,结构清晰,也适合想学习 HTTP 拦截原理的开发者阅读源码。

注意:这个项目与 iOS 上的同名网络工具 Surge(Surge for iOS/macOS)没有关系,仓库地址是 Choler/Surge,不要混淆。


二、安装与启动

入门

Surge 依赖 Node.js 环境,建议使用 12 及以上版本。获取项目后直接安装依赖即可运行:

git clone https://github.com/Choler/Surge.git
cd Surge
npm install

启动服务默认监听 127.0.0.1:8000,执行:

npm start

看到控制台输出 Surge proxy server is running on port 8000 说明启动成功。此时将终端或应用的 HTTP 代理指向 127.0.0.1:8000,请求就会进入 Surge 的处理管道。

项目没有提供配置文件,所有行为都通过脚本文件控制。默认情况下,Surge 读取项目根目录下的 rules.js 作为处理逻辑入口。


三、核心用法:写一条请求处理规则

入门

Surge 的工作方式非常直接:你导出一个函数,函数接收请求对象,返回修改后的请求对象或响应对象。来看一个最小示例:

// rules.js
module.exports = (req) => {
  // 给所有请求添加一个自定义头
  req.headers['X-Custom-Header'] = 'hello-surge';
  return req;
};

保存后重启服务,所有经过代理的请求都会带上这个头。如果想让某个接口直接返回假数据,可以返回一个响应对象:

module.exports = (req) => {
  if (req.url.includes('/api/user')) {
    return {
      statusCode: 200,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: 'mock-user', age: 18 })
    };
  }
  return req;
};

返回 req 表示放行请求;返回一个带 statusCodebody 的对象则直接构造响应,不再访问真实服务器。这是 Surge 最核心的两个分支逻辑。

请求对象上常用的字段包括 methodurlheadersbody,响应对象则支持 statusCodeheadersbody。理解这几个字段就能覆盖大部分使用场景。


四、配置与定制:按域名分流、修改响应体

进阶 · 推荐细读

实际使用中,你通常只想拦截部分请求,而不是全部。Surge 支持在规则函数内做条件判断,实现按域名、路径或请求方法分流:

module.exports = (req) => {
  // 只处理 API 请求
  if (!req.url.startsWith('/api/')) return req;

  // 对 POST 请求单独处理
  if (req.method === 'POST') {
    req.headers['X-Request-Source'] = 'surge-proxy';
  }

  // 修改请求体中的某个字段
  if (req.body && req.body.userId) {
    req.body.userId = '999999';
  }

  return req;
};

修改响应体是另一个高频需求。Surge 允许你在规则函数中返回一个 transform 函数,用于在拿到真实响应后做改写:

module.exports = (req) => {
  if (req.url === '/api/list') {
    return (res) => {
      const data = JSON.parse(res.body);
      data.items = data.items.filter(item => item.visible !== false);
      res.body = JSON.stringify(data);
      return res;
    };
  }
  return req;
};

注意这里返回的不是响应对象,而是一个接收 res 并返回 res 的函数。这种「先放行、后改写」的模式很适合做数据清洗或字段脱敏。

提示:请求体 req.body 只有在 Content-Type 为 application/jsonapplication/x-www-form-urlencoded 时才会被自动解析为对象,其他格式(如二进制)保持原始字符串。


五、踩坑:常见问题与规避方法

进阶 · 推荐细读

HTTPS 请求需要额外处理。 Surge 默认只能拦截明文 HTTP 流量。对于 HTTPS 请求,需要设置环境变量 NODE_TLS_REJECT_UNAUTHORIZED=0 来跳过证书校验,但这会带来安全风险,建议只在本地开发环境使用:

NODE_TLS_REJECT_UNAUTHORIZED=0 npm start

规则函数必须同步返回。 Surge 的处理管道是同步的,不支持在规则函数内使用 async/await。如果需要异步操作(比如查数据库),建议提前把数据加载到内存中,或者在函数外部做预取。

修改请求体后 Content-Length 不会自动更新。 如果你手动改了 req.body,但长度变了,目标服务器可能报 411 或解析错误。建议在修改后手动更新:

req.headers['Content-Length'] = Buffer.byteLength(req.body);

代理只对显式设置了代理的客户端生效。 浏览器默认不会走系统代理,需要手动配置或使用 SwitchyOmega 等插件。curl 测试时加上 -x 参数:

curl -x http://127.0.0.1:8000 http://example.com

六、进阶:动态规则与多环境切换

深入 · 老手可选

Surge 的规则文件只是一个普通 Node 模块,这意味你可以利用 JavaScript 的全部能力来构建规则。比如根据环境变量切换不同配置:

const env = process.env.SURGE_ENV || 'dev';

const mockData = {
  dev: { name: 'dev-user' },
  test: { name: 'test-user' }
};

module.exports = (req) => {
  if (req.url.includes('/api/user') && env !== 'prod') {
    return {
      statusCode: 200,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(mockData[env])
    };
  }
  return req;
};

启动时指定环境:

SURGE_ENV=test npm start

另一个实用技巧是把规则拆分成多个模块,按需加载。比如把 Mock 规则放到 mocks/ 目录,用 fs.readdirSync 动态加载:

const fs = require('fs');
const path = require('path');

const mocks = {};
fs.readdirSync(path.join(__dirname, 'mocks')).forEach(file => {
  if (file.endsWith('.js')) {
    const name = path.basename(file, '.js');
    mocks[name] = require(`./mocks/${file}`);
  }
});

module.exports = (req) => {
  for (const mock of Object.values(mocks)) {
    const result = mock(req);
    if (result) return result;
  }
  return req;
};

每个 mock 文件只负责一个接口的拦截逻辑,互不干扰,维护起来比单文件堆叠清晰得多。


七、判断建议:这个项目适合你吗

入门

Surge 适合以下场景:

  • 接口联调时快速造 Mock 数据,不用等后端就绪
  • 爬虫开发中绕过简单的签名校验,修改请求头或参数
  • 学习 HTTP 代理实现原理,代码量小、逻辑直白,适合通读

如果你的需求是图形化抓包、断点调试、流量录制回放,Surge 并不合适——这些功能它都没有。同样,如果你需要处理 HTTPS 双向认证或复杂的代理链,Surge 的同步模型会限制你。

项目目前维护频率不高,Star 数也不多,但核心功能稳定,作为开发辅助工具完全够用。建议先跑通最小示例,确认它能满足你的需求,再决定是否深度使用。

Surge 项目封面

项目信息

项目
仓库 Choler/Surge
语言 JavaScript
Star 292
Fork 65
主页

参考链接