vcr 1.11.3 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +6 -2
  3. data/CHANGELOG.md +49 -1
  4. data/Gemfile +1 -5
  5. data/Guardfile +0 -5
  6. data/README.md +3 -2
  7. data/Rakefile +11 -16
  8. data/cucumber.yml +0 -4
  9. data/features/.nav +14 -2
  10. data/features/cassettes/automatic_re_recording.feature +4 -6
  11. data/features/cassettes/dynamic_erb.feature +6 -8
  12. data/features/cassettes/exclusive.feature +111 -0
  13. data/features/cassettes/format.feature +16 -14
  14. data/features/cassettes/naming.feature +4 -6
  15. data/features/cassettes/no_cassette.feature +25 -28
  16. data/features/cassettes/update_content_length_header.feature +9 -9
  17. data/features/configuration/allow_http_connections_when_no_cassette.feature +6 -8
  18. data/features/configuration/cassette_library_dir.feature +4 -6
  19. data/features/configuration/default_cassette_options.feature +12 -10
  20. data/features/configuration/filter_sensitive_data.feature +12 -17
  21. data/features/configuration/{stub_with.feature → hook_into.feature} +63 -62
  22. data/features/configuration/hooks.feature +23 -33
  23. data/features/configuration/ignore_hosts.feature +16 -17
  24. data/features/configuration/ignore_localhost.feature +33 -42
  25. data/features/http_libraries/em_http_request.feature +7 -8
  26. data/features/http_libraries/net_http.feature +26 -28
  27. data/features/middleware/faraday.feature +17 -56
  28. data/features/middleware/rack.feature +8 -11
  29. data/features/record_modes/all.feature +5 -7
  30. data/features/record_modes/new_episodes.feature +5 -7
  31. data/features/record_modes/none.feature +6 -6
  32. data/features/record_modes/once.feature +6 -8
  33. data/features/request_matching/README.md +28 -0
  34. data/features/request_matching/body.feature +81 -0
  35. data/features/request_matching/custom_matcher.feature +125 -0
  36. data/features/request_matching/headers.feature +85 -0
  37. data/features/request_matching/host.feature +85 -0
  38. data/features/request_matching/identical_request_sequence.feature +79 -0
  39. data/features/request_matching/method.feature +86 -0
  40. data/features/request_matching/path.feature +86 -0
  41. data/features/request_matching/playback_repeats.feature +87 -0
  42. data/features/request_matching/uri.feature +84 -0
  43. data/features/request_matching/uri_without_param.feature +85 -0
  44. data/features/step_definitions/cli_steps.rb +4 -28
  45. data/features/support/env.rb +11 -9
  46. data/features/support/http_lib_filters.rb +2 -11
  47. data/features/support/vcr_cucumber_helpers.rb +4 -5
  48. data/features/test_frameworks/cucumber.feature +17 -18
  49. data/features/test_frameworks/rspec.feature +8 -12
  50. data/features/test_frameworks/shoulda.feature +5 -8
  51. data/features/test_frameworks/test_unit.feature +5 -8
  52. data/lib/vcr.rb +38 -58
  53. data/lib/vcr/cassette.rb +41 -60
  54. data/lib/vcr/cassette/http_interaction_list.rb +56 -0
  55. data/lib/vcr/cassette/reader.rb +29 -31
  56. data/lib/vcr/configuration.rb +76 -0
  57. data/lib/vcr/deprecations.rb +39 -0
  58. data/lib/vcr/errors.rb +22 -0
  59. data/lib/vcr/library_hooks.rb +19 -0
  60. data/lib/vcr/library_hooks/excon.rb +136 -0
  61. data/lib/vcr/library_hooks/fakeweb.rb +110 -0
  62. data/lib/vcr/library_hooks/faraday.rb +3 -0
  63. data/lib/vcr/library_hooks/typhoeus.rb +98 -0
  64. data/lib/vcr/library_hooks/webmock.rb +100 -0
  65. data/lib/vcr/middleware/faraday.rb +43 -36
  66. data/lib/vcr/middleware/rack.rb +28 -4
  67. data/lib/vcr/request_handler.rb +43 -0
  68. data/lib/vcr/request_ignorer.rb +31 -0
  69. data/lib/vcr/request_matcher_registry.rb +86 -0
  70. data/lib/vcr/structs/http_interaction.rb +24 -18
  71. data/lib/vcr/structs/normalizers/body.rb +1 -1
  72. data/lib/vcr/structs/normalizers/header.rb +1 -1
  73. data/lib/vcr/structs/normalizers/status_message.rb +1 -1
  74. data/lib/vcr/structs/normalizers/uri.rb +1 -1
  75. data/lib/vcr/structs/request.rb +0 -13
  76. data/lib/vcr/structs/response.rb +2 -9
  77. data/lib/vcr/structs/response_status.rb +0 -4
  78. data/lib/vcr/test_frameworks/cucumber.rb +1 -1
  79. data/lib/vcr/test_frameworks/rspec.rb +1 -1
  80. data/lib/vcr/util/hooks.rb +28 -19
  81. data/lib/vcr/util/internet_connection.rb +29 -2
  82. data/lib/vcr/util/version_checker.rb +60 -0
  83. data/lib/vcr/version.rb +1 -1
  84. data/script/FullBuildRakeFile +0 -7
  85. data/script/full_build +1 -1
  86. data/spec/capture_warnings.rb +36 -31
  87. data/spec/fixtures/{1.9.1/cassette_spec → cassette_spec}/empty.yml +0 -0
  88. data/spec/fixtures/{not_1.9.1/cassette_spec → cassette_spec}/example.yml +0 -0
  89. data/spec/fixtures/{not_1.9.1/cassette_spec → cassette_spec}/with_localhost_requests.yml +0 -0
  90. data/spec/fixtures/{not_1.9.1/fake_example.com_responses.yml → fake_example.com_responses.yml} +0 -0
  91. data/spec/fixtures/{not_1.9.1/match_requests_on.yml → match_requests_on.yml} +0 -0
  92. data/spec/monkey_patches.rb +40 -11
  93. data/spec/spec_helper.rb +7 -43
  94. data/spec/support/http_library_adapters.rb +3 -13
  95. data/spec/support/shared_example_groups/{http_library.rb → hook_into_http_library.rb} +39 -111
  96. data/spec/support/shared_example_groups/version_checking.rb +9 -9
  97. data/spec/vcr/cassette/http_interaction_list_spec.rb +178 -0
  98. data/spec/vcr/cassette/reader_spec.rb +2 -2
  99. data/spec/vcr/cassette_spec.rb +121 -156
  100. data/spec/vcr/configuration_spec.rb +143 -0
  101. data/spec/vcr/deprecations_spec.rb +91 -0
  102. data/spec/vcr/{http_stubbing_adapters → library_hooks}/excon_spec.rb +6 -9
  103. data/spec/vcr/library_hooks/fakeweb_spec.rb +83 -0
  104. data/spec/vcr/{http_stubbing_adapters → library_hooks}/typhoeus_spec.rb +7 -11
  105. data/spec/vcr/library_hooks/webmock_spec.rb +17 -0
  106. data/spec/vcr/library_hooks_spec.rb +51 -0
  107. data/spec/vcr/middleware/faraday_spec.rb +17 -44
  108. data/spec/vcr/middleware/rack_spec.rb +94 -58
  109. data/spec/vcr/request_ignorer_spec.rb +54 -0
  110. data/spec/vcr/request_matcher_registry_spec.rb +223 -0
  111. data/spec/vcr/structs/request_spec.rb +0 -33
  112. data/spec/vcr/structs/response_spec.rb +0 -24
  113. data/spec/vcr/structs/response_status_spec.rb +0 -9
  114. data/spec/vcr/util/hooks_spec.rb +3 -5
  115. data/spec/vcr/version_spec.rb +1 -1
  116. data/spec/vcr_spec.rb +79 -91
  117. data/vcr.gemspec +1 -1
  118. metadata +83 -103
  119. data/features/cassettes/request_matching.feature +0 -383
  120. data/lib/vcr/config.rb +0 -84
  121. data/lib/vcr/deprecations/cassette.rb +0 -29
  122. data/lib/vcr/deprecations/config.rb +0 -18
  123. data/lib/vcr/deprecations/http_stubbing_adapters/common.rb +0 -9
  124. data/lib/vcr/deprecations/http_stubbing_adapters/fakeweb.rb +0 -11
  125. data/lib/vcr/extensions/net_http.rb +0 -32
  126. data/lib/vcr/http_stubbing_adapters/common.rb +0 -202
  127. data/lib/vcr/http_stubbing_adapters/excon.rb +0 -178
  128. data/lib/vcr/http_stubbing_adapters/fakeweb.rb +0 -107
  129. data/lib/vcr/http_stubbing_adapters/faraday.rb +0 -26
  130. data/lib/vcr/http_stubbing_adapters/multi_object_proxy.rb +0 -43
  131. data/lib/vcr/http_stubbing_adapters/typhoeus.rb +0 -115
  132. data/lib/vcr/http_stubbing_adapters/webmock.rb +0 -120
  133. data/lib/vcr/middleware/cassette_arguments.rb +0 -19
  134. data/lib/vcr/middleware/common.rb +0 -20
  135. data/lib/vcr/request_matcher.rb +0 -94
  136. data/lib/vcr/rspec.rb +0 -2
  137. data/lib/vcr/util/basic_object.rb +0 -43
  138. data/lib/vcr/util/ping.rb +0 -30
  139. data/lib/vcr/util/regexes.rb +0 -37
  140. data/spec/fixtures/1.9.1/0_3_1_cassette.yml +0 -29
  141. data/spec/fixtures/1.9.1/cassette_spec/example.yml +0 -110
  142. data/spec/fixtures/1.9.1/cassette_spec/with_localhost_requests.yml +0 -109
  143. data/spec/fixtures/1.9.1/example_net_http.yml +0 -14
  144. data/spec/fixtures/1.9.1/example_net_http_request.yml +0 -12
  145. data/spec/fixtures/1.9.1/example_net_http_response.yml +0 -25
  146. data/spec/fixtures/1.9.1/fake_example.com_responses.yml +0 -108
  147. data/spec/fixtures/1.9.1/match_requests_on.yml +0 -185
  148. data/spec/fixtures/not_1.9.1/0_3_1_cassette.yml +0 -29
  149. data/spec/fixtures/not_1.9.1/cassette_spec/empty.yml +0 -0
  150. data/spec/fixtures/not_1.9.1/example_net_http.yml +0 -14
  151. data/spec/fixtures/not_1.9.1/example_net_http_request.yml +0 -12
  152. data/spec/fixtures/not_1.9.1/example_net_http_response.yml +0 -25
  153. data/spec/support/shared_example_groups/http_stubbing_adapter.rb +0 -133
  154. data/spec/support/shared_example_groups/ignore_localhost_deprecation.rb +0 -28
  155. data/spec/vcr/config_spec.rb +0 -181
  156. data/spec/vcr/deprecations/cassette_spec.rb +0 -57
  157. data/spec/vcr/deprecations/config_spec.rb +0 -30
  158. data/spec/vcr/deprecations/http_stubbing_adapters/common_spec.rb +0 -7
  159. data/spec/vcr/deprecations/http_stubbing_adapters/fakeweb_spec.rb +0 -16
  160. data/spec/vcr/extensions/net_http_spec.rb +0 -80
  161. data/spec/vcr/http_stubbing_adapters/fakeweb_spec.rb +0 -19
  162. data/spec/vcr/http_stubbing_adapters/faraday_spec.rb +0 -76
  163. data/spec/vcr/http_stubbing_adapters/multi_object_proxy_spec.rb +0 -101
  164. data/spec/vcr/http_stubbing_adapters/webmock_spec.rb +0 -17
  165. data/spec/vcr/middleware/cassette_arguments_spec.rb +0 -32
  166. data/spec/vcr/request_matcher_spec.rb +0 -230
@@ -0,0 +1,3 @@
1
+ Kernel.warn "WARNING: `VCR.config { |c| c.stub_with :faraday }` is deprecated. " +
2
+ "Just use `VCR::Middleware::Faraday` in your faraday stack."
3
+
@@ -0,0 +1,98 @@
1
+ require 'vcr/util/version_checker'
2
+ require 'vcr/request_handler'
3
+ require 'typhoeus'
4
+
5
+ VCR::VersionChecker.new('Typhoeus', Typhoeus::VERSION, '0.2.1', '0.2').check_version!
6
+
7
+ module VCR
8
+ class LibraryHooks
9
+ module Typhoeus
10
+ module Helpers
11
+ def vcr_request_from(request)
12
+ VCR::Request.new \
13
+ request.method,
14
+ request.url,
15
+ request.body,
16
+ request.headers
17
+ end
18
+
19
+ def vcr_response_from(response)
20
+ VCR::Response.new \
21
+ VCR::ResponseStatus.new(response.code, response.status_message),
22
+ response.headers_hash,
23
+ response.body,
24
+ response.http_version
25
+ end
26
+ end
27
+
28
+ class RequestHandler < ::VCR::RequestHandler
29
+ include Helpers
30
+
31
+ attr_reader :request
32
+ def initialize(request)
33
+ @request = request
34
+ end
35
+
36
+ private
37
+
38
+ def on_stubbed_request
39
+ hydra_mock
40
+ end
41
+
42
+ def vcr_request
43
+ @vcr_request ||= vcr_request_from(request)
44
+ end
45
+
46
+ def typhoeus_response
47
+ @typhoeus_response ||= ::Typhoeus::Response.new \
48
+ :http_version => stubbed_response.http_version,
49
+ :code => stubbed_response.status.code,
50
+ :status_message => stubbed_response.status.message,
51
+ :headers_hash => stubbed_response_headers,
52
+ :body => stubbed_response.body
53
+ end
54
+
55
+ def hydra_mock
56
+ @hydra_mock ||= ::Typhoeus::HydraMock.new(/.*/, :any).tap do |m|
57
+ m.and_return(typhoeus_response)
58
+ end
59
+ end
60
+
61
+ def stubbed_response_headers
62
+ @stubbed_response_headers ||= {}.tap do |hash|
63
+ stubbed_response.headers.each do |key, values|
64
+ hash[key] = values.size == 1 ? values.first : values
65
+ end if stubbed_response.headers
66
+ end
67
+ end
68
+ end
69
+
70
+ extend Helpers
71
+ ::Typhoeus::Hydra.after_request_before_on_complete do |request|
72
+ unless VCR.library_hooks.disabled?(:typhoeus) || request.response.mock?
73
+ http_interaction = VCR::HTTPInteraction.new(vcr_request_from(request), vcr_response_from(request.response))
74
+ VCR.record_http_interaction(http_interaction)
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+
82
+ # TODO: add Typhoeus::Hydra.register_stub_finder API to Typhoeus
83
+ # so we can use that instead of monkey-patching it.
84
+ Typhoeus::Hydra::Stubbing::SharedMethods.class_eval do
85
+ undef find_stub_from_request
86
+ def find_stub_from_request(request)
87
+ VCR::LibraryHooks::Typhoeus::RequestHandler.new(request).handle
88
+ end
89
+ end
90
+
91
+ VCR.configuration.after_library_hooks_loaded do
92
+ # ensure WebMock's Typhoeus adapter does not conflict with us here
93
+ # (i.e. to double record requests or whatever).
94
+ if defined?(WebMock::HttpLibAdapters::TyphoeusAdapter)
95
+ WebMock::HttpLibAdapters::TyphoeusAdapter.disable!
96
+ end
97
+ end
98
+
@@ -0,0 +1,100 @@
1
+ require 'vcr/util/version_checker'
2
+ require 'vcr/request_handler'
3
+ require 'webmock'
4
+
5
+ VCR::VersionChecker.new('WebMock', WebMock.version, '1.7.0', '1.7').check_version!
6
+
7
+ module VCR
8
+ class LibraryHooks
9
+ module WebMock
10
+ module Helpers
11
+ def response_hash_for(response)
12
+ {
13
+ :body => response.body,
14
+ :status => [response.status.code.to_i, response.status.message],
15
+ :headers => response.headers
16
+ }
17
+ end
18
+
19
+ def vcr_request_from(webmock_request)
20
+ VCR::Request.new \
21
+ webmock_request.method,
22
+ webmock_request.uri.to_s,
23
+ webmock_request.body,
24
+ webmock_request.headers
25
+ end
26
+
27
+ def vcr_response_from(response)
28
+ VCR::Response.new \
29
+ VCR::ResponseStatus.new(response.status.first, response.status.last),
30
+ response.headers,
31
+ response.body,
32
+ '1.1'
33
+ end
34
+ end
35
+
36
+ class RequestHandler < ::VCR::RequestHandler
37
+ include Helpers
38
+
39
+ attr_reader :request
40
+ def initialize(request)
41
+ @request = request
42
+ end
43
+
44
+ private
45
+
46
+ def stubbed_response
47
+ VCR.http_interactions.has_interaction_matching?(vcr_request)
48
+ end
49
+
50
+ def vcr_request
51
+ @vcr_request ||= vcr_request_from(request)
52
+ end
53
+
54
+ def on_ignored_request; false; end
55
+ def on_stubbed_request; true; end
56
+ def on_recordable_request; false; end
57
+ end
58
+
59
+ extend Helpers
60
+
61
+ GLOBAL_VCR_HOOK = ::WebMock::RequestStub.new(:any, /.*/).tap do |stub|
62
+ stub.with { |request|
63
+ RequestHandler.new(request).handle
64
+ }.to_return(lambda { |request|
65
+ response_hash_for VCR.http_interactions.response_for(vcr_request_from(request))
66
+ })
67
+ end
68
+
69
+ ::WebMock::StubRegistry.instance.register_request_stub(GLOBAL_VCR_HOOK)
70
+
71
+ ::WebMock.after_request(:real_requests_only => true) do |request, response|
72
+ unless VCR.library_hooks.disabled?(:webmock)
73
+ http_interaction = VCR::HTTPInteraction.new \
74
+ vcr_request_from(request),
75
+ vcr_response_from(response)
76
+
77
+ VCR.record_http_interaction(http_interaction)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ class << WebMock
85
+ # ensure HTTP requests are always allowed; VCR takes care of disallowing
86
+ # them at the appropriate times in its hook
87
+ undef net_connect_allowed?
88
+ def net_connect_allowed?(*args)
89
+ true
90
+ end
91
+ end
92
+
93
+ WebMock::StubRegistry.class_eval do
94
+ # ensure our VCR hook is not removed when WebMock is reset
95
+ undef reset!
96
+ def reset!
97
+ self.request_stubs = [VCR::LibraryHooks::WebMock::GLOBAL_VCR_HOOK]
98
+ end
99
+ end
100
+
@@ -1,55 +1,41 @@
1
1
  require 'faraday'
2
+ require 'vcr/util/version_checker'
3
+ require 'vcr/request_handler'
4
+
5
+ VCR::VersionChecker.new('Faraday', Faraday::VERSION, '0.7.0', '0.7').check_version!
2
6
 
3
7
  module VCR
4
8
  module Middleware
5
- class Faraday < ::Faraday::Middleware
6
- include Common
9
+ class Faraday
10
+ include VCR::Deprecations::Middleware::Faraday
7
11
 
8
- class HttpConnectionNotAllowedError < StandardError; end
12
+ def initialize(app)
13
+ super
14
+ @app = app
15
+ end
9
16
 
10
17
  def call(env)
11
- VCR::HttpStubbingAdapters::Faraday.exclusively_enabled do
12
- VCR.use_cassette(*cassette_arguments(env)) do |cassette|
13
- request = request_for(env)
14
-
15
- if VCR::HttpStubbingAdapters::Faraday.uri_should_be_ignored?(request.uri)
16
- @app.call(env)
17
- elsif response = VCR::HttpStubbingAdapters::Faraday.stubbed_response_for(request)
18
- headers = env[:response_headers] ||= ::Faraday::Utils::Headers.new
19
- headers.update response.headers if response.headers
20
- env.update :status => response.status.code, :body => response.body
21
-
22
- faraday_response = ::Faraday::Response.new
23
- faraday_response.finish(env) unless env[:parallel_manager]
24
- env[:response] = faraday_response
25
- elsif VCR::HttpStubbingAdapters::Faraday.http_connections_allowed?
26
- response = @app.call(env)
27
-
28
- # Checking #enabled? isn't strictly needed, but conforms
29
- # the Faraday adapter to the behavior of the other adapters
30
- if VCR::HttpStubbingAdapters::Faraday.enabled?
31
- VCR.record_http_interaction(VCR::HTTPInteraction.new(request, response_for(env)))
32
- end
33
-
34
- response
35
- else
36
- raise HttpConnectionNotAllowedError.new(
37
- "Real HTTP connections are disabled. Request: #{request.method.inspect} #{request.uri}"
38
- )
39
- end
40
- end
18
+ # Faraday must be exlusive here in case another library hook is being used.
19
+ # We don't want double recording/double playback.
20
+ VCR.library_hooks.exclusively_enabled(:faraday) do
21
+ RequestHandler.new(@app, env).handle
41
22
  end
42
23
  end
43
24
 
25
+ class RequestHandler < ::VCR::RequestHandler
26
+ attr_reader :app, :env
27
+ def initialize(app, env)
28
+ @app, @env = app, env
29
+ end
30
+
44
31
  private
45
32
 
46
- def request_for(env)
47
- VCR::Request.new(
33
+ def vcr_request
34
+ @vcr_request ||= VCR::Request.new \
48
35
  env[:method],
49
36
  env[:url].to_s,
50
37
  env[:body],
51
38
  env[:request_headers]
52
- )
53
39
  end
54
40
 
55
41
  def response_for(env)
@@ -62,6 +48,27 @@ module VCR
62
48
  '1.1'
63
49
  )
64
50
  end
51
+
52
+ def on_ignored_request
53
+ app.call(env)
54
+ end
55
+
56
+ def on_stubbed_request
57
+ headers = env[:response_headers] ||= ::Faraday::Utils::Headers.new
58
+ headers.update stubbed_response.headers if stubbed_response.headers
59
+ env.update :status => stubbed_response.status.code, :body => stubbed_response.body
60
+
61
+ faraday_response = ::Faraday::Response.new
62
+ faraday_response.finish(env) unless env[:parallel_manager]
63
+ env[:response] = faraday_response
64
+ end
65
+
66
+ def on_recordable_request
67
+ app.call(env).on_complete do |env|
68
+ VCR.record_http_interaction(VCR::HTTPInteraction.new(vcr_request, response_for(env)))
69
+ end
70
+ end
71
+ end
65
72
  end
66
73
  end
67
74
  end
@@ -1,11 +1,27 @@
1
1
  module VCR
2
2
  module Middleware
3
+ class CassetteArguments
4
+ def initialize
5
+ @name = nil
6
+ @options = {}
7
+ end
8
+
9
+ def name(name = nil)
10
+ @name = name if name
11
+ @name
12
+ end
13
+
14
+ def options(options = {})
15
+ @options.merge!(options)
16
+ end
17
+ end
18
+
3
19
  class Rack
4
- include Common
20
+ include VCR::VariableArgsBlockCaller
5
21
 
6
- def initialize(*args)
7
- @mutex = Mutex.new
8
- super
22
+ def initialize(app, &block)
23
+ raise ArgumentError.new("You must provide a block to set the cassette options") unless block
24
+ @app, @cassette_arguments_block, @mutex = app, block, Mutex.new
9
25
  end
10
26
 
11
27
  def call(env)
@@ -15,6 +31,14 @@ module VCR
15
31
  end
16
32
  end
17
33
  end
34
+
35
+ private
36
+
37
+ def cassette_arguments(env)
38
+ arguments = CassetteArguments.new
39
+ call_block(@cassette_arguments_block, arguments, env)
40
+ [arguments.name, arguments.options]
41
+ end
18
42
  end
19
43
  end
20
44
  end
@@ -0,0 +1,43 @@
1
+ module VCR
2
+ class RequestHandler
3
+ def handle
4
+ return on_ignored_request if should_ignore?
5
+ return on_stubbed_request if stubbed_response
6
+ return on_recordable_request if VCR.real_http_connections_allowed?
7
+ on_connection_not_allowed
8
+ end
9
+
10
+ private
11
+
12
+ def should_ignore?
13
+ disabled? || VCR.request_ignorer.ignore?(vcr_request)
14
+ end
15
+
16
+ def disabled?
17
+ VCR.library_hooks.disabled?(library_name)
18
+ end
19
+
20
+ def stubbed_response
21
+ @stubbed_response ||= VCR.http_interactions.response_for(vcr_request)
22
+ end
23
+
24
+ def library_name
25
+ # extracts `:typhoeus` from `VCR::LibraryHooks::Typhoeus::RequestHandler`
26
+ @library_name ||= self.class.name.split('::')[-2].downcase.to_sym
27
+ end
28
+
29
+ # Subclasses can implement these
30
+ def on_ignored_request
31
+ end
32
+
33
+ def on_stubbed_request
34
+ end
35
+
36
+ def on_recordable_request
37
+ end
38
+
39
+ def on_connection_not_allowed
40
+ raise VCR::HTTPConnectionNotAllowedError.new(vcr_request)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,31 @@
1
+ require 'uri'
2
+ require 'set'
3
+
4
+ module VCR
5
+ class RequestIgnorer
6
+ LOCALHOST_ALIASES = %w( localhost 127.0.0.1 0.0.0.0 )
7
+
8
+ def ignore_localhost=(value)
9
+ if value
10
+ ignore_hosts(*LOCALHOST_ALIASES)
11
+ else
12
+ ignored_hosts.reject! { |h| LOCALHOST_ALIASES.include?(h) }
13
+ end
14
+ end
15
+
16
+ def ignore_hosts(*hosts)
17
+ ignored_hosts.merge(hosts)
18
+ end
19
+
20
+ def ignore?(request)
21
+ ignored_hosts.include?(URI(request.uri).host)
22
+ end
23
+
24
+ private
25
+
26
+ def ignored_hosts
27
+ @ignored_hosts ||= Set.new
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,86 @@
1
+ module VCR
2
+ class RequestMatcherRegistry
3
+ DEFAULT_MATCHERS = [:method, :uri]
4
+
5
+ class Matcher < Struct.new(:callable)
6
+ def matches?(request_1, request_2)
7
+ callable.call(request_1, request_2)
8
+ end
9
+ end
10
+
11
+ def initialize
12
+ @registry = {}
13
+ register_built_ins
14
+ end
15
+
16
+ def register(name, &block)
17
+ if @registry.has_key?(name)
18
+ warn "WARNING: There is already a VCR request matcher registered for #{name.inspect}. Overriding it."
19
+ end
20
+
21
+ @registry[name] = Matcher.new(block)
22
+ end
23
+
24
+ def [](matcher)
25
+ @registry.fetch(matcher) do
26
+ matcher.respond_to?(:call) ?
27
+ Matcher.new(matcher) :
28
+ raise_unregistered_matcher_error(matcher)
29
+ end
30
+ end
31
+
32
+ def uri_without_params(*ignores)
33
+ ignores = ignores.map { |i| i.to_s }
34
+
35
+ lambda do |request_1, request_2|
36
+ uri_1, uri_2 = [request_1, request_2].map do |r|
37
+ URI(r.uri).tap do |uri|
38
+ uri.query = uri.query.split('&').tap { |params|
39
+ params.map! do |p|
40
+ key, value = p.split('=')
41
+ key.gsub!(/\[\]\z/, '') # handle params like tag[]=
42
+ [key, value]
43
+ end
44
+
45
+ params.reject! { |p| ignores.include?(p.first) }
46
+ params.map! { |p| p.join('=') }
47
+ }.join('&')
48
+ end
49
+ end
50
+
51
+ uri_1 == uri_2
52
+ end
53
+ end
54
+ alias uri_without_param uri_without_params
55
+
56
+ private
57
+
58
+ def raise_unregistered_matcher_error(name)
59
+ raise Errors::UnregisteredMatcherError.new \
60
+ "There is no matcher registered for #{name.inspect}. " +
61
+ "Did you mean one of #{@registry.keys.map(&:inspect).join(', ')}?"
62
+ end
63
+
64
+ def register_built_ins
65
+ register(:method) { |r1, r2| r1.method == r2.method }
66
+ register(:uri) { |r1, r2| normalize_uri(r1.uri) == normalize_uri(r2.uri) }
67
+ register(:host) { |r1, r2| URI(r1.uri).host == URI(r2.uri).host }
68
+ register(:path) { |r1, r2| URI(r1.uri).path == URI(r2.uri).path }
69
+ register(:body) { |r1, r2| r1.body == r2.body }
70
+ register(:headers) { |r1, r2| r1.headers == r2.headers }
71
+ end
72
+
73
+ def normalize_uri(uri)
74
+ # TODO: find a better, less-hacky way to do this.
75
+ if defined?(::WebMock)
76
+ ::WebMock::Util::URI.normalize_uri(uri).to_s
77
+ elsif defined?(VCR::Middleware::Faraday)
78
+ # Faraday normalizes URIs by replacing '+' with '%20'
79
+ uri.gsub('+', '%20')
80
+ else
81
+ uri
82
+ end
83
+ end
84
+ end
85
+ end
86
+