Подтвердить что ты не робот

VCRProxy: запись вызовов PhantomJS ajax с видеомагнитофоном внутри Capybara

Я уже занимался некоторыми исследованиями в этой области, но не нашел решения. У меня есть сайт, на котором асинхронные вызовы ajax делаются в facebook (с использованием JSONP). Я записываю все свои HTTP-запросы на стороне Ruby с видеомагнитофоном, поэтому я подумал, что было бы здорово использовать эту функцию для вызовов AJAX.

Итак, я немного поиграл и придумал попытку прокси. Я использую PhantomJS как безгласный браузер и полтергейст для интеграции внутри Capybara. Полтергейст теперь настроен на использование прокси-сервера следующим образом:

  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)

Это хорошо работает с каждым вызовом localhost, и они хорошо записываются. Файлы HTML, JS и CSS записываются видеомагнитофоном. Затем я включил параметр c.ignore_localhost = true, поэтому бесполезно (по-моему) записывать вызовы localhost.

Затем я снова попытался, но мне пришлось выяснить, что вызовы AJAX, сделанные на странице, не записываются. Хуже того, они больше не работают внутри тестов.

Итак, чтобы ответить на этот вопрос, мой вопрос: почему все вызовы в JS файлы на локальном хосте записываются, а JSONP-вызовы на внешние ressources не? Это не может быть проблемой jsonP, потому что это "обычный" запрос ajax. Или есть ошибка внутри phantomjs, что вызовы AJAX не проксированы? Если да, то как мы можем это исправить?

Если он работает, я хочу интегрировать процедуру запуска и остановки внутри

------- UPDATE -------

Я провел некоторое исследование и пришел к следующему пункту: у прокси-сервера есть некоторые проблемы с вызовами HTTPS и двоичными данными через вызовы HTTPS.

Я запустил сервер и сделал несколько завитушек:

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). Тогда я подумал, может быть, видеомагнитофон не может издеваться над HTTPS-запросами. Но используя этот script, видеомагнитофон высмеивает 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

Так в чем же проблема? Видеомагнитофон обрабатывает HTTPS, а прокси-сервер обрабатывает HTTPS. Почему они не играют вместе?

4b9b3361

Ответ 1

Итак, я провел некоторое исследование, и теперь у меня есть очень простой пример работающего прокси-сервера VCR, который обрабатывает HTTPS-вызовы как прокси-сервер MITM (если вы отключите проверку безопасности на своем клиенте). Я был бы очень рад, если бы кто-то мог внести свой вклад и помочь мне воплотить эту жизнь в жизнь.

Вот репозиторий github: https://github.com/23tux/vcr_proxy

Ответ 2

Мой друг рассказал мне о https://github.com/oesmith/puffing-billy, но я еще не использовал его, поэтому я не могу прокомментировать, насколько хорошо это может сработать.