Class: Revactor::HttpResponse

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

Overview

An object representing a response to an HTTP request

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, response_header) ⇒ HttpResponse

Returns a new instance of HttpResponse.



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/revactor/http_client.rb', line 240

def initialize(client, response_header)
  @client = client
  
  # Copy these out of the original Rev response object, then discard it
  @status = response_header.status
  @reason = response_header.http_reason
  @version = response_header.http_version
  @content_length = response_header.content_length
  @chunked_encoding = response_header.chunked_encoding?
  
  # Convert header fields hash from LIKE_THIS to like-this
  @headers = response_header.inject({}) do |h, (k, v)| 
    h[k.split('_').map(&:downcase).join('-')] = v; h
  end
  
  # Extract Transfer-Encoding if available
  @transfer_encoding = @headers.delete('transfer-encoding')
  
  # Extract Content-Type if available
  @content_type = @headers.delete('content-type')
  
  # Extract Content-Encoding if available
  @content_encoding = @headers.delete('content-encoding') || 'identity'
end

Instance Attribute Details

#content_encodingObject (readonly)

The encoding of the content. Gzip encoding will be processed automatically



278
279
280
# File 'lib/revactor/http_client.rb', line 278

def content_encoding
  @content_encoding
end

#content_lengthObject (readonly)

The content length as an integer, or nil if the length is unspecified or the response is using chunked transfer encoding



285
286
287
# File 'lib/revactor/http_client.rb', line 285

def content_length
  @content_length
end

#content_typeObject (readonly)

The MIME type of the response’s content



281
282
283
# File 'lib/revactor/http_client.rb', line 281

def content_type
  @content_type
end

#headersObject (readonly)

Access to the raw header fields from the request



288
289
290
# File 'lib/revactor/http_client.rb', line 288

def headers
  @headers
end

#reasonObject (readonly)

The reason returned in the http response (e.g “OK”, “File not found”, etc.)



269
270
271
# File 'lib/revactor/http_client.rb', line 269

def reason
  @reason
end

#statusObject (readonly)

The response status as an integer (e.g. 200)



266
267
268
# File 'lib/revactor/http_client.rb', line 266

def status
  @status
end

#transfer_encodingObject (readonly)

The encoding of the transfer



275
276
277
# File 'lib/revactor/http_client.rb', line 275

def transfer_encoding
  @transfer_encoding
end

#versionObject (readonly)

The HTTP version returned (e.g. “HTTP/1.1”)



272
273
274
# File 'lib/revactor/http_client.rb', line 272

def version
  @version
end

Instance Method Details

#body(maxlength = nil) ⇒ Object

Consume the entire response body and return it as a string. The body is stored for subsequent access. A maximum body length may optionally be specified



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/revactor/http_client.rb', line 326

def body(maxlength = nil)
  return @body if @body
  @body = ""
  
  begin
    while (data = read_body)
      @body << data
      
      if maxlength and @body.size > maxlength
        raise HttpClientError, "overlength body"
      end
    end
  rescue EOFError => ex
    # If we didn't get a Content-Length and encoding isn't chunked
    # we have to depend on the socket closing to detect end-of-body
    # Otherwise the EOFError was unexpected and should be raised
    unless (content_length.nil? or content_length.zero?) and not chunked_encoding?
      raise ex 
    end
  end
  
  if content_length and body.size != content_length
    raise HttpClientError, "body size does not match Content-Length (#{body.size} of #{content_length})"
  end
  
  @body
end

#chunked_encoding?Boolean

Is the request encoding chunked?

Returns:

  • (Boolean)


291
# File 'lib/revactor/http_client.rb', line 291

def chunked_encoding?; @chunked_encoding; end

#closeObject

Explicitly close the connection



355
356
357
358
359
360
# File 'lib/revactor/http_client.rb', line 355

def close
  return if @client.closed?
  @finished = true
  @client.controller = Actor.current
  @client.close      
end

#read_bodyObject

Incrementally read the response body



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/revactor/http_client.rb', line 294

def read_body
  @client.controller = Actor.current
  @client.enable if @client.attached? and not @client.enabled?
  
  Actor.receive do |filter|
    filter.when(T[:http, @client]) do |_, _, data|
      return data
    end
    
    filter.when(T[:http_request_complete, @client]) do
      return nil
    end
    
    filter.when(T[:http_error, @client]) do |_, _, reason|
      raise HttpClientError, reason
    end
    
    filter.when(T[:http_closed, @client]) do
      raise EOFError, "connection closed unexpectedly"
    end

    filter.after(HttpClient::READ_TIMEOUT) do
      @finished = true
      @client.close unless @client.closed?          
      raise HttpClientError, "read timed out"
    end
  end
end