Class: EasyPost::HttpClient

Inherits:
Object
  • Object
show all
Defined in:
lib/easypost/http_client.rb

Instance Method Summary collapse

Constructor Details

#initialize(base_url, config, custom_client_exec = nil) ⇒ HttpClient

Returns a new instance of HttpClient.



6
7
8
9
10
# File 'lib/easypost/http_client.rb', line 6

def initialize(base_url, config, custom_client_exec = nil)
  @base_url = base_url
  @config = config
  @custom_client_exec = custom_client_exec
end

Instance Method Details

#default_request_execute(method, uri, headers, open_timeout, read_timeout, body = nil) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/easypost/http_client.rb', line 97

def default_request_execute(method, uri, headers, open_timeout, read_timeout, body = nil)
  # Create the request, set the headers and body if necessary.
  request = Net::HTTP.const_get(method.capitalize).new(uri)
  headers.each { |k, v| request[k] = v }
  request.body = body if body

  begin
    # Attempt to make the request and return the response.
    Net::HTTP.start(
      uri.host,
      uri.port,
      use_ssl: true,
      read_timeout: read_timeout,
      open_timeout: open_timeout,
    ) do |http|
      http.request(request)
    end
  rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EHOSTUNREACH => e
    # Raise a timeout error if the request times out.
    raise EasyPost::Errors::TimeoutError.new(e.message)
  rescue OpenSSL::SSL::SSLError => e
    # Raise an SSL error if the request fails due to an SSL error.
    raise EasyPost::Errors::SslError.new(e.message)
  rescue StandardError => e
    # Raise an unknown HTTP error if anything else causes the request to fail to complete
    # (this is different from processing 4xx/5xx errors from the API)
    raise EasyPost::Errors::UnknownApiError.new(e.message)
  end
end

#request(method, path, headers = nil, params = nil, api_version = EasyPost::InternalUtilities::Constants::API_VERSION) ⇒ Object

Execute an HTTP request to the API.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/easypost/http_client.rb', line 13

def request(
  method,
  path,
  headers = nil,
  params = nil,
  api_version = EasyPost::InternalUtilities::Constants::API_VERSION
)
  # Remove leading slash from path.
  path = path[1..] if path[0] == '/'

  headers = @config[:headers].merge(headers || {})
  open_timeout = @config[:open_timeout]
  read_timeout = @config[:read_timeout]
  request_timestamp = Time.now
  request_uuid = SecureRandom.uuid

  uri = URI.parse("#{@base_url}/#{api_version}/#{path}")
  serialized_body = nil

  if params
    if [:get, :delete].include?(method)
      uri.query = URI.encode_www_form(params)
    elsif params
      serialized_body = JSON.dump(EasyPost::InternalUtilities.objects_to_ids(params))
    end
  end

  if EasyPost::Hooks.any_subscribers?(:request)
    request_context = EasyPost::Hooks::RequestContext.new(
      method: method,
      path: uri.to_s,
      headers: headers,
      request_body: serialized_body,
      request_timestamp: request_timestamp,
      request_uuid: request_uuid,
    )
    EasyPost::Hooks.notify(:request, request_context)
  end

  # Execute the request, return the response.

  response = if @custom_client_exec
               @custom_client_exec.call(method, uri, headers, open_timeout, read_timeout, serialized_body)
             else
               default_request_execute(method, uri, headers, open_timeout, read_timeout, serialized_body)
             end
  response_timestamp = Time.now

  if EasyPost::Hooks.any_subscribers?(:response)
    response_context = {
      http_status: nil,
      method: method,
      path: uri.to_s,
      headers: nil,
      response_body: nil,
      request_timestamp: request_timestamp,
      response_timestamp: response_timestamp,
      client_response_object: response,
      request_uuid: request_uuid,
    }

    # If using a custom HTTP client, the user will have to infer these from the raw
    # client_response_object attribute
    if response.is_a?(Net::HTTPResponse)
      response_body = begin
        JSON.parse(response.body)
      rescue JSON::ParseError
        response.body
      end
      response_context.merge!(
        {
          http_status: response.code.to_i,
          headers: response.each_header.to_h,
          response_body: response_body,
        },
      )
    end

    EasyPost::Hooks.notify(:response, EasyPost::Hooks::ResponseContext.new(**response_context))
  end

  response
end