我正在尝试开发一个 Firefox 扩展,它将每个 HTTP 请求丢弃到某个站点并返回一个虚假的响应。任何请求都不应到达原始 Web 服务器,但我希望能够创建自定义响应。我试图拦截“http-on-modify-request”消息,但取消请求似乎不起作用,因为之后我无法模拟真实的响应。同样,使用 nsITraceableStream 实例,我似乎无法真正取消请求。我没有想法,有人可以帮忙吗?
最佳答案
自 Firefox 21 起,以下答案已被取代,现在是 nsIHttpChannel.redirectTo() method做得很好。你可以重定向到一个数据:URI,像这样的东西会起作用:
Components.utils.import("resource://gre/modules/Services.jsm");
const Ci = Components.interfaces;
[...]
onModifyRequest: function(channel)
{
if (channel instanceof Ci.nsIHttpChannel && shouldRedirect(channel.URI.spec))
{
let redirectURL = "data:text/html," + encodeURIComponent("<html>Hi there!</html>");
channel.redirectTo(Services.io.newURI(redirectURI, null, null));
}
}
原始答案(已过时)
每个 channel 都有其关联的 stream listener在收到数据时得到通知。伪造响应所需要做的就是获取此监听器并向其提供错误数据。和 nsITraceableChannel实际上是这样做的方法。您需要用您自己的不会执行任何操作的常规监听器替换 channel 的常用监听器,之后您可以取消该 channel 而不通知监听器。然后你触发监听器并给它你自己的数据。像这样:
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;
[...]
onModifyRequest: function(channel)
{
if (channel instanceof Ci.nsIHttpChannel && channel instanceof Ci.nsITraceableChannel)
{
// Our own listener for the channel
var fakeListener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener,
Ci.nsIRequestObserver, Ci.nsIRunnable]),
oldListener: null,
run: function()
{
// Replace old listener by our fake listener
this.oldListener = channel.setNewListener(this);
// Now we can cancel the channel, listener old won't notice
//channel.cancel(Components.results.NS_BINDING_ABORTED);
},
onDataAvailable: function(){},
onStartRequest: function(){},
onStopRequest: function(request, context, status)
{
// Call old listener with our data and set "response" headers
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stream.setData("<html>Hi there!</html>", -1);
this.oldListener.onStartRequest(channel, context);
channel.setResponseHeader("Refresh", "5; url=http://google.com/", false);
this.oldListener.onDataAvailable(channel, context, stream, 0, stream.available());
this.oldListener.onStopRequest(channel, context, Components.results.NS_OK);
}
}
// We cannot replace the listener right now, see
// https://bugzilla.mozilla.org/show_bug.cgi?id=646370.
// Do it asynchronously instead.
var threadManager = Cc["@mozilla.org/thread-manager;1"]
.getService(Ci.nsIThreadManager);
threadManager.currentThread.dispatch(fakeListener, Ci.nsIEventTarget.DISPATCH_NORMAL);
}
}
此代码的问题仍然是,如果 channel 被取消,页面将显示为空白(所以我评论了那行)- 听众似乎仍在查看 channel 并注意到它已被取消。
关于javascript - Firefox 扩展 : Cancel requests and emit fake responses,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7222577/
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类
我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我正在使用Watir运行一个Ruby脚本来为我自动化一些事情。我试图自动将一些文件保存到某个目录。因此,在我的Mozilla设置中,我将默认下载目录设置为桌面并选择自动保存文件。但是,当我开始运行我的脚本时,这些更改并没有反射(reflect)出来。似乎首选项恢复为默认值。我已经包括以下内容require"rubygems"#Optional.require"watir-webdriver"#Forwebautomation.require"win32ole"#Forfilesavedialog.并打开一个新的firefox实例:browser=Watir::Browser.new(:
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我想编写一个ruby脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"
这个问题有两个部分。在RubyProgrammingLanguage一书中,有一个使用模块扩展字符串对象和类的示例(第8.1.1节)。第一个问题。为什么如果您使用新方法扩展类,然后创建该类的对象/实例,则无法访问该方法?irb(main):001:0>moduleGreeter;defciao;"Ciao!";end;end=>nilirb(main):002:0>String.extend(Greeter)=>Stringirb(main):003:0>String.ciao=>"Ciao!"irb(main):004:0>x="foobar"=>"foobar"irb(main):
假设我们有A、B、C类。Adefself.inherited(sub)#metaprogramminggoeshere#takeclassthathasjustinheritedclassA#andforfooclassesinjectprepare_foo()as#firstlineofmethodthenrunrestofthecodeenddefprepare_foo#=>prepare_foo()neededhere#somecodeendendBprepare_foo()neededhere#somecodeendend如您所见,我正在尝试将foo_prepare()调用注入
我有这个: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