ruby - VCR代理 : Record PhantomJS ajax calls with VCR inside Capybara

标签 ruby ajax https phantomjs vcr

我已经在这个领域做了一些研究,但没有找到任何解决方案。我有一个站点,其中对 facebook 进行异步 ajax 调用(使用 JSONP)。我正在使用 VCR 在 Ruby 端记录我所有的 HTTP 请求,所以我认为将此功能也用于 AJAX 调用会很酷。

所以我尝试了一下,想出了一个代理尝试。我正在使用 PhantomJS 作为 headless 浏览器和 poltergeist 来集成到 Capybara 中。 Poltergeist 现在配置为使用这样的代理:

  Capybara.register_driver :poltergeist_vcr do |app|
    options = {
      :phantomjs_options => [
        "--proxy=127.0.0.1:9100",
        "--proxy-type=http",
        "--ignore-ssl-errors=yes",
        "--web-security=no"
      ],
      :inspector => true
    }
    Capybara::Poltergeist::Driver.new(app, options)
  end
  Capybara.javascript_driver = :poltergeist_vcr

出于测试目的,我编写了一个基于 WEbrick 的代理服务器,它集成了 VCR:

require 'io/wait'
require 'webrick'
require 'webrick/httpproxy'

require 'rubygems'
require 'vcr'

module WEBrick
  class VCRProxyServer < HTTPProxyServer
    def service(*args)
      VCR.use_cassette('proxied') { super(*args) }
    end
  end
end

VCR.configure do |c|
  c.stub_with :webmock
  c.cassette_library_dir = '.'
  c.default_cassette_options = { :record => :new_episodes }
  c.ignore_localhost = true
end

IP   = '127.0.0.1'
PORT = 9100

reader, writer = IO.pipe

@pid = fork do
  reader.close
  $stderr = writer
  server = WEBrick::VCRProxyServer.new(:BindAddress => IP, :Port => PORT)
  trap('INT') { server.shutdown }
  server.start
end

raise 'VCR Proxy did not start in 10 seconds' unless reader.wait(10)

这适用于每个本地主机调用,并且它们会得到很好的记录。 HTML、JS 和 CSS 文件由 VCR 录制。然后我启用了 c.ignore_localhost = true 选项,因为它没有用(在我看来)来记录本地主机调用。

然后我再次尝试,但我不得不弄清楚,在页面上进行的 AJAX 调用没有被记录下来。更糟糕的是,它们不再在测试中起作用。

言归正传,我的问题是:为什么所有对本地主机上JS文件的调用都被记录下来,而对外部资源的JSONP调用却没有?它不可能是 jsonP 的东西,因为它是一个“正常”的 ajax 请求。或者 phantomjs 中是否存在错误,即 AJAX 调用未被代理?如果是这样,我们该如何解决?

如果它正在运行,我想在里面集成启动和停止过程

--------更新--------

我做了一些研究,得出以下几点:代理在 HTTPS 调用和通过 HTTPS 调用的二进制数据方面存在一些问题。

我启动了服务器,并进行了一些 curl 调用:

curl --proxy 127.0.0.1:9100 http://d3jgo56a5b0my0.cloudfront.net/images/v7/application/stories_view/icons/bug.png

此通话会按应有的方式进行录音。代理的请求和响应输出是

GET http://d3jgo56a5b0my0.cloudfront.net/images/v7/application/stories_view/icons/bug.png HTTP/1.1
User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
Host: d3jgo56a5b0my0.cloudfront.net
Accept: */*
Proxy-Connection: Keep-Alive

HTTP/1.1 200 OK 
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12)
Date: Tue, 20 Nov 2012 10:13:10 GMT
Content-Length: 0
Connection: Keep-Alive

但是这个调用没有被记录下来,一定是 HTTPS 有问题:

curl --proxy 127.0.0.1:9100 https://d3jgo56a5b0my0.cloudfront.net/images/v7/application/stories_view/icons/bug.png

标题输出是:

CONNECT d3jgo56a5b0my0.cloudfront.net:443 HTTP/1.1
Host: d3jgo56a5b0my0.cloudfront.net:443
User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
Proxy-Connection: Keep-Alive

HTTP/1.1 200 OK 
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12)
Date: Tue, 20 Nov 2012 10:15:48 GMT
Content-Length: 0
Connection: close

所以,我认为代理可能无法处理 HTTPS,但它可以(只要我在 cURL 调用后在控制台上获得输出)。然后我想,也许 VCR 不能模拟 HTTPS 请求。但是使用这个脚本,当我不在代理中使用它时,VCR 模拟了 HTTPS 请求:

require 'vcr'

VCR.configure do |c|
  c.hook_into :webmock
  c.cassette_library_dir = 'cassettes'
end

uri = URI("https://d3jgo56a5b0my0.cloudfront.net/images/v7/application/stories_view/icons/bug.png")

VCR.use_cassette('https', :record => :new_episodes) do
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  response = http.request_get(uri.path)
  puts response.body
end

那么问题是什么? VCR 处理 HTTPS,代理处理 HTTPS。他们为什么不一起玩?

最佳答案

所以我做了一些研究,现在我有一个非常基本的工作 VCR 代理服务器示例,它作为 MITM 代理服务器处理 HTTPS 调用(如果您停用客户端中的安全检查)。如果有人可以做出贡献并帮助我实现这件事,我将非常高兴。

这里是 github 仓库:https://github.com/23tux/vcr_proxy

关于ruby - VCR代理 : Record PhantomJS ajax calls with VCR inside Capybara,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13039251/

相关文章:

mysql - 在 ROR 中创建数据库时出错

ruby - 从模块创建类方法

android - 对于电话/服务器通信,Android 是否比 AJAX 更可靠?

javascript - AJAX 请求从 HTTPS 页面到 HTTP Url

ruby - ruby 中这个简单的 If 函数我做错了什么

java - 为什么 App Engine 上的 JRuby 应用程序需要很长时间才能启动(与 Python 应用程序相比)?

javascript - 使用ajax向node.js进行AJAX查询获取和发布数据时出现错误

javascript - Uncaught ReferenceError : response is not defined

https - 游戏框架 [2.0] HTTPS

javascript - 将我网站中的所有链接更改为 https