Class: Intercom::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/intercom/request.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, net_http_method) ⇒ Request

Returns a new instance of Request.



8
9
10
11
# File 'lib/intercom/request.rb', line 8

def initialize(path, net_http_method)
  self.path = path
  self.net_http_method = net_http_method
end

Instance Attribute Details

#net_http_methodObject

Returns the value of attribute net_http_method.



6
7
8
# File 'lib/intercom/request.rb', line 6

def net_http_method
  @net_http_method
end

#pathObject

Returns the value of attribute path.



6
7
8
# File 'lib/intercom/request.rb', line 6

def path
  @path
end

Class Method Details

.append_query_string_to_url(url, params) ⇒ Object



160
161
162
163
164
# File 'lib/intercom/request.rb', line 160

def self.append_query_string_to_url(url, params)
  return url if params.empty?
  query_string = params.map { |k, v| "#{k.to_s}=#{CGI::escape(v.to_s)}" }.join('&')
  url + "?#{query_string}"
end

.default_headersObject



41
42
43
# File 'lib/intercom/request.rb', line 41

def self.default_headers
  {'Accept-Encoding' => 'gzip, deflate', 'Accept' => 'application/vnd.intercom.3+json', 'User-Agent' => "Intercom-Ruby/#{Intercom::VERSION}"}
end

.delete(path, params) ⇒ Object



26
27
28
# File 'lib/intercom/request.rb', line 26

def self.delete(path, params)
  new(path, method_with_body(Net::HTTP::Delete, path, params))
end

.get(path, params) ⇒ Object



18
19
20
# File 'lib/intercom/request.rb', line 18

def self.get(path, params)
  new(path, Net::HTTP::Get.new(append_query_string_to_url(path, params), default_headers))
end

.method_with_body(http_method, path, params) ⇒ Object



34
35
36
37
38
39
# File 'lib/intercom/request.rb', line 34

def self.method_with_body(http_method, path, params)
  request = http_method.send(:new, path, default_headers)
  request.body = params.to_json
  request["Content-Type"] = "application/json"
  request
end

.post(path, form_data) ⇒ Object



22
23
24
# File 'lib/intercom/request.rb', line 22

def self.post(path, form_data)
  new(path, method_with_body(Net::HTTP::Post, path, form_data))
end

.put(path, form_data) ⇒ Object



30
31
32
# File 'lib/intercom/request.rb', line 30

def self.put(path, form_data)
  new(path, method_with_body(Net::HTTP::Put, path, form_data))
end

Instance Method Details

#client(uri) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/intercom/request.rb', line 45

def client(uri)
  net = Net::HTTP.new(uri.host, uri.port)
  if uri.is_a?(URI::HTTPS)
    net.use_ssl = true
    net.verify_mode = OpenSSL::SSL::VERIFY_PEER
    net.ca_file = File.join(File.dirname(__FILE__), '../data/cacert.pem')
  end
  net.read_timeout = 90
  net.open_timeout = 30
  net
end

#decode(content_encoding, body) ⇒ Object



102
103
104
105
# File 'lib/intercom/request.rb', line 102

def decode(content_encoding, body)
  return body if (!body) || body.empty? || content_encoding != 'gzip'
  Zlib::GzipReader.new(StringIO.new(body)).read
end

#decode_body(response) ⇒ Object



78
79
80
# File 'lib/intercom/request.rb', line 78

def decode_body(response)
  decode(response['content-encoding'], response.body)
end

#execute(target_base_url = nil) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/intercom/request.rb', line 57

def execute(target_base_url=nil)
  base_uri = URI.parse(target_base_url)
  set_common_headers(net_http_method, base_uri)
  begin
    client(base_uri).start do |http|
      begin
        response = http.request(net_http_method)
        set_rate_limit_details(response)
        decoded_body = decode_body(response)
        parsed_body = parse_body(decoded_body, response)
        raise_errors_on_failure(response)
        parsed_body
      rescue Timeout::Error
        raise Intercom::ServiceUnavailableError.new('Service Unavailable [request timed out]')
      end
    end
  rescue Timeout::Error
    raise Intercom::ServiceConnectionError.new('Failed to connect to service [connection attempt timed out]')
  end
end

#message_for_unexpected_error_with_type(error_details, parsed_http_code) ⇒ Object



152
153
154
# File 'lib/intercom/request.rb', line 152

def message_for_unexpected_error_with_type(error_details, parsed_http_code)
  "The error of type '#{error_details['type']}' is not recognized. It occurred with the message: #{error_details['message']} and http_code: '#{parsed_http_code}'. Please contact Intercom with these details."
end

#message_for_unexpected_error_without_type(error_details, parsed_http_code) ⇒ Object



156
157
158
# File 'lib/intercom/request.rb', line 156

def message_for_unexpected_error_without_type(error_details, parsed_http_code)
  "An unexpected error occured. It occurred with the message: #{error_details['message']} and http_code: '#{parsed_http_code}'. Please contact Intercom with these details."
end

#parse_body(decoded_body, response) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/intercom/request.rb', line 82

def parse_body(decoded_body, response)
  parsed_body = nil
  return parsed_body if decoded_body.nil? || decoded_body.strip.empty?
  begin
    parsed_body = JSON.parse(decoded_body)
  rescue JSON::ParserError => _
    raise_errors_on_failure(response)
  end
  raise_application_errors_on_failure(parsed_body, response.code.to_i) if parsed_body['type'] == 'error.list'
  parsed_body
end

#raise_application_errors_on_failure(error_list_details, http_code) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/intercom/request.rb', line 123

def raise_application_errors_on_failure(error_list_details, http_code)
  # Currently, we don't support multiple errors
  error_details = error_list_details['errors'].first
  error_code = error_details['type'] || error_details['code']
  parsed_http_code = (http_code > 0 ? http_code : nil)
  error_context = {
    :http_code => parsed_http_code,
    :application_error_code => error_code
  }
  case error_code
  when 'unauthorized', 'forbidden'
    raise Intercom::AuthenticationError.new(error_details['message'], error_context)
  when "bad_request", "missing_parameter", 'parameter_invalid'
    raise Intercom::BadRequestError.new(error_details['message'], error_context)
  when "not_found"
    raise Intercom::ResourceNotFound.new(error_details['message'], error_context)
  when "rate_limit_exceeded"
    raise Intercom::RateLimitExceeded.new(error_details['message'], error_context)
  when 'service_unavailable'
    raise Intercom::ServiceUnavailableError.new(error_details['message'], error_context)
  when 'conflict'
    raise Intercom::MultipleMatchingUsersError.new(error_details['message'], error_context)
  when nil, ''
    raise Intercom::UnexpectedError.new(message_for_unexpected_error_without_type(error_details, parsed_http_code), error_context)
  else
    raise Intercom::UnexpectedError.new(message_for_unexpected_error_with_type(error_details, parsed_http_code), error_context)
  end
end

#raise_errors_on_failure(res) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/intercom/request.rb', line 107

def raise_errors_on_failure(res)
  if res.code.to_i.eql?(404)
    raise Intercom::ResourceNotFound.new('Resource Not Found')
  elsif res.code.to_i.eql?(401)
    raise Intercom::AuthenticationError.new('Unauthorized')
  elsif res.code.to_i.eql?(403)
    raise Intercom::AuthenticationError.new('Forbidden')
  elsif res.code.to_i.eql?(500)
    raise Intercom::ServerError.new('Server Error')
  elsif res.code.to_i.eql?(502)
    raise Intercom::BadGatewayError.new('Bad Gateway Error')
  elsif res.code.to_i.eql?(503)
    raise Intercom::ServiceUnavailableError.new('Service Unavailable')
  end
end

#set_common_headers(method, base_uri) ⇒ Object



13
14
15
16
# File 'lib/intercom/request.rb', line 13

def set_common_headers(method, base_uri)
  method.basic_auth(CGI.unescape(base_uri.user), CGI.unescape(base_uri.password))
  method.add_field('AcceptEncoding', 'gzip, deflate')
end

#set_rate_limit_details(response) ⇒ Object



94
95
96
97
98
99
100
# File 'lib/intercom/request.rb', line 94

def set_rate_limit_details(response)
  rate_limit_details = {}
  rate_limit_details[:limit] = response['X-RateLimit-Limit'].to_i if response['X-RateLimit-Limit']
  rate_limit_details[:remaining] = response['X-RateLimit-Remaining'].to_i if response['X-RateLimit-Remaining']
  rate_limit_details[:reset_at] = Time.at(response['X-RateLimit-Reset'].to_i) if response['X-RateLimit-Reset']
  Intercom.rate_limit_details = rate_limit_details
end