我想编写能够修改响应正文的 Node.js http 代理。到目前为止我已经这样做了:
http = require('http'),
httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer();
http.createServer( function (req, res){
//here I want to change the body I guess
proxy.web(req, res, {
target: req.url
});
}).listen(8013);
我曾尝试使用 res.write(),但它给我一个错误“发送后无法设置 header ”。好吧,我不想更改标题,我想更改正文。
我该如何改变 body ?任何建议将不胜感激。
最佳答案
你得到这个错误是因为写入 HTTP 响应必然会改变 header ; Content-Length 必须正确。
我解决这个问题的方法是缓冲整个响应主体,使用 cheerio解析和摆弄,然后将结果发送给客户端。
我通过猴子修补 res.writeHead、res.write 和 res.end 之后将请求传递给 http -代理模块。
function requestHandler(req, res) {
var writeHead = res.writeHead, write = res.write, end = res.end;
res.writeHead = function(status, reason, headers) {
if (res.headersSent) return req.socket.destroy(); // something went wrong; abort
if (typeof reason == 'object') headers = reason;
headers = headers || {};
res.headers = headers;
if (headers['content-type'] && headers['content-type'].substr(0,9) == 'text/html') { // we should only fiddle with HTML responses
delete headers['transfer-encoding']; // since we buffer the entire response, we'll send a proper Content-Length later with no Transfer-Encoding.
var buf = new Buffer();
res.write = function(data, encoding) {
if (Buffer.isBuffer(data)) buf = Buffer.concat([buf, data]); // append raw buffer
else buf = Buffer.concat([buf, new Buffer(data, encoding)]); // append string with optional character encoding (default utf8)
if (buf.length > 10 * 1024 * 1024) error('Document too large'); // sanity check: if the response is huge, bail.
// ...we don't want to let someone bring down the server by filling up all our RAM.
}
res.end = function(data, encoding) {
if (data) res.write(data, encoding);
var $ = cheerio.load(buf.toString());
// This is where we can modify the response. For example,
$('body').append('<p>Hi mom!</p>');
buf = new Buffer($.html()); // we have to convert back to a buffer so that we can get the *byte count* (rather than character count) of the body
res.headers['content-type'] = 'text/html; charset=utf-8'; // JS always deals in UTF-8.
res.headers['content-length'] = buf.length;
// Finally, send the modified response out using the real `writeHead`/`end`:
writeHead.call(res, status, res.headers);
end.call(res, buf);
}
} else {
writeHead.call(res, status, headers); // if it's not HTML, let the response go through normally
}
}
proxy.web(req, res, {
target: req.url
});
function error(msg) { // utility function to report errors
if (res.headersSent) end.call(res, msg);
else {
msg = new Buffer(msg);
writeHead.call(res, 502, { 'Content-Type': 'text/plain', 'Content-Length': msg.length });
end.call(res, msg);
}
}
}
关于javascript - Node.js HTTP 代理修改主体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22487048/
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)
有人知道如何将capybarapoltergeist的用户代理覆盖到移动用户代理以进行测试吗?我发现了一些有关为seleniumwebdriver配置它的信息:http://blog.plataformatec.com.br/2011/03/configuring-user-agents-with-capybara-selenium-webdriver/这在capybara闹鬼中怎么可能? 最佳答案 请参阅poltergeistgithub页面上的链接:https://github.com/teampoltergeist/polte
我正在使用Ruby/Mechanize编写一个“自动填写表格”应用程序。它几乎可以工作。我可以使用精彩CharlesWeb代理以查看服务器和我的Firefox浏览器之间的交换。现在我想使用Charles查看服务器和我的应用程序之间的交换。Charles在端口8888上代理。假设服务器位于https://my.host.com。.一件不起作用的事情是:@agent||=Mechanize.newdo|agent|agent.set_proxy("my.host.com",8888)end这会导致Net::HTTP::Persistent::Error:...lib/net/http/pe
我希望访问我机器上的所有HTTP流量(我的Windows机器-不是服务器)。据我了解,拥有一个本地代理是所有流量路线的必经之路。我一直在谷歌搜索但未能找到任何资源(关于Ruby)来帮助我。非常感谢任何提示或链接。 最佳答案 WEBrick中有一个HTTP代理(Rubystdlib的一部分)和here's一个实现示例。如果你喜欢生活在边缘,还有em-proxy伊利亚·格里戈里克。这postIlya暗示它似乎确实需要一些调整来解决您的问题。 关于ruby-如何捕获所有HTTP流量(本地代理)
我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan
我有一个包含多个组件的存储库,其中大部分是用JavaScript(Node.js)编写的,一个是用Ruby(RubyonRails)编写的。我想要一个.travis.yml文件来触发一个运行每个组件的所有测试的构建。根据thisTravisCIGoogleGroupthread,目前还没有官方支持。我的目录结构是这样的:.├──构建服务器├──核心├──扩展├──网络应用├──流浪文件├──package.json├──.travis.yml└──生成文件我希望能够运行特定版本的Ruby(2.2.2)和Node.js(0.12.2)。我已经有了一个make目标,所以maketest在每
假设我有一个名为Product的模型,其中有一个名为brand的字段。假设brand的值以this_is_a_brand格式存储。我可以在模型(或其他任何地方)中定义一个方法,允许我在调用brand之前修改它的值吗?例如,如果我调用@product.brand,我想得到ThisisaBrand,而不是this_is_a_brand。 最佳答案 我建议使用方括号语法([]和[]=)而不是read_attribute和write_attribute。方括号语法更短并且designedtowraptheprotectedread/writ
我正在使用Net::FTPruby库连接到FTP服务器并下载文件。一切正常,但现在我需要使用出站代理,因为他们的防火墙将IP地址列入白名单,并且我正在使用Heroku来托管该站点。我正在试用新的Proximo附加组件,它看起来很有前途,但我无法让Net::FTP使用它。我在Net::FTPdocs中看到以下内容:connect(host,port=FTP_PORT)EstablishesanFTPconnectiontohost,optionallyoverridingthedefaultport.IftheenvironmentvariableSOCKS_SERVERisset,