lib/amee/connection.rb in amee-2.5.1 vs lib/amee/connection.rb in amee-2.6.0

- old
+ new

@@ -16,10 +16,11 @@ @ssl = (options[:ssl] == false) ? false : true @port = @ssl ? 443 : 80 @auth_token = nil @format = options[:format] || (defined?(JSON) ? :json : :xml) @amee_source = options[:amee_source] + @retries = options[:retries] || 0 if !valid? raise "You must supply connection details - server, username and password are all required!" end # Handle old option if options[:enable_caching] @@ -50,26 +51,27 @@ @http.ca_file = RootCA @http.verify_mode = OpenSSL::SSL::VERIFY_PEER @http.verify_depth = 5 end end - @http.read_timeout = 60 + self.timeout = options[:timeout] || 60 @http.set_debug_output($stdout) if options[:enable_debug] @debug = options[:enable_debug] end attr_reader :format attr_reader :server attr_reader :username attr_reader :password + attr_reader :retries def timeout @http.read_timeout end def timeout=(t) - @http.read_timeout = t + @http.open_timeout = @http.read_timeout = t end def version authenticate if @version.nil? @version @@ -215,24 +217,26 @@ return false when '400' if response.body.include? "would have resulted in a duplicate resource being created" raise AMEE::DuplicateResource.new("The specified resource already exists. This is most often caused by creating an item that overlaps another in time.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}") else - raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}") + raise AMEE::BadRequest.new("Bad request. This is probably due to malformed input data.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}") end - else - raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}") end + raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}") end def do_request(request, format = @format) # Open HTTP connection @http.start - # Do request begin + # Set auth token in cookie (and header just in case someone's stripping cookies) + request['Cookie'] = "authToken=#{@auth_token}" + request['authToken'] = @auth_token + # Do request timethen=Time.now - response = send_request(request, format) + response = send_request(@http, request, format) Logger.log.debug("Requesting #{request.class} at #{request.path} with #{request.body} in format #{format}, taking #{(Time.now-timethen)*1000} miliseconds") end while !response_ok?(response, request) # Return response return response rescue SocketError @@ -240,19 +244,31 @@ ensure # Close HTTP connection @http.finish if @http.started? end - def send_request(request, format = @format) - # Set auth token in cookie (and header just in case someone's stripping cookies) - request['Cookie'] = "authToken=#{@auth_token}" - request['authToken'] = @auth_token + def send_request(connection, request, format = @format) # Set accept header request['Accept'] = content_type(format) # Set AMEE source header if set request['X-AMEE-Source'] = @amee_source if @amee_source # Do the business - response = @http.request(request) + retries = [1] * @retries + begin + response = connection.request(request) + # 500-series errors fail early + if ['502', '503', '504'].include? response.code + raise AMEE::ConnectionFailed.new("A connection error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method} #{request.path}") + end + rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, + Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, AMEE::ConnectionFailed => e + if delay = retries.shift + sleep delay + retry + else + raise + end + end # Done response end def cache(path, &block)