Search code examples
rubyseleniumsinatraheadless

Headless operations don't work inside Sinatra route


I am using the headless and selenium-webdriver gems to launch a headless Firefox browser:

headless = Headless.new(
  video: {
    frame_rate: 12,
    codec: 'libx264'
  }
)
headless.start
driver = Selenium::WebDriver.for(:firefox)

With this code I can write the following:

driver.navigate.to("http://google.com")

Yet the following raises an error after I visit '/' in the browser:

get '/' do
  driver.navigate.to("http://google.com")
  erb :root
end

The error is as follows:

*** Errno::ECONNREFUSED Exception: Failed to open TCP connection to 127.0.0.1:7055 (Connection refused - connect(2) for "127.0.0.1" port 7055)

I'm pretty sure this is because the driver.navigate is not being called in the headless scope, therefore it can't connect to the Firefox instance.

I have also tried using the modular sinatra style, but the same error occurred.


workaround

What I ended up doing is separating the headless server in a separate script. This script has loop and gets input, printing the output of running the command in the headless scope. Then from the sinatra server, i use PTY.spawn to instantiate the server and pass around its stdin and stdout so I can use it in my Sinatra app. This way the headless script is only run once (therefore multiple headless servers aren't started) and I can connect to it from my Sinatra routes. I can't interact with the headless script's variables or methods directly - I need to just use i/o.

I am hoping for an answer which hows how to make the original code work, though (when the sinatra app's routes are called in headless scope)


Solution

  • One possible trick that can help:

    this = self
    get '/' do
      this.driver.navigate.to("http://google.com")
      erb :root
    end