Class: WebMock::HttpLibAdapters::ExconAdapter

Inherits:
WebMock::HttpLibAdapter show all
Defined in:
lib/webmock/http_lib_adapters/excon_adapter.rb

Constant Summary collapse

PARAMS_TO_DELETE =
[:expects, :idempotent,
:instrumentor_name, :instrumentor,
:response_block,
:__construction_args, :stack,
:connection, :response]

Class Method Summary collapse

Methods inherited from WebMock::HttpLibAdapter

adapter_for

Class Method Details

.add_excon_stubObject



37
38
39
40
41
42
43
44
45
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 37

def self.add_excon_stub
  if not @stub
    @original_excon_mock_default = ::Excon.defaults[:mock]
    ::Excon.defaults[:mock] = true
    @stub = ::Excon.stub({}) do |params|
      self.handle_request(params)
    end
  end
end

.body_from(params) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 120

def self.body_from(params)
  body = params[:body]
  return body unless body.respond_to?(:read)

  contents = body.read
  body.rewind if body.respond_to?(:rewind)
  contents
end

.build_request(params) ⇒ Object



110
111
112
113
114
115
116
117
118
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 110

def self.build_request(params)
  params = params.dup
  params.delete(:user)
  params.delete(:password)
  method  = (params.delete(:method) || :get).to_s.downcase.to_sym
  params[:query] = to_query(params[:query]) if params[:query].is_a?(Hash)
  uri = Addressable::URI.new(params).to_s
  WebMock::RequestSignature.new method, uri, body: body_from(params), headers: params[:headers]
end

.connection_params_from(hash) ⇒ Object



81
82
83
84
85
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 81

def self.connection_params_from(hash)
  hash = hash.dup
  PARAMS_TO_DELETE.each { |key| hash.delete(key) }
  hash
end

.disable!Object



33
34
35
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 33

def self.disable!
  self.remove_excon_stub
end

.enable!Object



29
30
31
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 29

def self.enable!
  self.add_excon_stub
end

.handle_request(params) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 54

def self.handle_request(params)
  mock_request  = self.build_request params.dup
  WebMock::RequestRegistry.instance.requested_signatures.put(mock_request)

  if mock_response = WebMock::StubRegistry.instance.response_for_request(mock_request)
    self.perform_callbacks(mock_request, mock_response, real_request: false)
    response = self.real_response(mock_response)
    response
  elsif WebMock.net_connect_allowed?(mock_request.uri)
    conn = new_excon_connection(params)
    real_response = conn.request(request_params_from(params.merge(mock: false)))

    ExconAdapter.perform_callbacks(mock_request, ExconAdapter.mock_response(real_response), real_request: true)

    real_response.data
  else
    raise WebMock::NetConnectNotAllowedError.new(mock_request)
  end
end

.mock_response(real) ⇒ Object



140
141
142
143
144
145
146
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 140

def self.mock_response(real)
  mock = WebMock::Response.new
  mock.status  = [real.status, real.reason_phrase]
  mock.headers = real.headers
  mock.body    = real.body.dup
  mock
end

.new_excon_connection(params) ⇒ Object



74
75
76
77
78
79
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 74

def self.new_excon_connection(params)
  # Ensure the connection is constructed with the exact same args
  # that the orginal connection was constructed with.
  args = params.fetch(:__construction_args)
  ::Excon::Connection.new(connection_params_from args.merge(mock: false))
end

.perform_callbacks(request, response, options = {}) ⇒ Object



148
149
150
151
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 148

def self.perform_callbacks(request, response, options = {})
  return unless WebMock::CallbackRegistry.any_callbacks?
  WebMock::CallbackRegistry.invoke_callbacks(options.merge(lib: :excon), request, response)
end

.real_response(mock) ⇒ Object

Raises:

  • (Excon::Errors::Timeout)


129
130
131
132
133
134
135
136
137
138
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 129

def self.real_response(mock)
  raise Excon::Errors::Timeout if mock.should_timeout
  mock.raise_error_if_any
  {
    body: mock.body,
    status: mock.status[0].to_i,
    reason_phrase: mock.status[1],
    headers: mock.headers || {}
  }
end

.remove_excon_stubObject



47
48
49
50
51
52
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 47

def self.remove_excon_stub
  ::Excon.defaults[:mock] = @original_excon_mock_default
  @original_excon_mock_default = nil
  Excon.stubs.delete(@stub)
  @stub = nil
end

.request_params_from(hash) ⇒ Object



87
88
89
90
91
92
93
94
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 87

def self.request_params_from(hash)
  hash = hash.dup
  if defined?(Excon::VALID_REQUEST_KEYS)
    hash.reject! {|key,_| !Excon::VALID_REQUEST_KEYS.include?(key) }
  end
  PARAMS_TO_DELETE.each { |key| hash.delete(key) }
  hash
end

.to_query(hash) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/webmock/http_lib_adapters/excon_adapter.rb', line 96

def self.to_query(hash)
  string = "".dup
  for key, values in hash
    if values.nil?
      string << key.to_s << '&'
    else
      for value in [*values]
        string << key.to_s << '=' << CGI.escape(value.to_s) << '&'
      end
    end
  end
  string.chop! # remove trailing '&'
end