Class: Gitlab::HTTP

Inherits:
Object
  • Object
show all
Includes:
HTTParty
Defined in:
lib/gitlab/http.rb

Direct Known Subclasses

Atlassian::JiraConnect::Client

Constant Summary collapse

BlockedUrlError =
Class.new(StandardError)
RedirectionTooDeep =
Class.new(StandardError)
ReadTotalTimeout =
Class.new(Net::ReadTimeout)
HeaderReadTimeout =
Class.new(Net::ReadTimeout)
HTTP_TIMEOUT_ERRORS =
[
  Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout, Gitlab::HTTP::ReadTotalTimeout
].freeze
HTTP_ERRORS =
HTTP_TIMEOUT_ERRORS + [
  EOFError, SocketError, OpenSSL::SSL::SSLError, OpenSSL::OpenSSLError,
  Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH,
  Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep
].freeze
DEFAULT_TIMEOUT_OPTIONS =
{
  open_timeout: 10,
  read_timeout: 20,
  write_timeout: 30
}.freeze
DEFAULT_READ_TOTAL_TIMEOUT =
30.seconds

Class Method Summary collapse

Class Method Details

.httparty_perform_requestObject


33
# File 'lib/gitlab/http.rb', line 33

alias_method :httparty_perform_request, :perform_request

.perform_request(http_method, path, options, &block) ⇒ Object


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
74
75
76
77
78
79
80
81
# File 'lib/gitlab/http.rb', line 38

def self.perform_request(http_method, path, options, &block)
  log_info = options.delete(:extra_log_info)
  options_with_timeouts =
    if !options.has_key?(:timeout)
      options.with_defaults(DEFAULT_TIMEOUT_OPTIONS)
    else
      options
    end

  options[:skip_read_total_timeout] = true if options[:skip_read_total_timeout].nil? && options[:stream_body]

  if options[:skip_read_total_timeout]
    return httparty_perform_request(http_method, path, options_with_timeouts, &block)
  end

  start_time = nil
  read_total_timeout = options.fetch(:timeout, DEFAULT_READ_TOTAL_TIMEOUT)
  tracked_timeout_error = false

  httparty_perform_request(http_method, path, options_with_timeouts) do |fragment|
    start_time ||= Gitlab::Metrics::System.monotonic_time
    elapsed = Gitlab::Metrics::System.monotonic_time - start_time

    if elapsed > read_total_timeout
      error = ReadTotalTimeout.new("Request timed out after #{elapsed} seconds")

      raise error if options[:use_read_total_timeout]

      unless tracked_timeout_error
        Gitlab::ErrorTracking.track_exception(error)
        tracked_timeout_error = true
      end
    end

    block.call fragment if block
  end
rescue HTTParty::RedirectionTooDeep
  raise RedirectionTooDeep
rescue *HTTP_ERRORS => e
  extra_info = log_info || {}
  extra_info = log_info.call(e, path, options) if log_info.respond_to?(:call)
  Gitlab::ErrorTracking.log_exception(e, extra_info)
  raise e
end

.try_get(path, options = {}, &block) ⇒ Object


83
84
85
86
87
# File 'lib/gitlab/http.rb', line 83

def self.try_get(path, options = {}, &block)
  self.get(path, options, &block)
rescue *HTTP_ERRORS
  nil
end