Skip to content

Commit

Permalink
fix: #216 Configure with ws/wss url (#435)
Browse files Browse the repository at this point in the history
  • Loading branch information
route authored Jan 7, 2024
1 parent 3c95a10 commit e1efe3e
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 27 deletions.
1 change: 0 additions & 1 deletion lib/ferrum/browser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ def start

begin
@process.start
@options.ws_url = @process.ws_url&.merge(path: "/")
@options.default_user_agent = @process.default_user_agent

@client = Client.new(@process.ws_url, options)
Expand Down
5 changes: 3 additions & 2 deletions lib/ferrum/browser/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ class Options

attr_reader :window_size, :logger, :ws_max_receive_size,
:js_errors, :base_url, :slowmo, :pending_connection_errors,
:url, :env, :process_timeout, :browser_name, :browser_path,
:url, :ws_url, :env, :process_timeout, :browser_name, :browser_path,
:save_path, :proxy, :port, :host, :headless, :browser_options,
:ignore_default_browser_options, :xvfb, :flatten
attr_accessor :timeout, :ws_url, :default_user_agent
attr_accessor :timeout, :default_user_agent

def initialize(options = nil)
@options = Hash(options&.dup)
Expand Down Expand Up @@ -44,6 +44,7 @@ def initialize(options = nil)
@logger = parse_logger(@options[:logger])
@base_url = parse_base_url(@options[:base_url]) if @options[:base_url]
@url = @options[:url].to_s if @options[:url]
@ws_url = @options[:ws_url].to_s if @options[:ws_url]

@options = @options.merge(window_size: @window_size).freeze
@browser_options = @options.fetch(:browser_options, {}).freeze
Expand Down
48 changes: 32 additions & 16 deletions lib/ferrum/browser/process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,15 @@ def self.directory_remover(path)
def initialize(options)
@pid = @xvfb = @user_data_dir = nil

if options.ws_url
response = parse_json_version(options.ws_url)
self.ws_url = response&.[]("webSocketDebuggerUrl") || options.ws_url
return
end

if options.url
url = URI.join(options.url, "/json/version")
response = JSON.parse(::Net::HTTP.get(url))
self.ws_url = response["webSocketDebuggerUrl"]
parse_browser_versions
response = parse_json_version(options.url)
self.ws_url = response&.[]("webSocketDebuggerUrl")
return
end

Expand Down Expand Up @@ -100,7 +104,7 @@ def start
ObjectSpace.define_finalizer(self, self.class.process_killer(@pid))

parse_ws_url(read_io, @process_timeout)
parse_browser_versions
parse_json_version(ws_url)
ensure
close_io(read_io, write_io)
end
Expand Down Expand Up @@ -174,25 +178,37 @@ def ws_url=(url)
@port = @ws_url.port
end

def parse_browser_versions
return unless ws_url.is_a?(Addressable::URI)
def close_io(*ios)
ios.each do |io|
io.close unless io.closed?
rescue IOError
raise unless RUBY_ENGINE == "jruby"
end
end

def parse_json_version(url)
url = URI.join(url, "/json/version")

if %w[wss ws].include?(url.scheme)
url.scheme = case url.scheme
when "ws"
"http"
when "wss"
"https"
end
end

version_url = URI.parse(ws_url.merge(scheme: "http", path: "/json/version"))
response = JSON.parse(::Net::HTTP.get(version_url))
response = JSON.parse(::Net::HTTP.get(URI(url.to_s)))

@v8_version = response["V8-Version"]
@browser_version = response["Browser"]
@webkit_version = response["WebKit-Version"]
@default_user_agent = response["User-Agent"]
@protocol_version = response["Protocol-Version"]
end

def close_io(*ios)
ios.each do |io|
io.close unless io.closed?
rescue IOError
raise unless RUBY_ENGINE == "jruby"
end
response
rescue StandardError
# nop
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/ferrum/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ class Client
extend Forwardable
delegate %i[timeout timeout=] => :options

attr_reader :options, :subscriber
attr_reader :ws_url, :options, :subscriber

def initialize(ws_url, options)
@command_id = 0
@ws_url = ws_url
@options = options
@pendings = Concurrent::Hash.new
@ws = WebSocket.new(ws_url, options.ws_max_receive_size, options.logger)
Expand Down
20 changes: 16 additions & 4 deletions lib/ferrum/client/web_socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,27 @@ module Ferrum
class Client
class WebSocket
WEBSOCKET_BUG_SLEEP = 0.05
DEFAULT_PORTS = { "ws" => 80, "wss" => 443 }.freeze
SKIP_LOGGING_SCREENSHOTS = !ENV["FERRUM_LOGGING_SCREENSHOTS"]

attr_reader :url, :messages

def initialize(url, max_receive_size, logger)
@url = url
@logger = logger
uri = URI.parse(@url)
@sock = TCPSocket.new(uri.host, uri.port)
@url = url
@logger = logger
uri = URI.parse(@url)
port = uri.port || DEFAULT_PORTS[uri.scheme]

if port == 443
tcp = TCPSocket.new(uri.host, port)
ssl_context = OpenSSL::SSL::SSLContext.new
@sock = OpenSSL::SSL::SSLSocket.new(tcp, ssl_context)
@sock.sync_close = true
@sock.connect
else
@sock = TCPSocket.new(uri.host, port)
end

max_receive_size ||= ::WebSocket::Driver::MAX_LENGTH
@driver = ::WebSocket::Driver.client(self, max_length: max_receive_size)
@messages = Queue.new
Expand Down
2 changes: 1 addition & 1 deletion lib/ferrum/target.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def build_client
end

def ws_url
options.ws_url.merge(path: "/devtools/page/#{id}").to_s
@browser_client.ws_url.merge(path: "/devtools/page/#{id}")
end
end
end
21 changes: 20 additions & 1 deletion spec/browser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,29 @@
end

it "supports :url argument" do
with_external_browser do |url|
with_external_browser do |url, process|
browser = Ferrum::Browser.new(url: url)
browser.go_to(base_url)
expect(browser.body).to include("Hello world!")
expect(process.v8_version).not_to be_nil
expect(process.browser_version).not_to be_nil
expect(process.webkit_version).not_to be_nil
expect(process.default_user_agent).not_to be_nil
expect(process.protocol_version).not_to be_nil
ensure
browser&.quit
end
end

it "supports :ws_url argument" do
with_external_browser do |url, process|
uri = Addressable::URI.parse(url)
browser = Ferrum::Browser.new(ws_url: "ws://#{uri.host}:#{uri.port}")
expect(process.v8_version).not_to be_nil
expect(process.browser_version).not_to be_nil
expect(process.webkit_version).not_to be_nil
expect(process.default_user_agent).not_to be_nil
expect(process.protocol_version).not_to be_nil
ensure
browser&.quit
end
Expand Down
2 changes: 1 addition & 1 deletion spec/support/global_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def with_external_browser(host: "127.0.0.1", port: 32_001)

begin
process.start
yield "http://#{host}:#{port}"
yield "http://#{host}:#{port}", process
ensure
process.stop
end
Expand Down

0 comments on commit e1efe3e

Please sign in to comment.