4
attr_accessor :body, :headers, :status
6
# backwards compatability reader/writers
8
@data[:body] = new_body
13
def headers=(new_headers)
14
@data[:headers] = new_headers
19
def status=(new_status)
20
@data[:status] = new_status
25
def remote_ip=(new_remote_ip)
26
@data[:remote_ip] = new_remote_ip
32
def self.parse(socket, datum)
36
:status => socket.read(12)[9, 11].to_i,
37
:remote_ip => socket.respond_to?(:remote_ip) && socket.remote_ip
14
def initialize(attrs={})
15
@body = attrs[:body] || ''
16
@headers = attrs[:headers] || {}
17
@status = attrs[:status]
20
def self.parse(socket, params={})
21
response = new(:status => socket.readline[9, 11].to_i)
39
socket.readline # read the rest of the status line and CRLF
23
41
until ((data = socket.readline).chop!).empty?
24
42
key, value = data.split(/:\s*/, 2)
25
response.headers[key] = ([*response.headers[key]] << value).compact.join(', ')
43
datum[:response][:headers][key] = ([*datum[:response][:headers][key]] << value).compact.join(', ')
26
44
if key.casecmp('Content-Length') == 0
27
45
content_length = value.to_i
28
46
elsif (key.casecmp('Transfer-Encoding') == 0) && (value.casecmp('chunked') == 0)
33
unless (params[:method].to_s.casecmp('HEAD') == 0) || NO_ENTITY.include?(response.status)
51
unless (['HEAD', 'CONNECT'].include?(datum[:method].to_s.upcase)) || NO_ENTITY.include?(datum[:response][:status])
35
53
# check to see if expects was set and matched
36
expected_status = !params.has_key?(:expects) || [*params[:expects]].include?(response.status)
54
expected_status = !datum.has_key?(:expects) || [*datum[:expects]].include?(datum[:response][:status])
38
56
# if expects matched and there is a block, use it
39
if expected_status && params.has_key?(:response_block)
57
if expected_status && datum.has_key?(:response_block)
40
58
if transfer_encoding_chunked
41
59
# 2 == "/r/n".length
42
60
while (chunk_size = socket.readline.chop!.to_i(16)) > 0
43
params[:response_block].call(socket.read(chunk_size + 2).chop!, nil, nil)
61
datum[:response_block].call(socket.read(chunk_size + 2).chop!, nil, nil)
46
64
elsif remaining = content_length
47
remaining = content_length
48
65
while remaining > 0
49
params[:response_block].call(socket.read([CHUNK_SIZE, remaining].min), [remaining - CHUNK_SIZE, 0].max, content_length)
50
remaining -= CHUNK_SIZE
66
datum[:response_block].call(socket.read([datum[:chunk_size], remaining].min), [remaining - datum[:chunk_size], 0].max, content_length)
67
remaining -= datum[:chunk_size]
53
while remaining = socket.read(CHUNK_SIZE)
54
params[:response_block].call(remaining, remaining.length, content_length)
70
while remaining = socket.read(datum[:chunk_size])
71
datum[:response_block].call(remaining, remaining.length, content_length)
57
74
else # no block or unexpected status
58
75
if transfer_encoding_chunked
59
76
while (chunk_size = socket.readline.chop!.to_i(16)) > 0
60
response.body << socket.read(chunk_size + 2).chop! # 2 == "/r/n".length
77
datum[:response][:body] << socket.read(chunk_size + 2).chop! # 2 == "/r/n".length
62
79
socket.read(2) # 2 == "/r/n".length
63
80
elsif remaining = content_length
64
81
while remaining > 0
65
response.body << socket.read([CHUNK_SIZE, remaining].min)
66
remaining -= CHUNK_SIZE
82
datum[:response][:body] << socket.read([datum[:chunk_size], remaining].min)
83
remaining -= datum[:chunk_size]
69
response.body << socket.read
86
datum[:response][:body] << socket.read
93
def initialize(params={})
99
@headers = @data[:headers]
100
@status = @data[:status]
101
@remote_ip = @data[:remote_ip]
109
$stderr.puts("Excon::Response#params is deprecated use Excon::Response#data instead (#{caller.first})")
77
113
# Retrieve a specific header value. Header names are treated case-insensitively.