Catching Mechanize 404 => Net::HTTPNotFound - ruby

I wrote simple function which handles fetching of the url:
def tender_page_get url, agent
sleep(rand(6)+2)
begin
return agent.get(url).parser
rescue Errno::ETIMEDOUT, Timeout::Error, Net::HTTPNotFound
EYE.debug "--winter sleep #{url}"
puts "-x-#{url}"
sleep(300)
tender_page_get url, agent
rescue => e
puts "-x-#{url}"
EYE.debug "--unknown exception"
EYE.debug "#{url} #{e.inspect}"
end
end
The problem is, even though I am catching Net::HTTPNotFound in my first rescue block, I still see in my log records like:
--unknown exception
{url} 404 => Net::HTTPNotFound
which means that this exception was caught by the second rescue block. What could be the reason for that?

Mechanize raises a Mechanize::ResponseCodeError for a 404 and not a Net::HTTPNotFound. The to_s on Mechanize::ResponseCodeError looks like this:
def to_s
"#{response_code} => #{Net::HTTPResponse::CODE_TO_OBJ[response_code]}"
end
This returns '404 => Net::HTTPNotFound' which makes it look like this is the exception being raised.

Related

My Rubocop doesn't like => e in Ruby error handling. Isn't => e standard?

Rubocop doesn't seem to like how I am handling my error. What should I do?
Lint/UselessAssignment: Useless assignment to variable - e.
rescue *exceptions_list => e
It is for the piece of code below:
def get_request(url_args = {})
http_connection(url_builder(url_args[:url], url_args[:page]))
rescue *exceptions_list => e
raise "#{e.message}"
end
The *exceptions_list that you see there is defined in a private method:
private
def exceptions_list
[
Net::HTTPBadResponse,
Net::HTTPHeaderSyntaxError,
Net::ProtocolError,
Errno::ECONNRESET,
Errno::EINVAL,
Timeout::Error,
EOFError,
SocketError
]
end
To avoid the rescue line being too long.
Question:
Having => e is pretty standard for error handling no? What should I do?
Thank you very much in advance! =)
Your example does not give Lint/UselessAssignment from rubocop, not at least with version 0.55.0
The UselessAssignment usually comes from something like this:
def do_things
..
rescue *exception_list => e # Useless assignment, e is never used in the block below.
puts "it failed :("
end
To fix this, you can remove the assignment if you're not using the raised exception for anything:
def do_things
..
rescue *exception_list
puts "it failed and i don't care why :D"
end

How can I handle Connection timed out error in ruby Net/HTTP?

I try this code, but when the proxy is too slow I get connection timed out error. How can I solve this? I tried Exception handling but doesn't work. Can anybody help?
Net::HTTP.new('example.com', nil, '140.113.182.81', '808').start { |http|
begin
response = http.request
p response
rescue Timeout::Error
p 'timed out'
end
}
The Timeout::Error is raised by the Net::HTTP.connect method that is executed by start, not by request.
It means that in order to rescue the timeout, the whole Net::HTTP call should be inside the begin block.
begin
Net::HTTP.new('example.com', nil, '140.113.182.81', '808').start do |http|
response = http.request
p response
end
rescue Timeout::Error
p 'timed out'
end

Rescue ERRNO::EADDRINUSE in UDPSocket#bind

I'm trying to rescue the exception that ruby raises when you try to use the same address twice in a bind statement. The documentation is not very helpful.
Here's what I want:
require 'socket'
s = UDPSocket.new(Socket::AF_INET)
begin
s.bind address,port
rescue #Address_in_use => e
#code
end
rescue without an explicit Exception class only rescues StandardError and its subclasses. You should do the following:
rescue Errno::EADDRINUSE => ex
#code
end

How to catch all exceptions as soon as they occur by just one rescue statement

I know how to catch the exceptions but what we do is to put "rescue" after a suspicious section of a code. what if you had a lot functions sending a query to mysql through mysql2 gem and you want to catch their exceptions. One thing you can do is to put a "rescue" statement in each of them. but i want to do that just by one rescue statement. So I put a "rescue" in end of code and put all of code in a "begin" and "end" but it didn't work.
Here is my code and as you see there is a problem in mysql query and just because of "rescue" being end of file, it doesn't catch the exception but when I put it after that query it works.
require 'mysql2'
require 'colored'
begin
def log(string)
p "["+string.cyan+"]"
end
def err
p "["+"FAIL".red+"]"
end
def done
p "["+"DONE".red+"]"
end
class SqlClient
def initialize()
log "SqlClient/initialize"
puts "Host: \n"
#host = gets.strip
puts "User: \n"
#user = gets.strip
puts "Pass: \n"
#pass = gets.strip
#client = Mysql2::Client.new(host: #host , username: #user , password: #pass)
end
def list_databases()
puts "We are listing your databases(not just projects) \n \n \n "
#client.query("ELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA").each do |row|
p row["SCHEMA_NAME"]
end
puts "\n \n \n"
end
end
rescue Mysql2::Error
err
abort
end
`query': You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'ELECT SCHEMA_NAME FROM
INFORMATION_SCHEMA.SCHEMATA' at line 1 (Mysql2::Error)
I'm not looking for something like:
begin
# my code
rescue # this line is right after the code which is going to have problem and we catch it.
end
I'm looking for something like this:
begin
# first method
# second method
# thrid method
# rest of code and etc ...
# now this is end of file:
rescue
end
but as you saw in my code, it didn't work.
UPDATE: I found a similar question here and it seems there will be no answer :| maybe this is a sort of ruby Weakness.
if you want to see ANY error just use e for example
begin
# your call to a method of Mysql2 gem. for example:
client = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
puts e.message
puts e.backtrace.inspect
end
In order to catch every exception you'd need to wrap each method call with a begin rescue end. When an exception is raised it bails out of the execution so it wouldn't hit the next methods.
To catch all errors I guess I'd do something like this. Keep in mind, this is ugly and I'd recommend for you NOT to do this, but... if you want to try, maybe try something like this:
all_errors = []
# first method you call
begin
# some error might happen here
first_response = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
all_errors << e
end
# second method you call
begin
# some error might happen here
second_response = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
all_errors << e
end
puts all_errors.inspect
After a quick search I've found: (http://coderrr.wordpress.com/2008/11/07/the-simple-way-to-print-exceptions-in-ruby/)
# catch all exceptions (anything that derives from Exception)
begin
...
rescue Exception
puts $!, $#
end
You could use an at_exit handler, which has access to the last exception in $!
like
at_exit {
puts "the exception that killed us is", $!
}
If you want to catch Exceptions "as soon as they occur" (not after they're caught) you could use ruby's "debug mode" (which outputs messages when they occur to the console) or ruby-debug see Is there any way to start the Ruby debugger on exception?
Just wrap all your code in:
begin
#yourcode
#as much as you want
rescue
end
Nobody seemed to notice it but using rescue without a class will catch all StandardError and there are so much more.
If you want to catch ALL exceptions you need to do
begin
# your code where you call SqlClient.new etc
rescue Exception => e
puts "error raised"
puts [e, e.backtrace].flatten.join("\n")
end
List of all error classes:
Exception
NoMemoryError
ScriptError
LoadError
NotImplementedError
SyntaxError
SignalException
Interrupt
StandardError
ArgumentError
IOError
EOFError
IndexError
LocalJumpError
NameError
NoMethodError
RangeError
FloatDomainError
RegexpError
RuntimeError
SecurityError
SystemCallError
SystemStackError
ThreadError
TypeError
ZeroDivisionError
SystemExit
fatal
have you tried adding an at_exit method in your class? This would allow you to do something when ruby is exiting. like in this article.
Ruby at_exit
or
From Ruby 2.0 API Docs
However beware of cleverly rescuing from an exception!
You'll start pulling your hair out down the road (or another dev will) when you try to figure out why your code isn't failing when it should be failing. I prefer to fail massively with a bright shiny sign saying the code failed here! hehe.
Good luck!

How to test that method should raise different types of exceptions?

I have the following method:
def call_http_service(url, url_params)
begin
conn = create_connection(url)
resp = get_response(conn, url_params)
raise_if_http_status_error(resp)
xml_resp = parse_xml(resp)
raise_if_client_status_error(xml_resp)
return xml_resp
rescue ClientError => e
raise ClientError, "Error interacting with feed at #{url}: #{e.message}"
rescue Faraday::Error::ClientError => e
raise ClientError, "Error interacting with feed at #{url}: #{e.message}"
rescue Nokogiri::XML::SyntaxError => e
raise ClientParseError, "Error parsing response from #{url}: #{e.message}"
rescue => e
raise e
end
end
Based on my limited understanding of RSpec, it looks like the way to test that these different types of Exceptions are raised is to use message expectations. Is that how you would approach it?
It would look something like this:
it "raises ClientError when the HTTP request raises ClientError"
# stub the http request here to raise the error
expect do
subject.call_http_service 'http://example.com'
end.to raise_error(ClientError)
end
Note: Rescuing and reraising a different error is code smell.

Resources