Class: RaptorIO::Protocol::HTTP::Response

Inherits:
Message
  • Object
show all
Defined in:
lib/raptor-io/protocol/http/response.rb

Overview

HTTP Response.

Author:

Instance Attribute Summary collapse

Attributes inherited from Message

#body, #headers, #version

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Message

#http_1_0?, #http_1_1?, #keep_alive?

Constructor Details

#initialize(options = {}) ⇒ Response

Note:

This class’ options are in addition to Message#initialize.

Returns a new instance of Response.

Parameters:

  • options (Hash) (defaults to: {})

    Request options.

Options Hash (options):

  • :code (Integer)

    HTTP response status code.

  • :request (Request)

    HTTP request that triggered this response.

See Also:



39
40
41
42
43
44
45
46
47
# File 'lib/raptor-io/protocol/http/response.rb', line 39

def initialize( options = {} )
  super( options )

  @body = @body.force_utf8 if text?
  @code ||= 0

  # Holds the redirection responses that eventually led to this one.
  @redirections ||= []
end

Instance Attribute Details

#codeInteger

Returns HTTP response status code.

Returns:

  • (Integer)

    HTTP response status code.



15
16
17
# File 'lib/raptor-io/protocol/http/response.rb', line 15

def code
  @code
end

#errorException

Returns Exception representing the error that occurred.

Returns:

  • (Exception)

    Exception representing the error that occurred.



28
29
30
# File 'lib/raptor-io/protocol/http/response.rb', line 28

def error
  @error
end

#messageString

Returns HTTP response status message.

Returns:

  • (String)

    HTTP response status message.



18
19
20
# File 'lib/raptor-io/protocol/http/response.rb', line 18

def message
  @message
end

#redirectionsArray<Response>

Returns Automatically followed redirections that eventually led to this response.

Returns:

  • (Array<Response>)

    Automatically followed redirections that eventually led to this response.



25
26
27
# File 'lib/raptor-io/protocol/http/response.rb', line 25

def redirections
  @redirections
end

#requestRequest



21
22
23
# File 'lib/raptor-io/protocol/http/response.rb', line 21

def request
  @request
end

Class Method Details

.inflate(str) ⇒ String

Returns Inflated ‘str`.

Parameters:

  • str (String)

    Inflates ‘str`.

Returns:

  • (String)

    Inflated ‘str`.



145
146
147
148
149
150
# File 'lib/raptor-io/protocol/http/response.rb', line 145

def self.inflate( str )
  z = Zlib::Inflate.new
  s = z.inflate( str )
  z.close
  s
end

.parse(response) ⇒ Response

Parameters:

  • response (String)

    HTTP response.

Returns:



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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/raptor-io/protocol/http/response.rb', line 97

def self.parse( response )
  options ||= {}

  # FIXME: The existence of this extra newline at the beginning of a
  # response suggests a bug somewhere else in the response parsing
  # code.
  response = response.gsub(/\A\r\n/, '')

  headers_string, options[:body] = response.split( HEADER_SEPARATOR_PATTERN, 2 )
  request_line   = headers_string.to_s.lines.first.to_s.chomp

  options[:version], options[:code], options[:message] =
      request_line.scan( /HTTP\/([\d.]+)\s+(\d+)\s*(.*)\s*$/ ).flatten

  options.delete(:message) if options[:message].to_s.empty?

  options[:code] = options[:code].to_i

  if !headers_string.to_s.empty?
    options[:headers] =
        Headers.parse( headers_string.split( CRLF_PATTERN )[1..-1].join( "\r\n" ) )
  else
    options[:headers] = Headers.new
  end

  if !options[:body].to_s.empty?

    # If any encoding has been applied to the body, remove all evidence of it
    # and adjust the content-length accordingly.

    case options[:headers]['content-encoding'].to_s.downcase
      when 'gzip', 'x-gzip'
        options[:body] = unzip( options[:body] )
      when 'deflate', 'compress', 'x-compress'
        options[:body] = inflate( options[:body] )
    end

    if options[:headers].delete( 'content-encoding' ) ||
        options[:headers].delete( 'transfer-encoding' )
      options[:headers]['content-length'] = options[:body].size
    end
  end

  new( options )
end

.unzip(str) ⇒ String

Returns Unziped ‘str`.

Parameters:

  • str (String)

    Unzips ‘str`.

Returns:

  • (String)

    Unziped ‘str`.



154
155
156
157
158
159
160
161
# File 'lib/raptor-io/protocol/http/response.rb', line 154

def self.unzip( str )
  s = ''
  s.force_encoding( 'ASCII-8BIT' ) if s.respond_to?( :encoding )
  gz = Zlib::GzipReader.new( StringIO.new( str, 'rb' ) )
  s << gz.read
  gz.close
  s
end

Instance Method Details

#modified?Boolean

Note:

Depends on the response code.

Returns ‘true` if the remote resource has been modified since the date given in the `If-Modified-Since` request header field, `false` otherwise.

Returns:

  • (Boolean)

    ‘true` if the remote resource has been modified since the date given in the `If-Modified-Since` request header field, `false` otherwise.



61
62
63
# File 'lib/raptor-io/protocol/http/response.rb', line 61

def modified?
  code != 304
end

#redirect?Boolean

Returns ‘true` if the response is a `3xx` redirect and there is a `Location` header field.

Returns:

  • (Boolean)

    ‘true` if the response is a `3xx` redirect and there is a `Location` header field.



52
53
54
# File 'lib/raptor-io/protocol/http/response.rb', line 52

def redirect?
  code >= 300 && code <= 399 && !!headers['Location']
end

#text?Bool

Returns ‘true` if the response body is textual in nature, `false` otherwise (if binary).

Returns:

  • (Bool)

    ‘true` if the response body is textual in nature, `false` otherwise (if binary).



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/raptor-io/protocol/http/response.rb', line 68

def text?
  return if !@body

  if (type = headers['content-type'])
    return true if type.start_with?( 'text/' )

    # Non "application/" content types will surely not be text-based
    # so bail out early.
    return false if !type.start_with?( 'application/' )
  end

  # Last resort, more resource intensive binary detection.
  !@body.binary?
end

#to_sString

Returns String representation of the response.

Returns:

  • (String)

    String representation of the response.



85
86
87
88
89
90
91
92
93
# File 'lib/raptor-io/protocol/http/response.rb', line 85

def to_s
  headers['Content-Length'] = body.to_s.size

  r = "HTTP/#{version} #{code}"
  r <<  " #{message}" if message
  r <<  "\r\n"
  r << "#{headers.to_s}\r\n\r\n"
  r << body.to_s
end