节点 JS HTTP 代理挂起
Node JS HTTP Proxy hanging up
我有一个 http-proxy 来代理任何网站,并在将 HTML 服务回客户端之前注入一些自定义 JS 文件。每当我尝试访问代理网站时,它都会挂断或浏览器似乎不确定加载。但是当我检查 HTML 源时,我成功地注入了我的自定义 JavaScript 文件。这是代码:
const cheerio = require('cheerio');
const http = require('http');
const httpProxy = require('http-proxy');
const { ungzip } = require('node-gzip');
_initProxy(host: string) {
let proxy = httpProxy.createProxyServer({});
let option = {
target: host,
selfHandleResponse: true
};
proxy.on('proxyRes', function (proxyRes, req, res) {
let body = [];
proxyRes.on('data', function (chunk) {
body.push(chunk);
});
proxyRes.on('end', async function () {
let buffer = Buffer.concat(body);
if (proxyRes.headers['content-encoding'] === 'gzip') {
try {
let $ = null;
const decompressed = await ungzip(buffer);
const scriptTag = '<script src="my-customjs.js"></script>';
$ = await cheerio.load(decompressed.toString());
await $('body').append(scriptTag);
res.end($.html());
} catch (e) {
console.log(e);
}
}
});
});
let server = http.createServer(function (req, res) {
proxy.web(req, res, option, function (e) {
console.log(e);
});
});
console.log("listening on port 5051");
server.listen(5051);
}
如果我做错了什么,有人能告诉我吗,node-http-proxy 似乎快要死了,不能太依赖它,因为代理有时可以工作,然后在下一次死掉 运行,取决于我运行服务器的次数。
你的代码看起来不错,所以我很好奇并试了一下。
尽管您确实记录了一些错误,但您没有处理以下几种情况:
- 服务器 returns 一个 body 没有响应(
cheerio
将在这种情况下生成一个空的 HTML body)
- 服务器 return 未压缩的响应(您的代码将自动丢弃响应)
我对你的代码做了一些修改。
更改初始选项
let proxy = httpProxy.createProxyServer({
secure: false,
changeOrigin: true
});
- 不验证 TLS 证书
secure: false
- 发送正确的
Host
headerchangeOrigin: true
删除if
语句并用三元替换它
const isCompressed = proxyRes.headers['content-encoding'] === 'gzip';
const decompressed = isCompressed ? await ungzip(buffer) : buffer;
您还可以删除 cheerio
上的 2 await
,Cheerio 不是异步的,return 也不能 await
。
最终代码
这是有效的最终代码。你提到 "it looks like node-http-proxy is dying a lot [...] depending on how many times I ran the server." 我没有遇到过这样的稳定性问题,所以如果发生这种情况,你的问题可能出在其他地方(坏 ram?)
const cheerio = require('cheerio');
const http = require('http');
const httpProxy = require('http-proxy');
const { ungzip } = require('node-gzip');
const host = 'https://github.com';
let proxy = httpProxy.createProxyServer({
secure: false,
changeOrigin: true
});
let option = {
target: host,
selfHandleResponse: true
};
proxy.on('proxyRes', function (proxyRes, req, res) {
console.log(`Proxy response with status code: ${proxyRes.statusCode} to url ${req.url}`);
if (proxyRes.statusCode == 301) {
throw new Error('You should probably do something here, I think there may be an httpProxy option to handle redirects');
}
let body = [];
proxyRes.on('data', function (chunk) {
body.push(chunk);
});
proxyRes.on('end', async function () {
let buffer = Buffer.concat(body);
try {
let $ = null;
const isCompressed = proxyRes.headers['content-encoding'] === 'gzip';
const decompressed = isCompressed ? await ungzip(buffer) : buffer;
const scriptTag = '<script src="my-customjs.js"></script>';
$ = cheerio.load(decompressed.toString());
$('body').append(scriptTag);
res.end($.html());
} catch (e) {
console.log(e);
}
});
});
let server = http.createServer(function (req, res) {
proxy.web(req, res, option, function (e) {
console.log(e);
});
});
console.log("listening on port 5051");
server.listen(5051);
我最终使用 CherryPy 编写了一个小型 Python 服务器,并使用 mitmproxy 代理了网络应用程序。现在一切都很顺利。也许我在使用 node-http-proxy 时做错了,但我也对在生产环境中使用它持怀疑态度。
我有一个 http-proxy 来代理任何网站,并在将 HTML 服务回客户端之前注入一些自定义 JS 文件。每当我尝试访问代理网站时,它都会挂断或浏览器似乎不确定加载。但是当我检查 HTML 源时,我成功地注入了我的自定义 JavaScript 文件。这是代码:
const cheerio = require('cheerio');
const http = require('http');
const httpProxy = require('http-proxy');
const { ungzip } = require('node-gzip');
_initProxy(host: string) {
let proxy = httpProxy.createProxyServer({});
let option = {
target: host,
selfHandleResponse: true
};
proxy.on('proxyRes', function (proxyRes, req, res) {
let body = [];
proxyRes.on('data', function (chunk) {
body.push(chunk);
});
proxyRes.on('end', async function () {
let buffer = Buffer.concat(body);
if (proxyRes.headers['content-encoding'] === 'gzip') {
try {
let $ = null;
const decompressed = await ungzip(buffer);
const scriptTag = '<script src="my-customjs.js"></script>';
$ = await cheerio.load(decompressed.toString());
await $('body').append(scriptTag);
res.end($.html());
} catch (e) {
console.log(e);
}
}
});
});
let server = http.createServer(function (req, res) {
proxy.web(req, res, option, function (e) {
console.log(e);
});
});
console.log("listening on port 5051");
server.listen(5051);
}
如果我做错了什么,有人能告诉我吗,node-http-proxy 似乎快要死了,不能太依赖它,因为代理有时可以工作,然后在下一次死掉 运行,取决于我运行服务器的次数。
你的代码看起来不错,所以我很好奇并试了一下。
尽管您确实记录了一些错误,但您没有处理以下几种情况:
- 服务器 returns 一个 body 没有响应(
cheerio
将在这种情况下生成一个空的 HTML body) - 服务器 return 未压缩的响应(您的代码将自动丢弃响应)
我对你的代码做了一些修改。
更改初始选项
let proxy = httpProxy.createProxyServer({
secure: false,
changeOrigin: true
});
- 不验证 TLS 证书
secure: false
- 发送正确的
Host
headerchangeOrigin: true
删除if
语句并用三元替换它
const isCompressed = proxyRes.headers['content-encoding'] === 'gzip';
const decompressed = isCompressed ? await ungzip(buffer) : buffer;
您还可以删除 cheerio
上的 2 await
,Cheerio 不是异步的,return 也不能 await
。
最终代码
这是有效的最终代码。你提到 "it looks like node-http-proxy is dying a lot [...] depending on how many times I ran the server." 我没有遇到过这样的稳定性问题,所以如果发生这种情况,你的问题可能出在其他地方(坏 ram?)
const cheerio = require('cheerio');
const http = require('http');
const httpProxy = require('http-proxy');
const { ungzip } = require('node-gzip');
const host = 'https://github.com';
let proxy = httpProxy.createProxyServer({
secure: false,
changeOrigin: true
});
let option = {
target: host,
selfHandleResponse: true
};
proxy.on('proxyRes', function (proxyRes, req, res) {
console.log(`Proxy response with status code: ${proxyRes.statusCode} to url ${req.url}`);
if (proxyRes.statusCode == 301) {
throw new Error('You should probably do something here, I think there may be an httpProxy option to handle redirects');
}
let body = [];
proxyRes.on('data', function (chunk) {
body.push(chunk);
});
proxyRes.on('end', async function () {
let buffer = Buffer.concat(body);
try {
let $ = null;
const isCompressed = proxyRes.headers['content-encoding'] === 'gzip';
const decompressed = isCompressed ? await ungzip(buffer) : buffer;
const scriptTag = '<script src="my-customjs.js"></script>';
$ = cheerio.load(decompressed.toString());
$('body').append(scriptTag);
res.end($.html());
} catch (e) {
console.log(e);
}
});
});
let server = http.createServer(function (req, res) {
proxy.web(req, res, option, function (e) {
console.log(e);
});
});
console.log("listening on port 5051");
server.listen(5051);
我最终使用 CherryPy 编写了一个小型 Python 服务器,并使用 mitmproxy 代理了网络应用程序。现在一切都很顺利。也许我在使用 node-http-proxy 时做错了,但我也对在生产环境中使用它持怀疑态度。