Class: Superbot::Web

Inherits:
Object
  • Object
show all
Defined in:
lib/superbot/web.rb

Instance Method Summary collapse

Constructor Details

#initialize(webdriver_type: 'cloud', region: nil) ⇒ Web

Returns a new instance of Web.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/superbot/web.rb', line 12

def initialize(webdriver_type: 'cloud', region: nil)
  @sinatra = Sinatra.new
  @sinatra.set :bind, "127.0.0.1"
  @sinatra.set :silent_sinatra, true
  @sinatra.set :silent_webrick, true
  @sinatra.set :silent_access_log, false
  @sinatra.server_settings[:Silent] = true
  instance = self

  @sinatra.before do
    headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Headers'] = 'accept, authorization, origin'
  end

  @sinatra.options '*' do
    response.headers['Allow'] = 'HEAD,GET,PUT,DELETE,OPTIONS,POST'
    response.headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Cache-Control, Accept'
  end

  @sinatra.get "/__superbot/v1/ping" do
    "PONG"
  end

  @sinatra.post "/__superbot/v1/convert" do
    converted_script = Superbot::Capybara::Convert.call(request.body.read)
    instance.capybara_runner.run(converted_script)
  end

  @webdriver_type = webdriver_type
  webdriver_uri = URI.parse(Superbot.webdriver_endpoint(@webdriver_type))
  @request_settings = {
    scheme:   webdriver_uri.scheme,
    host:     webdriver_uri.host,
    port:     webdriver_uri.port,
    path:     webdriver_uri.path
  }
  @region = region

  %w(get post put patch delete).each do |verb|
    @sinatra.send(verb, "/wd/hub/*") do
      begin
        request_path = request.path_info.gsub('/wd/hub', '')
        content_type 'application/json'
        response = instance.remote_webdriver_request(
          verb.capitalize,
          request_path,
          request.query_string,
          request.body,
          instance.incomming_headers(request)
        )
        status response.code
        headers instance.all_headers(response)
        response.body
      rescue StandardError => e
        error_message = "Remote webdriver doesn't respond"
        puts error_message, e
        halt 500, { message: error_message }.to_json
      end
    end
  end
end

Instance Method Details

#all_headers(response) ⇒ Object



118
119
120
121
122
123
124
# File 'lib/superbot/web.rb', line 118

def all_headers(response)
  header_list = {}
  response.header.each_capitalized do |k, v|
    header_list[k] = v unless k == "Transfer-Encoding"
  end
  header_list
end

#capybara_runnerObject



75
76
77
# File 'lib/superbot/web.rb', line 75

def capybara_runner
  @capybara_runner ||= Superbot::Capybara::Runner.new
end

#cloud_teleport?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/superbot/web.rb', line 110

def cloud_teleport?
  %w(cloud local_cloud).include?(@webdriver_type)
end

#creating_session?(method, path) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/superbot/web.rb', line 114

def creating_session?(method, path)
  method.casecmp?('post') && path == '/session'
end

#incomming_headers(request) ⇒ Object



126
127
128
# File 'lib/superbot/web.rb', line 126

def incomming_headers(request)
  request.env.map { |header, value| [header[5..-1].split("_").map(&:capitalize).join('-'), value] if header.start_with?("HTTP_") }.compact.to_h
end

#output_response_errors(response) ⇒ Object



130
131
132
133
134
135
136
137
# File 'lib/superbot/web.rb', line 130

def output_response_errors(response)
  return unless response.is_a?(Net::HTTPClientError) || response.is_a?(Net::HTTPServerError)

  parsed_body = JSON.parse(response.body, symbolize_names: true)
  puts "Error: #{parsed_body[:error]}"
rescue JSON::ParserError
  puts "Request to webdriver failed with status: #{response.code}"
end

#quit!Object



155
156
157
# File 'lib/superbot/web.rb', line 155

def quit!
  @sinatra&.quit!
end

#remote_webdriver_request(type, path, query_string, body, new_headers) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/superbot/web.rb', line 79

def remote_webdriver_request(type, path, query_string, body, new_headers)
  uri = URI.const_get(@request_settings[:scheme].upcase).build(
    @request_settings.merge(
      path: @request_settings[:path] + path,
      query: query_string.empty? ? nil : query_string
    )
  )
  req = Net::HTTP.const_get(type).new(uri, new_headers.merge('Content-Type' => 'application/json'))

  request_body = body.read
  if cloud_teleport?
    user_auth_creds = Superbot::Cloud.credentials&.slice(:username, :token)
    req.basic_auth(*user_auth_creds.values) if user_auth_creds

    if @region && creating_session?(type, path)
      parsed_body = JSON.parse(request_body)
      parsed_body['desiredCapabilities']['superOptions'] = { 'region': @region }
      request_body = parsed_body.to_json
    end
  end
  req.body = request_body

  Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    http.read_timeout = Superbot.cloud_timeout
    http.request(req)
  end.tap do |response|
    output_response_errors(response)
  end
end

#run!Object



139
140
141
# File 'lib/superbot/web.rb', line 139

def run!
  @sinatra.run_async!
end

#run_async_after_running!Object



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/superbot/web.rb', line 143

def run_async_after_running!
  Thread.new do
    @sinatra.run!
  end

  loop do
    break if @sinatra.running?

    sleep 0.001
  end
end