forked from chrisk/fakeweb
/
registry.rb
131 lines (104 loc) · 3.54 KB
/
registry.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
module FakeWeb
class Registry #:nodoc:
include Singleton
attr_accessor :uri_map, :passthrough_uri_map
def initialize
clean_registry
end
def clean_registry
self.uri_map = Hash.new { |hash, key| hash[key] = {} }
end
def register_uri(method, uri, options)
uri_map[normalize_uri(uri)][method] = [*[options]].flatten.collect do |option|
FakeWeb::Responder.new(method, uri, option, option[:times])
end
end
def unregister_uri(method, uri)
uri_map[normalize_uri(uri)][method] = {}
end
def registered_uri?(method, uri)
!responders_for(method, uri).empty?
end
def response_for(method, uri, &block)
responders = responders_for(method, uri)
return nil if responders.empty?
next_responder = responders.last
responders.each do |responder|
if responder.times and responder.times > 0
responder.times -= 1
next_responder = responder
break
end
end
next_responder.response(&block)
end
def register_passthrough_uri(uri)
self.passthrough_uri_map = {normalize_uri(uri) => {:any => true}}
end
def remove_passthrough_uri
self.passthrough_uri_map = {}
end
def passthrough_uri_matches?(uri)
uri = normalize_uri(uri)
uri_map_matches(passthrough_uri_map, :any, uri, URI) ||
uri_map_matches(passthrough_uri_map, :any, uri, Regexp)
end
private
def responders_for(method, uri)
uri = normalize_uri(uri)
uri_map_matches(uri_map, method, uri, URI) ||
uri_map_matches(uri_map, :any, uri, URI) ||
uri_map_matches(uri_map, method, uri, Regexp) ||
uri_map_matches(uri_map, :any, uri, Regexp) ||
[]
end
def uri_map_matches(map, method, uri, type_to_check = URI)
uris_to_check = variations_of_uri_as_strings(uri)
matches = map.select { |registered_uri, method_hash|
registered_uri.is_a?(type_to_check) && method_hash.has_key?(method)
}.select { |registered_uri, method_hash|
if type_to_check == URI
uris_to_check.include?(registered_uri.to_s)
elsif type_to_check == Regexp
uris_to_check.any? { |u| u.match(registered_uri) }
end
}
if matches.size > 1
raise MultipleMatchingURIsError,
"More than one registered URI matched this request: #{method.to_s.upcase} #{uri}"
end
matches.map { |_, method_hash| method_hash[method] }.first
end
def variations_of_uri_as_strings(uri_object)
normalized_uri = normalize_uri(uri_object.dup)
normalized_uri_string = normalized_uri.to_s
variations = [normalized_uri_string]
# if the port is implied in the original, add a copy with an explicit port
if normalized_uri.default_port == normalized_uri.port
variations << normalized_uri_string.sub(
/#{Regexp.escape(normalized_uri.request_uri)}$/,
":#{normalized_uri.port}#{normalized_uri.request_uri}")
end
variations
end
def normalize_uri(uri)
return uri if uri.is_a?(Regexp)
normalized_uri =
case uri
when URI then uri
when String
uri = 'http://' + uri unless uri.match('^https?://')
URI.parse(uri)
end
normalized_uri.query = sort_query_params(normalized_uri.query)
normalized_uri.normalize
end
def sort_query_params(query)
if query.nil? || query.empty?
nil
else
query.split('&').sort.join('&')
end
end
end
end