webmock 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +9 -0
- data/README.md +169 -76
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/lib/webmock.rb +12 -9
- data/lib/webmock/adapters/rspec.rb +20 -22
- data/lib/webmock/adapters/rspec/matchers.rb +4 -4
- data/lib/webmock/adapters/rspec/webmock_matcher.rb +2 -2
- data/lib/webmock/adapters/test_unit.rb +20 -21
- data/lib/webmock/http_lib_adapters/net_http.rb +51 -15
- data/lib/webmock/request_profile.rb +5 -44
- data/lib/webmock/request_registry.rb +10 -11
- data/lib/webmock/request_signature.rb +44 -0
- data/lib/webmock/request_stub.rb +3 -3
- data/lib/webmock/response.rb +1 -1
- data/lib/webmock/rspec.rb +1 -0
- data/lib/webmock/test_unit.rb +1 -0
- data/lib/webmock/util/hash_counter.rb +16 -8
- data/lib/webmock/util/headers.rb +23 -0
- data/lib/webmock/util/uri.rb +81 -0
- data/lib/webmock/webmock.rb +16 -19
- data/spec/net_http_spec.rb +10 -9
- data/spec/other_net_http_libs_spec.rb +3 -1
- data/spec/request_profile_spec.rb +6 -116
- data/spec/request_registry_spec.rb +12 -17
- data/spec/request_signature_spec.rb +155 -0
- data/spec/request_stub_spec.rb +2 -2
- data/spec/response_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/util/hash_counter_spec.rb +4 -4
- data/spec/util/headers_spec.rb +11 -0
- data/spec/util/uri_spec.rb +213 -0
- data/spec/vendor/addressable/lib/addressable/uri.rb +8 -0
- data/spec/vendor/addressable/lib/uri.rb +0 -0
- data/spec/webmock_spec.rb +58 -10
- data/test/test_helper.rb +5 -1
- data/test/test_webmock.rb +11 -6
- data/webmock.gemspec +21 -6
- metadata +28 -6
- data/lib/webmock/url.rb +0 -46
- data/lib/webmock/utility.rb +0 -65
- data/spec/utility_spec.rb +0 -70
@@ -8,12 +8,12 @@ module WebMock
|
|
8
8
|
WebMock::RequestProfileMatcher.new.times(0)
|
9
9
|
end
|
10
10
|
|
11
|
-
def have_requested(method,
|
12
|
-
WebMock::WebMockMatcher.new(method,
|
11
|
+
def have_requested(method, uri)
|
12
|
+
WebMock::WebMockMatcher.new(method, uri)
|
13
13
|
end
|
14
14
|
|
15
|
-
def have_not_requested(method,
|
16
|
-
WebMock::WebMockMatcher.new(method,
|
15
|
+
def have_not_requested(method, uri)
|
16
|
+
WebMock::WebMockMatcher.new(method, uri).times(0)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module WebMock
|
2
2
|
class WebMockMatcher
|
3
3
|
|
4
|
-
def initialize(method,
|
4
|
+
def initialize(method, uri)
|
5
5
|
@request_execution_verifier = RequestExecutionVerifier.new
|
6
|
-
@request_execution_verifier.request_profile = RequestProfile.new(method,
|
6
|
+
@request_execution_verifier.request_profile = RequestProfile.new(method, uri)
|
7
7
|
end
|
8
8
|
|
9
9
|
def once
|
@@ -1,25 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Test::Unit::TestCase
|
4
|
-
include WebMock
|
5
|
-
alias setup_without_webmock setup
|
6
|
-
def setup
|
7
|
-
reset_webmock
|
8
|
-
@original_allow_net_connect = WebMock.net_connect_allowed?
|
9
|
-
WebMock.disable_net_connect!
|
10
|
-
end
|
1
|
+
require 'test/unit'
|
2
|
+
require 'webmock'
|
11
3
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
class Test::Unit::TestCase
|
5
|
+
alias setup_without_webmock setup
|
6
|
+
def setup
|
7
|
+
WebMock.reset_webmock
|
8
|
+
@original_allow_net_connect = WebMock.net_connect_allowed?
|
9
|
+
WebMock.disable_net_connect!
|
16
10
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
raise Test::Unit::AssertionFailedError.new(message)
|
22
|
-
end
|
11
|
+
|
12
|
+
alias teardown_without_webmock teardown
|
13
|
+
def teardown
|
14
|
+
@original_allow_net_connect ? WebMock.allow_net_connect! : WebMock.disable_net_connect!
|
23
15
|
end
|
24
|
-
|
25
16
|
end
|
17
|
+
|
18
|
+
module WebMock
|
19
|
+
private
|
20
|
+
def assertion_failure(message)
|
21
|
+
raise Test::Unit::AssertionFailedError.new(message)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -2,7 +2,6 @@ require 'net/http'
|
|
2
2
|
require 'net/https'
|
3
3
|
require 'stringio'
|
4
4
|
|
5
|
-
|
6
5
|
class StubSocket #:nodoc:
|
7
6
|
|
8
7
|
def initialize(*args)
|
@@ -61,11 +60,11 @@ module Net #:nodoc: all
|
|
61
60
|
protocol = use_ssl? ? "https" : "http"
|
62
61
|
|
63
62
|
path = request.path
|
64
|
-
path = URI.
|
63
|
+
path = Addressable::URI.heuristic_parse(request.path).request_uri if request.path =~ /^http/
|
65
64
|
|
66
65
|
if request["authorization"] =~ /^Basic /
|
67
|
-
userinfo = WebMock::
|
68
|
-
userinfo = WebMock::
|
66
|
+
userinfo = WebMock::Util::Headers.decode_userinfo_from_header(request["authorization"])
|
67
|
+
userinfo = WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo) + "@"
|
69
68
|
else
|
70
69
|
userinfo = ""
|
71
70
|
end
|
@@ -74,24 +73,21 @@ module Net #:nodoc: all
|
|
74
73
|
method = request.method.downcase.to_sym
|
75
74
|
|
76
75
|
headers = Hash[*request.to_hash.map {|k,v| [k, v.flatten]}.flatten]
|
77
|
-
headers.reject! {|k,v| k =~ /[Aa]ccept/ && v = '*/*'}
|
76
|
+
headers.reject! {|k,v| k =~ /[Aa]ccept/ && v = '*/*'} #removing header added by Net::HTTP
|
77
|
+
|
78
|
+
request_signature = WebMock::RequestSignature.new(method, uri, body, headers)
|
78
79
|
|
79
|
-
|
80
|
+
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
80
81
|
|
81
|
-
if WebMock.registered_request?(
|
82
|
+
if WebMock.registered_request?(request_signature)
|
82
83
|
@socket = Net::HTTP.socket_type.new
|
83
|
-
webmock_response = WebMock.response_for_request(
|
84
|
+
webmock_response = WebMock.response_for_request(request_signature)
|
84
85
|
build_net_http_response(webmock_response, &block)
|
85
86
|
elsif WebMock.net_connect_allowed?
|
86
|
-
WebMock::RequestRegistry.instance.requested.put(request_profile)
|
87
87
|
connect_without_webmock
|
88
88
|
request_without_webmock(request, body, &block)
|
89
89
|
else
|
90
|
-
|
91
|
-
message = "Real HTTP connections are disabled. Unregistered request: #{request.method} #{uri}"
|
92
|
-
message << " with body '#{body}'" if body
|
93
|
-
message << " with headers #{WebMock::Utility.normalize_headers(headers).inspect.gsub("\"","'")}" if
|
94
|
-
headers && !headers.empty?
|
90
|
+
message = "Real HTTP connections are disabled. Unregistered request: #{request_signature}"
|
95
91
|
raise WebMock::NetConnectNotAllowedError, message
|
96
92
|
end
|
97
93
|
end
|
@@ -101,7 +97,7 @@ headers && !headers.empty?
|
|
101
97
|
|
102
98
|
def connect_with_webmock
|
103
99
|
unless @@alredy_checked_for_net_http_replacement_libs ||= false
|
104
|
-
WebMock::
|
100
|
+
WebMock::NetHTTPUtility.puts_warning_for_net_http_replacement_libs_if_needed
|
105
101
|
@@alredy_checked_for_net_http_replacement_libs = true
|
106
102
|
end
|
107
103
|
nil
|
@@ -127,3 +123,43 @@ headers && !headers.empty?
|
|
127
123
|
end
|
128
124
|
|
129
125
|
end
|
126
|
+
|
127
|
+
module WebMock
|
128
|
+
module NetHTTPUtility
|
129
|
+
def self.puts_warning_for_net_http_around_advice_libs_if_needed
|
130
|
+
libs = {"Samuel" => defined?(Samuel)}
|
131
|
+
warnings = libs.select { |_, loaded| loaded }.map do |name, _|
|
132
|
+
<<-TEXT.gsub(/ {10}/, '')
|
133
|
+
\e[1mWarning: WebMock was loaded after #{name}\e[0m
|
134
|
+
* #{name}'s code is being ignored when a request is handled by WebMock,
|
135
|
+
because both libraries work by patching Net::HTTP.
|
136
|
+
* To fix this, just reorder your requires so that WebMock is before #{name}.
|
137
|
+
TEXT
|
138
|
+
end
|
139
|
+
$stderr.puts "\n" + warnings.join("\n") + "\n" if warnings.any?
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.record_loaded_net_http_replacement_libs
|
143
|
+
libs = {"RightHttpConnection" => defined?(RightHttpConnection)}
|
144
|
+
@loaded_net_http_replacement_libs = libs.map { |name, loaded| name if loaded }.compact
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.puts_warning_for_net_http_replacement_libs_if_needed
|
148
|
+
libs = {"RightHttpConnection" => defined?(RightHttpConnection)}
|
149
|
+
warnings = libs.select { |_, loaded| loaded }.
|
150
|
+
reject { |name, _| @loaded_net_http_replacement_libs.include?(name) }.
|
151
|
+
map do |name, _|
|
152
|
+
<<-TEXT.gsub(/ {10}/, '')
|
153
|
+
\e[1mWarning: #{name} was loaded after WebMock\e[0m
|
154
|
+
* WebMock's code is being ignored, because #{name} replaces parts of
|
155
|
+
Net::HTTP without deferring to other libraries. This will break Net::HTTP requests.
|
156
|
+
* To fix this, just reorder your requires so that #{name} is before WebMock.
|
157
|
+
TEXT
|
158
|
+
end
|
159
|
+
$stderr.puts "\n" + warnings.join("\n") + "\n" if warnings.any?
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
WebMock::NetHTTPUtility.record_loaded_net_http_replacement_libs
|
165
|
+
WebMock::NetHTTPUtility.puts_warning_for_net_http_around_advice_libs_if_needed
|
@@ -4,64 +4,25 @@ module WebMock
|
|
4
4
|
|
5
5
|
def initialize(method, uri, body = nil, headers = nil)
|
6
6
|
super
|
7
|
-
self.uri = WebMock::
|
8
|
-
self.headers =
|
7
|
+
self.uri = WebMock::Util::URI.normalize_uri(self.uri) unless self.uri.is_a?(Addressable::URI)
|
8
|
+
self.headers = WebMock::Util::Headers.normalize_headers(self.headers)
|
9
9
|
end
|
10
10
|
|
11
11
|
def with(options)
|
12
12
|
self.body = options[:body] if options.has_key?(:body)
|
13
|
-
self.headers =
|
13
|
+
self.headers = WebMock::Util::Headers.normalize_headers(options[:headers]) if options.has_key?(:headers)
|
14
14
|
self
|
15
15
|
end
|
16
16
|
|
17
|
-
#self needs to be a subset of other. Other needs to be more general.
|
18
|
-
def match(other)
|
19
|
-
match_method(other) &&
|
20
|
-
match_body(other) &&
|
21
|
-
match_headers(other) &&
|
22
|
-
match_url(other)
|
23
|
-
end
|
24
|
-
|
25
17
|
def to_s
|
26
|
-
string = "#{self.method.to_s.upcase} #{self.uri}"
|
18
|
+
string = "#{self.method.to_s.upcase} #{WebMock::Util::URI.strip_default_port_from_uri_string(self.uri.to_s)}"
|
27
19
|
string << " with body '#{body}'" if body
|
28
20
|
if headers && !headers.empty?
|
29
|
-
string << " with headers #{WebMock::
|
21
|
+
string << " with headers #{WebMock::Util::Headers.normalize_headers(headers).inspect.gsub("\"","'")}"
|
30
22
|
end
|
31
23
|
string
|
32
24
|
end
|
33
25
|
|
34
|
-
private
|
35
|
-
|
36
|
-
def match_url(other)
|
37
|
-
raise "Can't match regexp request profile" if self.uri.is_a?(Regexp)
|
38
|
-
@uris_to_check ||= WebMock::URL.variations_of_uri_as_strings(self.uri)
|
39
|
-
if other.uri.is_a?(URI)
|
40
|
-
@uris_to_check.include?(other.uri.to_s)
|
41
|
-
elsif other.uri.is_a?(Regexp)
|
42
|
-
@uris_to_check.any? { |u| u.match(other.uri) }
|
43
|
-
else
|
44
|
-
false
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def match_headers(other)
|
49
|
-
return false if self.headers && !self.headers.empty? && other.headers && other.headers.empty?
|
50
|
-
if other.headers && !other.headers.empty?
|
51
|
-
other.headers.each do | key, value |
|
52
|
-
return false unless (self.headers && self.headers.has_key?(key) && value == self.headers[key])
|
53
|
-
end
|
54
|
-
end
|
55
|
-
return true
|
56
|
-
end
|
57
|
-
|
58
|
-
def match_body(other)
|
59
|
-
other.body == self.body || other.body.nil?
|
60
|
-
end
|
61
|
-
|
62
|
-
def match_method(other)
|
63
|
-
other.method == self.method || other.method == :any
|
64
|
-
end
|
65
26
|
end
|
66
27
|
|
67
28
|
end
|
@@ -3,7 +3,7 @@ module WebMock
|
|
3
3
|
class RequestRegistry
|
4
4
|
include Singleton
|
5
5
|
|
6
|
-
attr_accessor :request_stubs, :
|
6
|
+
attr_accessor :request_stubs, :requested_signatures
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
reset_webmock
|
@@ -11,7 +11,7 @@ module WebMock
|
|
11
11
|
|
12
12
|
def reset_webmock
|
13
13
|
self.request_stubs = []
|
14
|
-
self.
|
14
|
+
self.requested_signatures = Util::HashCounter.new
|
15
15
|
end
|
16
16
|
|
17
17
|
def register_request_stub(stub)
|
@@ -19,27 +19,26 @@ module WebMock
|
|
19
19
|
stub
|
20
20
|
end
|
21
21
|
|
22
|
-
def registered_request?(
|
23
|
-
|
22
|
+
def registered_request?(request_signature)
|
23
|
+
request_stub_for(request_signature)
|
24
24
|
end
|
25
25
|
|
26
|
-
def response_for_request(
|
27
|
-
stub =
|
28
|
-
self.requested.put(request_profile)
|
26
|
+
def response_for_request(request_signature)
|
27
|
+
stub = request_stub_for(request_signature)
|
29
28
|
stub ? stub.response : nil
|
30
29
|
end
|
31
30
|
|
32
31
|
def times_executed(request_profile)
|
33
|
-
self.
|
34
|
-
|
32
|
+
self.requested_signatures.hash.select { |request_signature, times_executed|
|
33
|
+
request_signature.match(request_profile)
|
35
34
|
}.inject(0) {|sum, (_, times_executed)| sum + times_executed }
|
36
35
|
end
|
37
36
|
|
38
37
|
private
|
39
38
|
|
40
|
-
def
|
39
|
+
def request_stub_for(request_signature)
|
41
40
|
request_stubs.detect { |registered_request_stub|
|
42
|
-
|
41
|
+
request_signature.match(registered_request_stub.request_profile)
|
43
42
|
}
|
44
43
|
end
|
45
44
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module WebMock
|
2
|
+
|
3
|
+
class RequestSignature < RequestProfile
|
4
|
+
|
5
|
+
def match(request_profile)
|
6
|
+
match_method(request_profile) &&
|
7
|
+
match_body(request_profile) &&
|
8
|
+
match_headers(request_profile) &&
|
9
|
+
match_uri(request_profile)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def match_uri(request_profile)
|
15
|
+
if request_profile.uri.is_a?(Addressable::URI)
|
16
|
+
WebMock::Util::URI.normalize_uri(uri) === WebMock::Util::URI.normalize_uri(request_profile.uri)
|
17
|
+
elsif request_profile.uri.is_a?(Regexp)
|
18
|
+
WebMock::Util::URI.variations_of_uri_as_strings(self.uri).any? { |u| u.match(request_profile.uri) }
|
19
|
+
else
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def match_headers(request_profile)
|
25
|
+
return false if self.headers && !self.headers.empty? && request_profile.headers && request_profile.headers.empty?
|
26
|
+
if request_profile.headers && !request_profile.headers.empty?
|
27
|
+
request_profile.headers.each do | key, value |
|
28
|
+
return false unless (self.headers && self.headers.has_key?(key) && value == self.headers[key])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
def match_body(request_profile)
|
35
|
+
request_profile.body == self.body || request_profile.body.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def match_method(request_profile)
|
39
|
+
request_profile.method == self.method || request_profile.method == :any
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
end
|
data/lib/webmock/request_stub.rb
CHANGED
@@ -2,15 +2,15 @@ module WebMock
|
|
2
2
|
class RequestStub
|
3
3
|
attr_accessor :request_profile, :response
|
4
4
|
|
5
|
-
def initialize(method,
|
6
|
-
@request_profile = RequestProfile.new(method,
|
5
|
+
def initialize(method, uri)
|
6
|
+
@request_profile = RequestProfile.new(method, uri)
|
7
7
|
@response = WebMock::Response.new
|
8
8
|
self
|
9
9
|
end
|
10
10
|
|
11
11
|
def with(params)
|
12
12
|
@request_profile.body = params[:body]
|
13
|
-
@request_profile.headers =
|
13
|
+
@request_profile.headers = Util::Headers.normalize_headers(params[:headers])
|
14
14
|
self
|
15
15
|
end
|
16
16
|
|
data/lib/webmock/response.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "adapters/rspec")
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "adapters/test_unit")
|
@@ -1,12 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module WebMock
|
2
|
+
|
3
|
+
module Util
|
4
|
+
|
5
|
+
class Util::HashCounter
|
6
|
+
attr_accessor :hash
|
7
|
+
def initialize
|
4
8
|
self.hash = {}
|
5
|
-
|
6
|
-
|
9
|
+
end
|
10
|
+
def put key, num=1
|
7
11
|
hash[key] = (hash[key] || 0) + num
|
8
|
-
|
9
|
-
|
12
|
+
end
|
13
|
+
def get key
|
10
14
|
hash[key] || 0
|
15
|
+
end
|
11
16
|
end
|
12
|
-
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module WebMock
|
2
|
+
|
3
|
+
module Util
|
4
|
+
|
5
|
+
class Headers
|
6
|
+
|
7
|
+
def self.normalize_headers(headers)
|
8
|
+
return nil unless headers
|
9
|
+
array = headers.map { |name, value|
|
10
|
+
[name.to_s.split(/_|-/).map { |segment| segment.capitalize }.join("-"), value.to_s]
|
11
|
+
}
|
12
|
+
Hash[*array.flatten]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.decode_userinfo_from_header(header)
|
16
|
+
header.sub(/^Basic /, "").unpack("m").first
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Addressable
|
2
|
+
class URI
|
3
|
+
module CharacterClasses
|
4
|
+
USERINFO = UNRESERVED + SUB_DELIMS + "\\:"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module WebMock
|
10
|
+
|
11
|
+
module Util
|
12
|
+
|
13
|
+
class URI
|
14
|
+
|
15
|
+
def self.normalize_uri(uri)
|
16
|
+
return uri if uri.is_a?(Regexp)
|
17
|
+
uri = 'http://' + uri unless uri.match('^https?://') if uri.is_a?(String)
|
18
|
+
normalized_uri = Addressable::URI.heuristic_parse(uri)
|
19
|
+
normalized_uri.query_values = normalized_uri.query_values if normalized_uri.query_values
|
20
|
+
normalized_uri.normalize!
|
21
|
+
normalized_uri.port = normalized_uri.inferred_port unless normalized_uri.port && normalized_uri.inferred_port
|
22
|
+
normalized_uri
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.variations_of_uri_as_strings(uri_object)
|
26
|
+
normalized_uri = normalize_uri(uri_object.dup).freeze
|
27
|
+
uris = [ normalized_uri ]
|
28
|
+
|
29
|
+
if normalized_uri.port == Addressable::URI.port_mapping[normalized_uri.scheme]
|
30
|
+
uris = uris_with_inferred_port_and_without(uris)
|
31
|
+
end
|
32
|
+
|
33
|
+
if normalized_uri.scheme == "http"
|
34
|
+
uris = uris_with_scheme_and_without(uris)
|
35
|
+
end
|
36
|
+
|
37
|
+
if normalized_uri.path == '/' && normalized_uri.query == nil
|
38
|
+
uris = uris_with_trailing_slash_and_without(uris)
|
39
|
+
end
|
40
|
+
|
41
|
+
uris = uris_encoded_and_unencoded(uris)
|
42
|
+
|
43
|
+
uris.map {|uri| uri.to_s.gsub(/^\/\//,'') }.uniq
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.strip_default_port_from_uri_string(uri_string)
|
47
|
+
case uri_string
|
48
|
+
when %r{^http://} then uri_string.sub(%r{:80(/|$)}, '\1')
|
49
|
+
when %r{^https://} then uri_string.sub(%r{:443(/|$)}, '\1')
|
50
|
+
else uri_string
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.encode_unsafe_chars_in_userinfo(userinfo)
|
55
|
+
Addressable::URI.encode_component(userinfo, Addressable::URI::CharacterClasses::USERINFO)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def self.uris_with_inferred_port_and_without(uris)
|
61
|
+
uris.map { |uri| [ uri, uri.omit(:port).freeze ] }.flatten
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.uris_encoded_and_unencoded(uris)
|
65
|
+
uris.map do |uri|
|
66
|
+
[ uri, Addressable::URI.heuristic_parse(Addressable::URI.unencode(uri)).freeze ]
|
67
|
+
end.flatten
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.uris_with_scheme_and_without(uris)
|
71
|
+
uris.map { |uri| [ uri, uri.omit(:scheme).freeze ] }.flatten
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.uris_with_trailing_slash_and_without(uris)
|
75
|
+
uris = uris.map { |uri| [ uri, uri.omit(:path).freeze ] }.flatten
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|