There is a some heavy page, that after visiting it Selenium doesn't respond to Capybara for a minute, so whatever do I call, throws Net::ReadTimeout.
I could edit it globally somehow like:
http_client = Selenium::WebDriver::Remote::Http::Default.new
http_client.timeout = 120
Capybara::Selenium::Driver.new(app,
http_client: http_client,
But in the case of some repetitive timeouts my tests would last for too long, so I do not want to increase timeout globally.
I want to increase it for a single test somehow like:
before do
#timeout = page.driver.bridge.http.timeout
page.driver.bridge.http.timeout = 120
end
after do
page.driver.bridge.http.timeout = #timeout
end
But in /lib/selenium/webdriver/common/driver.rb the bridge method is private, while only browser and capabilities are exposed to public.
So what is the correct way to edit this timeout attribute globally?
UPD: Even if I find how to set this attribute, seems like the before/after approach doesn't work, because #http ||= ( saves the default timeout value in the first before in the chain of setUps, that precede mine.
Capybara has a default_wait_time that can be changed in the middle of tests:
using_wait_time 120 do
foo(bar)
end
This is how I broke private method, attribute without getter, and patched timeout for a single command:
http = page.driver.browser.send(:bridge).http.instance_variable_get(:#http)
old_timeout = http.read_timeout
begin
http.read_timeout = 120
find("anything") # here we had timeout
ensure
http.read_timeout = old_http_timeout
end
Related
If I use:
uri = URI("...")
http = Net::HTTP.new(uri.host, uri.port)
http.read_timeout = 60
# Add http.start here? Why?
for i in 1..n
uri = getFullUri()
req = Net::HTTP::Get.new(uri.path)
resp = http.request(req)
end
everything works fine.
Why do I need to add an http.start?
I see that http.started? returns false everywhere if I don't add http.start, but does this have a negative impact?
Which is the difference between those 2 cases?
Do the number of TCP connections or HTTP sessions differ?
http.start() will explicitly open the TCP connection at the point in time that it's been called. It's automatically called by http.request() if it hasn't been called already. To wit, here's the first few lines of the request method:
def request(req, body = nil, &block) # :yield: +response+
unless started?
start {
req['connection'] ||= 'close'
return request(req, body, &block)
}
end
Assuming getFullUri() takes less than a couple of seconds to run (see the keep_alive_timeout attribute), the original connection should be reused regardless of how it was created.
I'm expecting this piece of code to run for no longer than 5 seconds:
require 'httpi'
require 'timeout'
puts Time.new
begin
request,response=nil,nil
Timeout::timeout(5){
request=HTTPI::Request.new(url: "http://example.com")
response=HTTPI.get(request)
}
rescue
puts "except: #{$!}"
ensure
puts Time.new
end
But this is the output I'm getting:
2016-11-04 09:44:55 -0400
D, [2016-11-04T09:44:55.916557 #2476] DEBUG -- : HTTPI GET request to example.com (net_http)
except: execution expired
2016-11-04 09:45:16 -0400
I'm assuming NET's default HTTP timeout is 20 seconds, so Timeout::timeout is just allowing the code to run however long it wants. Why?
As you can see here, here and here, the Ruby's Timeout module is famous for having some problems.
You should consider not using this module, unless it is extremely necessary.
Instead, you can use the read_timeout and/or open_timeout options provided by the HTTPI's API.
request = HTTPI::Request.new(url: "http://example.com")
request.open_timeout = 5 # seconds
request.read_timeout = 5 # seconds
response = HTTPI.get(request)
I want to test a http get request. output something if timeout.
begin
url = "#{url}?#{params.to_param}"
Net::HTTP.get_response(URI.parse(url))
rescue Timeout::Error
puts "....."
end
How to raise a timeout error manually? or how to set a shorter timeout number for http request?
For a http request, should I change the default timeout number? How long is appropriate?
Based on http://opensourceconnections.com/blog/2008/04/24/adding-timeout-to-nethttp-get_response/
http = Net::HTTP.new(url.host, url.port)
http.read_timeout = 5
http.open_timeout = 5
resp = http.start() {|http|
http.get(url.path)
}
puts resp.kind_of? Net::HTTPResponse
puts resp.code
puts resp.body
To set timeout use:
http = Net::HTTP.new(host_param)
http.read_timeout = 500
There are few types of timeouts you can set. From docs:
open_timeout:
Number of seconds to wait for the connection to open.
Any number may be used, including Floats for fractional seconds.
If the HTTP object cannot open a connection in this many seconds,
it raises a Net::OpenTimeout exception. The default value is nil.
read_timeout:
Number of seconds to wait for one block to be read (via one read(2) call).
Any number may be used, including Floats for fractional seconds.
If the HTTP object cannot read data in this many seconds,
it raises a Net::ReadTimeout exception. The default value is 60 seconds.
ssl_timeout:
Sets the SSL timeout seconds.
I have a function that gets response over http. It runs some tests. Lately it started to happen that the test never finishes. So I introduced a time out. Then I found out that if I stop the database server the test script finishes with a db error that is in fact very good lead why the test didn't finish as expected. So to get the error could help to save me time. Because I wouldn't have to reproduce the whole test again manually.
Q1: Is there any way to let the connection time out but then get the response after the database server is restarted? Note that I cannot send the http request again as it would start the same text again.
Q2: I think that a solution would be to introduce timer while "waiting" for http response. But I don't know how to do that. Any idea?
My function is like
def execute_db2_script(url)
db2_database = 'RATIONAL'
http_read_timeout=$http_read_timeout
uri = URI.parse(url)
start = Time.new
connection = Net::HTTP.new(uri.host, 443)
connection.use_ssl = true
begin
response = connection.start() do |http|
http.open_timeout = 50
http.read_timeout = http_read_timeout
http.request_get(uri.request_uri)
end
rescue Timeout::Error
time_out_message ="security time out - after #{$http_read_timeout} sec"
return time_out_message
end
return response.body.gsub("\n","<BR>")
end
You can use retry keyword
def execute_db2_script(url)
...
begin
...
rescue Timeout::Error
time_out_message ="security time out - after #{$http_read_timeout} sec"
if "the server is going to restart then"
retry # this will restart begin-rescue-end block again
else
return time_out_message
end
end
response.body.gsub("\n","<BR>")
end
I have a ruby code that triggers php script over https.
Use case: The php script usually finishes in 5 minutes so I have set up time out for https request after 10 minutes. I need a timer that would trigger code after let's say 7 minutes after the https request started.
I was thinking of using thread that I created just before I initiate https request. I am not sure if this the correct way to approach this. Maybe there is not need to use threads at all. I am using ruby 1.8.7 (2010-08-16 patchlevel 302) [i386-mingw32]. Also I don't now if I can 'kill' the thread on successful finish of https request.
uri = URI.parse(url)
start = Time.new
http_read_timeout=60*10
connection = Net::HTTP.new(uri.host, 443)
connection.use_ssl = true
begin
response = connection.start() do |http|
http.open_timeout = 50
http.read_timeout = http_read_timeout
http.request_get(uri.request_uri)
# here I need to place a code that is triggered
# in case of custom timeout is reached
end
rescue Timeout::Error
# "Connection failed
time_out_message ="security time out - after #{http_read_timeout} sec"
return time_out_message
end
puts "finished"
The basic structure could be like this:
seconds_timer = MyDelay
counter = 0
test_thread = Thread.new do
run_http_php_test
end
while test_thread.alive?
counter += 1
if counter > seconds_timer
handle_custom_timeout_somehow
# if you want to halt run_http_php_test:
test_thread.kill if test_thread.alive?
# otherwise:
break
end
sleep 1
end
# the below doesn't apply if you kill the run_http_php_test thread
test_thread.join if test_thread.alive?
...but of course you could change that sleep 1 to whatever polling interval you like. Polling is nicer than just forcing your original thread to sleep, because the code will finish faster if run_http_php_test is done before you hit your custom timeout value.
Most or all of your code above can be in the run_http_php_test method, or inserted directly...whichever you'd prefer.
ruby 1.9.3 implements timeout module that has a timeout function. you can see it here. if you scroll down you can click show source and see the definition for timeout method. you can copy it if you dont want to upgrade to ruby 1.9.3 (I recommend upgrade since 1.8.7 is very slow compared to 1.9.3)