/
responder.rb
107 lines (85 loc) · 2.96 KB
/
responder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
module FakeWeb
class Responder #:nodoc:
attr_accessor :method, :uri, :options, :times
KNOWN_OPTIONS = [:exception, :file, :response, :status, :string].freeze
def initialize(method, uri, options, times)
self.method = method
self.uri = uri
self.options = options
self.times = times ? times : 1
end
def response(&block)
if has_baked_response?
response = baked_response
else
code, msg = meta_information
response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
response.instance_variable_set(:@body, content)
headers_extracted_from_options.each { |name, value| response[name] = value }
end
response.instance_variable_set(:@read, true)
response.extend FakeWeb::Response
optionally_raise(response)
yield response if block_given?
response
end
private
def headers_extracted_from_options
options.reject {|name, _| KNOWN_OPTIONS.include?(name) }.map { |name, value|
[name.to_s.split("_").map { |segment| segment.capitalize }.join("-"), value]
}
end
def content
[ :file, :string ].each do |map_option|
next unless options.has_key?(map_option)
return self.send("#{map_option}_response", options[map_option])
end
return ''
end
def file_response(path)
IO.read(path)
end
def string_response(string)
string
end
def baked_response
resp = case options[:response]
when Net::HTTPResponse then options[:response]
when String
socket = Net::BufferedIO.new(options[:response])
r = Net::HTTPResponse.read_new(socket)
# Store the oiriginal transfer-encoding
saved_transfer_encoding = r.instance_eval {
@header['transfer-encoding'] if @header.key?('transfer-encoding')
}
# read the body of response.
r.instance_eval { @header['transfer-encoding'] = nil }
r.reading_body(socket, true) {}
# Delete the transfer-encoding key from r.@header if there wasn't one,
# else restore the saved_transfer_encoding.
if saved_transfer_encoding.nil?
r.instance_eval { @header.delete('transfer-encoding') }
else
r.instance_eval { @header['transfer-encoding'] = saved_transfer_encoding }
end
r
else raise StandardError, "Handler unimplemented for response #{options[:response]}"
end
end
def has_baked_response?
options.has_key?(:response)
end
def optionally_raise(response)
return unless options.has_key?(:exception)
case options[:exception].to_s
when "Net::HTTPError", "OpenURI::HTTPError"
raise options[:exception].new('Exception from FakeWeb', response)
else
raise options[:exception].new('Exception from FakeWeb')
end
end
def meta_information
options.has_key?(:status) ? options[:status] : [200, 'OK']
end
end
end