Module: HTTPAdapter

Defined in:
lib/httpadapter.rb,
lib/httpadapter/version.rb,
lib/httpadapter/connection.rb,
lib/httpadapter/adapters/mock.rb,
lib/httpadapter/adapters/rack.rb,
lib/httpadapter/adapters/net_http.rb,
lib/httpadapter/adapters/typhoeus.rb

Overview

:nodoc:

Defined Under Namespace

Modules: MockAdapter, VERSION Classes: Connection, NetHTTPRequestAdapter, NetHTTPResponseAdapter, RackRequestAdapter, RackResponseAdapter, TyphoeusRequestAdapter, TyphoeusResponseAdapter

Class Method Summary collapse

Class Method Details

.adapt_request(request, adapter = nil) ⇒ Array

Converts an HTTP request object to a simple tuple.

Parameters:

  • request (Object, #to_ary)

    The request object to be converted. The request may either implement the #to_ary method directly or alternately, an optional adapter class may be provided. The adapter must accept the request object as a parameter and provide the #to_ary method.

Returns:

  • (Array)

    The tuple that the request was converted to.



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/httpadapter.rb', line 29

def self.adapt_request(request, adapter=nil)
  # Temporarily wrap the request if there's an adapter
  request = adapter.new(request) if adapter
  if request.respond_to?(:to_ary)
    converted_request = request.to_ary
  else
    # Can't use #to_a because some versions of Ruby define #to_a on Object
    raise TypeError,
      "Expected adapter or request to implement #to_ary."
  end
  return self.verified_request(converted_request)
end

.adapt_response(response, adapter = nil) ⇒ Array

Converts an HTTP response object to a simple tuple.

Parameters:

  • response (Object, #to_ary)

    The response object to be converted. The response may either implement the #to_ary method directly or alternately, an optional adapter class may be provided. The adapter must accept the response object as a parameter and provide the #to_ary method.

Returns:

  • (Array)

    The tuple that the reponse was converted to.



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/httpadapter.rb', line 52

def self.adapt_response(response, adapter=nil)
  # Temporarily wrap the response if there's an adapter
  response = adapter.new(response) if adapter
  if response.respond_to?(:to_ary)
    converted_response = response.to_ary
  else
    # Can't use #to_a because some versions of Ruby define #to_a on Object
    raise TypeError,
      "Expected adapter or response to implement #to_ary."
  end
  return self.verified_response(converted_response)
end

.specialize_request(request, adapter) ⇒ Array

Converts a tuple to a specific HTTP implementation’s request format.

Parameters:

  • request (Array)

    The request object to be converted. The request object must be a tuple with a length of 4. The first element must be the request method. The second element must be the URI. The URI may be relative. The third element contains the headers. It must respond to #each and iterate over the header names and values. The fourth element must be the body. It must respond to #each but may not be a String. It should emit String objects.

  • adapter (#from_ary)

    The adapter object that will convert to a tuple. It must respond to #from_ary. Typically a reference to a class is used.

Returns:

  • (Array)

    The implementation-specific request object.



81
82
83
84
85
86
87
88
89
# File 'lib/httpadapter.rb', line 81

def self.specialize_request(request, adapter)
  request = self.verified_request(request)
  if adapter.respond_to?(:from_ary)
    return adapter.from_ary(request)
  else
    raise TypeError,
      "Expected adapter to implement .from_ary."
  end
end

.specialize_response(response, adapter) ⇒ Array

Converts a tuple to a specific HTTP implementation’s response format.

Parameters:

  • response (Array)

    The response object to be converted. The response object must be a tuple with a length of 3. The first element must be the HTTP status code. The second element contains the headers. It must respond to #each and iterate over the header names and values. The third element must be the body. It must respond to #each but may not be a String. It should emit String objects. This is essentially the same format that Rack uses.

  • adapter (#from_ary)

    The adapter object that will convert to a tuple. It must respond to #from_ary. Typically a reference to a class is used.

Returns:

  • (Array)

    The implementation-specific response object.



108
109
110
111
112
113
114
115
# File 'lib/httpadapter.rb', line 108

def self.specialize_response(response, adapter)
  response = self.verified_response(response)
  if adapter.respond_to?(:from_ary)
    return adapter.from_ary(response)
  else
    raise TypeError, 'Expected adapter to implement .from_ary.'
  end
end

.transmit(request, adapter, connection = nil) ⇒ Array

Transmits a request.

Parameters:

  • request (Array)

    The request that will be sent.

  • adapter (#transmit)

    The adapter object that will perform the transmission of the HTTP request. It must respond to #transmit. Typically a reference to a class is used.

  • connection (HTTPAdapter::Connection) (defaults to: nil)

    An object representing a connection. This object represents an open HTTP connection that is used to make multiple HTTP requests.

Returns:

  • (Array)

    The response given by the server.

  • (Array)

    The implementation-specific response object.



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/httpadapter.rb', line 133

def self.transmit(request, adapter, connection=nil)
  request = self.verified_request(request)
  if connection && !connection.kind_of?(HTTPAdapter::Connection)
    raise TypeError,
      "Expected HTTPAdapter::Connection, got #{connection.class}."
  end
  if adapter.respond_to?(:transmit)
    response = adapter.transmit(request, connection)
    return self.verified_response(response)
  else
    raise TypeError, 'Expected adapter to implement .transmit.'
  end
end

.verified_request(request) ⇒ Array

Verifies a request tuple matches the specification.

Parameters:

  • request (Array)

    The request object to be verified.

Returns:

  • (Array)

    The tuple, after normalization.



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/httpadapter.rb', line 154

def self.verified_request(request)
  if !request.kind_of?(Array)
    raise TypeError, "Expected Array, got #{request.class}."
  end
  if request.size == 4
    # Verify that the request object matches the specification
    method, uri, headers, body = request
    method = method.to_str if method.respond_to?(:to_str)
    # Special-casing symbols here
    method = method.to_s if method.kind_of?(Symbol)
    if !method.kind_of?(String)
      raise TypeError,
        "Expected String, got #{method.class}."
    end
    method = method.upcase
    if uri.respond_to?(:to_str)
      uri = uri.to_str
    else
      raise TypeError, "Expected String, got #{uri.class}."
    end
    original_headers, headers = headers, []
    if original_headers.respond_to?(:each)
      original_headers.each do |header, value|
        if header.respond_to?(:to_str)
          header = header.to_str
        else
          raise TypeError, "Expected String, got #{header.class}."
        end
        if value.respond_to?(:to_str)
          value = value.to_str
        else
          raise TypeError, "Expected String, got #{value.class}."
        end
        headers << [header, value]
      end
    else
      raise TypeError, "Expected headers to respond to #each."
    end
    if body.kind_of?(String)
      raise TypeError,
        'Body must not be a String; it must respond to #each and ' +
        'emit String values.'
    end
    # Can't verify that all chunks are Strings because #each may be
    # effectively destructive.
    if !body.respond_to?(:each)
      raise TypeError, "Expected body to respond to #each."
    end
  else
    raise TypeError,
      "Expected tuple of [method, uri, headers, body]."
  end
  return [method, uri, headers, body]
end

.verified_response(response) ⇒ Array

Verifies a response tuple matches the specification.

Parameters:

  • response (Array)

    The response object to be verified.

Returns:

  • (Array)

    The tuple, after normalization.



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/httpadapter.rb', line 216

def self.verified_response(response)
  if !response.kind_of?(Array)
    raise TypeError, "Expected Array, got #{response.class}."
  end
  if response.size == 3
    # Verify that the response object matches the specification
    status, headers, body = response
    status = status.to_i if status.respond_to?(:to_i)
    if !status.kind_of?(Integer)
      raise TypeError, "Expected Integer, got #{status.class}."
    end
    original_headers, headers = headers, []
    if original_headers.respond_to?(:each)
      original_headers.each do |header, value|
        if header.respond_to?(:to_str)
          header = header.to_str
        else
          raise TypeError, "Expected String, got #{header.class}."
        end
        if value.respond_to?(:to_str)
          value = value.to_str
        else
          raise TypeError, "Expected String, got #{value.class}."
        end
        headers << [header, value]
      end
    else
      raise TypeError, "Expected headers to respond to #each."
    end
    if body.kind_of?(String)
      raise TypeError,
        'Body must not be a String; it must respond to #each and ' +
        'emit String values.'
    end
    # Can't verify that all chunks are Strings because #each may be
    # effectively destructive.
    if !body.respond_to?(:each)
      raise TypeError, "Expected body to respond to #each."
    end
  else
    raise TypeError,
      "Expected tuple of [status, headers, body]."
  end
  return [status, headers, body]
end