vcr 2.0.0.rc1 → 2.0.0.rc2

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.
Files changed (113) hide show
  1. data/.gitignore +2 -0
  2. data/.limited_red +1 -0
  3. data/.travis.yml +10 -1
  4. data/.yardopts +9 -0
  5. data/CHANGELOG.md +51 -1
  6. data/Gemfile +5 -1
  7. data/LICENSE +1 -1
  8. data/README.md +23 -28
  9. data/Rakefile +63 -18
  10. data/Upgrade.md +200 -0
  11. data/features/.nav +2 -0
  12. data/features/cassettes/automatic_re_recording.feature +19 -15
  13. data/features/cassettes/dynamic_erb.feature +12 -4
  14. data/features/cassettes/exclusive.feature +31 -23
  15. data/features/cassettes/format.feature +54 -30
  16. data/features/cassettes/naming.feature +1 -1
  17. data/features/cassettes/update_content_length_header.feature +16 -12
  18. data/features/configuration/allow_http_connections_when_no_cassette.feature +1 -1
  19. data/features/configuration/debug_logging.feature +52 -0
  20. data/features/configuration/filter_sensitive_data.feature +4 -4
  21. data/features/configuration/hook_into.feature +5 -2
  22. data/features/configuration/ignore_request.feature +5 -3
  23. data/features/configuration/preserve_exact_body_bytes.feature +103 -0
  24. data/features/hooks/after_http_request.feature +17 -4
  25. data/features/hooks/around_http_request.feature +2 -1
  26. data/features/hooks/before_http_request.feature +25 -8
  27. data/features/hooks/before_playback.feature +16 -12
  28. data/features/hooks/before_record.feature +2 -2
  29. data/features/http_libraries/em_http_request.feature +82 -58
  30. data/features/http_libraries/net_http.feature +6 -6
  31. data/features/middleware/faraday.feature +2 -1
  32. data/features/middleware/rack.feature +2 -2
  33. data/features/record_modes/all.feature +19 -15
  34. data/features/record_modes/new_episodes.feature +17 -13
  35. data/features/record_modes/none.feature +15 -11
  36. data/features/record_modes/once.feature +16 -12
  37. data/features/request_matching/body.feature +28 -20
  38. data/features/request_matching/custom_matcher.feature +28 -20
  39. data/features/request_matching/headers.feature +34 -26
  40. data/features/request_matching/host.feature +28 -20
  41. data/features/request_matching/identical_request_sequence.feature +28 -20
  42. data/features/request_matching/method.feature +28 -20
  43. data/features/request_matching/path.feature +28 -20
  44. data/features/request_matching/playback_repeats.feature +28 -20
  45. data/features/request_matching/uri.feature +28 -20
  46. data/features/request_matching/uri_without_param.feature +28 -20
  47. data/features/support/env.rb +7 -6
  48. data/features/support/vcr_cucumber_helpers.rb +1 -0
  49. data/features/test_frameworks/cucumber.feature +8 -8
  50. data/features/test_frameworks/rspec_macro.feature +4 -4
  51. data/features/test_frameworks/rspec_metadata.feature +6 -6
  52. data/features/test_frameworks/shoulda.feature +1 -1
  53. data/features/test_frameworks/test_unit.feature +1 -1
  54. data/lib/vcr.rb +156 -5
  55. data/lib/vcr/cassette.rb +80 -30
  56. data/lib/vcr/cassette/http_interaction_list.rb +33 -4
  57. data/lib/vcr/cassette/migrator.rb +2 -3
  58. data/lib/vcr/cassette/reader.rb +1 -0
  59. data/lib/vcr/cassette/serializers.rb +22 -0
  60. data/lib/vcr/cassette/serializers/json.rb +27 -2
  61. data/lib/vcr/cassette/serializers/psych.rb +26 -2
  62. data/lib/vcr/cassette/serializers/syck.rb +28 -2
  63. data/lib/vcr/cassette/serializers/yaml.rb +28 -2
  64. data/lib/vcr/configuration.rb +348 -10
  65. data/lib/vcr/deprecations.rb +8 -0
  66. data/lib/vcr/errors.rb +40 -0
  67. data/lib/vcr/extensions/net_http_response.rb +12 -11
  68. data/lib/vcr/library_hooks.rb +1 -0
  69. data/lib/vcr/library_hooks/excon.rb +24 -3
  70. data/lib/vcr/library_hooks/fakeweb.rb +32 -16
  71. data/lib/vcr/library_hooks/faraday.rb +3 -0
  72. data/lib/vcr/library_hooks/typhoeus.rb +40 -37
  73. data/lib/vcr/library_hooks/webmock.rb +54 -34
  74. data/lib/vcr/middleware/faraday.rb +13 -0
  75. data/lib/vcr/middleware/rack.rb +35 -0
  76. data/lib/vcr/request_handler.rb +60 -8
  77. data/lib/vcr/request_ignorer.rb +1 -0
  78. data/lib/vcr/request_matcher_registry.rb +28 -0
  79. data/lib/vcr/structs.rb +245 -38
  80. data/lib/vcr/test_frameworks/cucumber.rb +10 -0
  81. data/lib/vcr/test_frameworks/rspec.rb +26 -1
  82. data/lib/vcr/util/hooks.rb +29 -27
  83. data/lib/vcr/util/internet_connection.rb +2 -0
  84. data/lib/vcr/util/logger.rb +25 -0
  85. data/lib/vcr/util/variable_args_block_caller.rb +1 -0
  86. data/lib/vcr/util/version_checker.rb +1 -0
  87. data/lib/vcr/version.rb +8 -1
  88. data/spec/capture_warnings.rb +3 -3
  89. data/spec/monkey_patches.rb +28 -13
  90. data/spec/spec_helper.rb +17 -0
  91. data/spec/support/http_library_adapters.rb +7 -4
  92. data/spec/support/shared_example_groups/hook_into_http_library.rb +96 -32
  93. data/spec/support/shared_example_groups/request_hooks.rb +9 -8
  94. data/spec/support/sinatra_app.rb +3 -1
  95. data/spec/support/vcr_localhost_server.rb +1 -0
  96. data/spec/vcr/cassette/http_interaction_list_spec.rb +119 -54
  97. data/spec/vcr/cassette/migrator_spec.rb +19 -6
  98. data/spec/vcr/cassette/serializers_spec.rb +51 -6
  99. data/spec/vcr/cassette_spec.rb +44 -19
  100. data/spec/vcr/configuration_spec.rb +91 -6
  101. data/spec/vcr/library_hooks/excon_spec.rb +54 -16
  102. data/spec/vcr/library_hooks/fakeweb_spec.rb +12 -21
  103. data/spec/vcr/library_hooks/typhoeus_spec.rb +2 -29
  104. data/spec/vcr/library_hooks/webmock_spec.rb +4 -18
  105. data/spec/vcr/middleware/faraday_spec.rb +1 -16
  106. data/spec/vcr/structs_spec.rb +194 -61
  107. data/spec/vcr/test_frameworks/rspec_spec.rb +10 -0
  108. data/spec/vcr/util/hooks_spec.rb +104 -56
  109. data/spec/vcr/util/version_checker_spec.rb +45 -0
  110. data/spec/vcr_spec.rb +11 -0
  111. data/vcr.gemspec +30 -34
  112. metadata +149 -95
  113. data/spec/support/shared_example_groups/version_checking.rb +0 -34
@@ -1,15 +1,19 @@
1
1
  module VCR
2
+ # @deprecated Use #configure instead.
3
+ # @see #configure
2
4
  def config
3
5
  warn "WARNING: `VCR.config` is deprecated. Use VCR.configure instead."
4
6
  configure { |c| yield c }
5
7
  end
6
8
 
9
+ # @private
7
10
  def self.const_missing(const)
8
11
  return super unless const == :Config
9
12
  warn "WARNING: `VCR::Config` is deprecated. Use VCR.configuration instead."
10
13
  configuration
11
14
  end
12
15
 
16
+ # @private
13
17
  def Cassette.const_missing(const)
14
18
  return super unless const == :MissingERBVariableError
15
19
  warn "WARNING: `VCR::Cassette::MissingERBVariableError` is deprecated. Use `VCR::Errors::MissingERBVariableError` instead."
@@ -17,14 +21,18 @@ module VCR
17
21
  end
18
22
 
19
23
  class Configuration
24
+ # @deprecated Use #hook_into instead.
25
+ # @see #hook_into
20
26
  def stub_with(*adapters)
21
27
  warn "WARNING: `VCR.config { |c| c.stub_with ... }` is deprecated. Use `VCR.configure { |c| c.hook_into ... }` instead."
22
28
  hook_into(*adapters)
23
29
  end
24
30
  end
25
31
 
32
+ # @private
26
33
  module Deprecations
27
34
  module Middleware
35
+ # @private
28
36
  module Faraday
29
37
  def initialize(*args)
30
38
  if block_given?
data/lib/vcr/errors.rb CHANGED
@@ -1,18 +1,57 @@
1
1
  module VCR
2
+ # Namespace for VCR errors.
2
3
  module Errors
4
+ # Base class for all VCR errors.
3
5
  class Error < StandardError; end
6
+
7
+ # Error raised when VCR is turned off while a cassette is in use.
8
+ # @see VCR#turn_off!
9
+ # @see VCR#turned_off
4
10
  class CassetteInUseError < Error; end
11
+
12
+ # Error raised when a VCR cassette is inserted while VCR is turned off.
13
+ # @see VCR#insert_cassette
14
+ # @see VCR#use_cassette
5
15
  class TurnedOffError < Error; end
16
+
17
+ # Error raised when an cassette ERB template is rendered and a
18
+ # variable is missing.
19
+ # @see VCR#insert_cassette
20
+ # @see VCR#use_cassette
6
21
  class MissingERBVariableError < Error; end
22
+
23
+ # Error raised when the version of one of the libraries that VCR hooks into
24
+ # is too low for VCR to support.
25
+ # @see VCR::Configuration#hook_into
7
26
  class LibraryVersionTooLowError < Error; end
27
+
28
+ # Error raised when a request matcher is requested that is not registered.
8
29
  class UnregisteredMatcherError < Error; end
30
+
31
+ # Error raised when a VCR 1.x cassette is used with VCR 2.
9
32
  class InvalidCassetteFormatError < Error; end
33
+
34
+ # Error raised when an +around_http_request+ hook is used improperly.
35
+ # @see VCR::Configuration#around_http_request
10
36
  class AroundHTTPRequestHookError < Error; end
37
+
38
+ # Error raised when you attempt to use a VCR feature that is not
39
+ # supported on your ruby interpreter.
40
+ # @see VCR::Configuration#around_http_request
11
41
  class NotSupportedError < Error; end
12
42
 
43
+ # Error raised when an HTTP request is made that VCR is unable to handle.
44
+ # @note VCR will raise this to force you to do something about the
45
+ # HTTP request. The idea is that you want to handle _every_ HTTP
46
+ # request in your test suite. The error message will give you
47
+ # suggestions for how to deal with the request.
13
48
  class UnhandledHTTPRequestError < Error
49
+ # The HTTP request.
14
50
  attr_reader :request
15
51
 
52
+ # Constructs the error.
53
+ #
54
+ # @param [VCR::Request] request the unhandled request.
16
55
  def initialize(request)
17
56
  @request = request
18
57
  super construct_message
@@ -77,6 +116,7 @@ module VCR
77
116
  "[#{index + 1}] #{url % relish_version_slug}"
78
117
  end
79
118
 
119
+ # List of suggestions for how to configure VCR to handle the request.
80
120
  ALL_SUGGESTIONS = {
81
121
  :use_new_episodes => [
82
122
  ["You can use the :new_episodes record mode to allow VCR to",
@@ -1,16 +1,17 @@
1
- # A Net::HTTP response that has already been read raises an IOError when #read_body
2
- # is called with a destination string or block.
3
- #
4
- # This causes a problem when VCR records a response--it reads the body before yielding
5
- # the response, and if the code that is consuming the HTTP requests uses #read_body, it
6
- # can cause an error.
7
- #
8
- # This is a bit of a hack, but it allows a Net::HTTP response to be "re-read"
9
- # after it has aleady been read. This attemps to preserve the behavior of
10
- # #read_body, acting just as if it had never been read.
11
-
12
1
  module VCR
2
+ # @private
13
3
  module Net
4
+ # A Net::HTTP response that has already been read raises an IOError when #read_body
5
+ # is called with a destination string or block.
6
+ #
7
+ # This causes a problem when VCR records a response--it reads the body before yielding
8
+ # the response, and if the code that is consuming the HTTP requests uses #read_body, it
9
+ # can cause an error.
10
+ #
11
+ # This is a bit of a hack, but it allows a Net::HTTP response to be "re-read"
12
+ # after it has aleady been read. This attemps to preserve the behavior of
13
+ # #read_body, acting just as if it had never been read.
14
+ # @private
14
15
  module HTTPResponse
15
16
  def self.extended(response)
16
17
  response.instance_variable_set(:@__read_body_previously_called, false)
@@ -1,4 +1,5 @@
1
1
  module VCR
2
+ # @private
2
3
  class LibraryHooks
3
4
  attr_accessor :exclusive_hook
4
5
 
@@ -2,10 +2,11 @@ require 'vcr/util/version_checker'
2
2
  require 'vcr/request_handler'
3
3
  require 'excon'
4
4
 
5
- VCR::VersionChecker.new('Excon', Excon::VERSION, '0.6.5', '0.7').check_version!
5
+ VCR::VersionChecker.new('Excon', Excon::VERSION, '0.9.6', '0.9').check_version!
6
6
 
7
7
  module VCR
8
8
  class LibraryHooks
9
+ # @private
9
10
  module Excon
10
11
  class RequestHandler < ::VCR::RequestHandler
11
12
  attr_reader :params
@@ -45,9 +46,21 @@ module VCR
45
46
  end
46
47
  end
47
48
 
49
+ def real_request_params
50
+ # Excon supports a variety of options that affect how it handles failure
51
+ # and retry; we don't want to use any options here--we just want to get
52
+ # a raw response, and then the main request (with :mock => true) can
53
+ # handle failure/retry on its own with its set options.
54
+ params.merge(:mock => false, :retry_limit => 0).tap do |p|
55
+ [:expects, :idempotent, :instrumentor_name, :instrumentor].each do |key|
56
+ p.delete(key)
57
+ end
58
+ end
59
+ end
60
+
48
61
  def perform_real_request
49
62
  begin
50
- response = ::Excon.new(uri).request(params.merge(:mock => false))
63
+ response = ::Excon.new(uri).request(real_request_params)
51
64
  rescue ::Excon::Errors::Error => excon_error
52
65
  response = response_from_excon_error(excon_error)
53
66
  end
@@ -138,5 +151,13 @@ module VCR
138
151
  end
139
152
  end
140
153
 
141
- Excon.mock = true
154
+ Excon.defaults[:mock] = true
155
+
156
+ VCR.configuration.after_library_hooks_loaded do
157
+ # ensure WebMock's Excon adapter does not conflict with us here
158
+ # (i.e. to double record requests or whatever).
159
+ if defined?(WebMock::HttpLibAdapters::ExconAdapter)
160
+ WebMock::HttpLibAdapters::ExconAdapter.disable!
161
+ end
162
+ end
142
163
 
@@ -9,13 +9,21 @@ VCR::VersionChecker.new('FakeWeb', FakeWeb::VERSION, '1.3.0', '1.3').check_versi
9
9
 
10
10
  module VCR
11
11
  class LibraryHooks
12
+ # @private
12
13
  module FakeWeb
14
+ # @private
13
15
  class RequestHandler < ::VCR::RequestHandler
14
16
  attr_reader :net_http, :request, :request_body, :response_block
15
17
  def initialize(net_http, request, request_body = nil, &response_block)
16
18
  @net_http, @request, @request_body, @response_block =
17
19
  net_http, request, request_body, response_block
18
20
  @vcr_response, @recursing = nil, false
21
+
22
+ if ([:@__vcr_request_type, "@__vcr_request_type"] & request.instance_variables).any?
23
+ @request_type = request.instance_variable_get(:@__vcr_request_type)
24
+ else
25
+ @request_type = nil
26
+ end
19
27
  end
20
28
 
21
29
  def handle
@@ -32,6 +40,15 @@ module VCR
32
40
 
33
41
  private
34
42
 
43
+ def request_type(*args)
44
+ @request_type || super
45
+ end
46
+
47
+ def set_typed_request_for_after_hook(request_type)
48
+ @request.instance_variable_set(:@__vcr_request_type, request_type)
49
+ super
50
+ end
51
+
35
52
  def invoke_before_request_hook
36
53
  unless self.class.already_seen_requests.include?(request.object_id)
37
54
  super
@@ -63,12 +80,6 @@ module VCR
63
80
  perform_request(net_http.started?)
64
81
  end
65
82
 
66
- # overriden to prevent it from invoking the after_http_request hook,
67
- # since we invoke the hook in an ensure block above.
68
- def on_connection_not_allowed
69
- raise VCR::Errors::UnhandledHTTPRequestError.new(vcr_request)
70
- end
71
-
72
83
  def perform_request(started, record_interaction = false)
73
84
  # Net::HTTP calls #request recursively in certain circumstances.
74
85
  # We only want to record the request when the request is started, as
@@ -117,7 +128,7 @@ module VCR
117
128
  @vcr_request ||= VCR::Request.new \
118
129
  request.method.downcase.to_sym,
119
130
  uri,
120
- request_body,
131
+ (request_body || request.body),
121
132
  request.to_hash
122
133
  end
123
134
 
@@ -133,7 +144,9 @@ module VCR
133
144
  end
134
145
  end
135
146
 
147
+ # @private
136
148
  module Net
149
+ # @private
137
150
  class HTTP
138
151
  unless method_defined?(:request_with_vcr)
139
152
  def request_with_vcr(*args, &block)
@@ -152,16 +165,19 @@ module Net
152
165
  end
153
166
  end
154
167
 
155
- class << FakeWeb
156
- # ensure HTTP requests are always allowed; VCR takes care of disallowing
157
- # them at the appropriate times in its hook
158
- def allow_net_connect_with_vcr?(*args)
159
- VCR.turned_on? ? true : allow_net_connect_without_vcr?
160
- end
168
+ # @private
169
+ module FakeWeb
170
+ class << self
171
+ # ensure HTTP requests are always allowed; VCR takes care of disallowing
172
+ # them at the appropriate times in its hook
173
+ def allow_net_connect_with_vcr?(*args)
174
+ VCR.turned_on? ? true : allow_net_connect_without_vcr?
175
+ end
161
176
 
162
- alias allow_net_connect_without_vcr? allow_net_connect?
163
- alias allow_net_connect? allow_net_connect_with_vcr?
164
- end unless FakeWeb.respond_to?(:allow_net_connect_with_vcr?)
177
+ alias allow_net_connect_without_vcr? allow_net_connect?
178
+ alias allow_net_connect? allow_net_connect_with_vcr?
179
+ end unless respond_to?(:allow_net_connect_with_vcr?)
180
+ end
165
181
 
166
182
  VCR.configuration.after_library_hooks_loaded do
167
183
  if defined?(WebMock)
@@ -2,7 +2,9 @@ require 'faraday'
2
2
 
3
3
  module VCR
4
4
  class LibraryHooks
5
+ # @private
5
6
  module Faraday
7
+ # @private
6
8
  module BuilderClassExtension
7
9
  def new(*args)
8
10
  super.extend BuilderInstanceExtension
@@ -11,6 +13,7 @@ module VCR
11
13
  ::Faraday::Builder.extend self
12
14
  end
13
15
 
16
+ # @private
14
17
  module BuilderInstanceExtension
15
18
  def lock!(*args)
16
19
  insert_vcr_middleware
@@ -6,42 +6,33 @@ VCR::VersionChecker.new('Typhoeus', Typhoeus::VERSION, '0.3.2', '0.3').check_ver
6
6
 
7
7
  module VCR
8
8
  class LibraryHooks
9
+ # @private
9
10
  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
-
11
+ # @private
28
12
  class RequestHandler < ::VCR::RequestHandler
29
- include Helpers
30
-
31
13
  attr_reader :request
32
14
  def initialize(request)
33
15
  @request = request
34
16
  end
35
17
 
18
+ def vcr_request
19
+ @vcr_request ||= VCR::Request.new \
20
+ request.method,
21
+ request.url,
22
+ request.body,
23
+ request.headers
24
+ end
25
+
36
26
  private
37
27
 
38
- def on_connection_not_allowed
39
- invoke_after_request_hook(nil)
28
+ def set_typed_request_for_after_hook(*args)
40
29
  super
30
+ request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
41
31
  end
42
32
 
43
- def vcr_request
44
- @vcr_request ||= vcr_request_from(request)
33
+ def on_unhandled_request
34
+ invoke_after_request_hook(nil)
35
+ super
45
36
  end
46
37
 
47
38
  def on_stubbed_request
@@ -62,17 +53,26 @@ module VCR
62
53
  end
63
54
  end
64
55
 
65
- extend Helpers
56
+ # @private
57
+ def self.vcr_response_from(response)
58
+ VCR::Response.new \
59
+ VCR::ResponseStatus.new(response.code, response.status_message),
60
+ response.headers_hash,
61
+ response.body,
62
+ response.http_version
63
+ end
64
+
66
65
  ::Typhoeus::Hydra.after_request_before_on_complete do |request|
67
66
  unless VCR.library_hooks.disabled?(:typhoeus)
68
- vcr_request, vcr_response = vcr_request_from(request), vcr_response_from(request.response)
67
+ vcr_response = vcr_response_from(request.response)
68
+ typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
69
69
 
70
70
  unless request.response.mock?
71
- http_interaction = VCR::HTTPInteraction.new(vcr_request, vcr_response)
71
+ http_interaction = VCR::HTTPInteraction.new(typed_vcr_request, vcr_response)
72
72
  VCR.record_http_interaction(http_interaction)
73
73
  end
74
74
 
75
- VCR.configuration.invoke_hook(:after_http_request, vcr_request, vcr_response)
75
+ VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response)
76
76
  end
77
77
  end
78
78
 
@@ -83,16 +83,19 @@ module VCR
83
83
  end
84
84
  end
85
85
 
86
- class << Typhoeus::Hydra
87
- # ensure HTTP requests are always allowed; VCR takes care of disallowing
88
- # them at the appropriate times in its hook
89
- def allow_net_connect_with_vcr?(*args)
90
- VCR.turned_on? ? true : allow_net_connect_without_vcr?
91
- end
86
+ # @private
87
+ module Typhoeus
88
+ class << Hydra
89
+ # ensure HTTP requests are always allowed; VCR takes care of disallowing
90
+ # them at the appropriate times in its hook
91
+ def allow_net_connect_with_vcr?(*args)
92
+ VCR.turned_on? ? true : allow_net_connect_without_vcr?
93
+ end
92
94
 
93
- alias allow_net_connect_without_vcr? allow_net_connect?
94
- alias allow_net_connect? allow_net_connect_with_vcr?
95
- end unless Typhoeus::Hydra.respond_to?(:allow_net_connect_with_vcr?)
95
+ alias allow_net_connect_without_vcr? allow_net_connect?
96
+ alias allow_net_connect? allow_net_connect_with_vcr?
97
+ end unless Hydra.respond_to?(:allow_net_connect_with_vcr?)
98
+ end
96
99
 
97
100
  VCR.configuration.after_library_hooks_loaded do
98
101
  # ensure WebMock's Typhoeus adapter does not conflict with us here
@@ -2,31 +2,13 @@ require 'vcr/util/version_checker'
2
2
  require 'vcr/request_handler'
3
3
  require 'webmock'
4
4
 
5
- VCR::VersionChecker.new('WebMock', WebMock.version, '1.7.8', '1.7').check_version!
5
+ VCR::VersionChecker.new('WebMock', WebMock.version, '1.8.0', '1.8').check_version!
6
6
 
7
7
  module VCR
8
8
  class LibraryHooks
9
+ # @private
9
10
  module WebMock
10
- module Helpers
11
- def vcr_request_from(webmock_request)
12
- VCR::Request.new \
13
- webmock_request.method,
14
- webmock_request.uri.to_s,
15
- webmock_request.body,
16
- webmock_request.headers
17
- end
18
-
19
- def vcr_response_from(response)
20
- VCR::Response.new \
21
- VCR::ResponseStatus.new(response.status.first, response.status.last),
22
- response.headers,
23
- response.body,
24
- nil
25
- end
26
- end
27
-
28
11
  class RequestHandler < ::VCR::RequestHandler
29
- include Helpers
30
12
 
31
13
  attr_reader :request
32
14
  def initialize(request)
@@ -35,11 +17,38 @@ module VCR
35
17
 
36
18
  private
37
19
 
20
+ def set_typed_request_for_after_hook(*args)
21
+ super
22
+ request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
23
+ end
24
+
38
25
  def vcr_request
39
- @vcr_request ||= vcr_request_from(request)
26
+ @vcr_request ||= VCR::Request.new \
27
+ request.method,
28
+ request.uri.to_s,
29
+ request.body,
30
+ request_headers
31
+ end
32
+
33
+ if defined?(::Excon)
34
+ # @private
35
+ def request_headers
36
+ return nil unless request.headers
37
+
38
+ # WebMock hooks deeply into a Excon at a place where it manually adds a "Host"
39
+ # header, but this isn't a header we actually care to store...
40
+ request.headers.dup.tap do |headers|
41
+ headers.delete("Host")
42
+ end
43
+ end
44
+ else
45
+ # @private
46
+ def request_headers
47
+ request.headers
48
+ end
40
49
  end
41
50
 
42
- def on_connection_not_allowed
51
+ def on_unhandled_request
43
52
  invoke_after_request_hook(nil)
44
53
  super
45
54
  end
@@ -53,14 +62,21 @@ module VCR
53
62
  end
54
63
  end
55
64
 
56
- extend Helpers
65
+ # @private
66
+ def self.vcr_response_from(response)
67
+ VCR::Response.new \
68
+ VCR::ResponseStatus.new(response.status.first, response.status.last),
69
+ response.headers,
70
+ response.body,
71
+ nil
72
+ end
57
73
 
58
74
  ::WebMock.globally_stub_request { |req| RequestHandler.new(req).handle }
59
75
 
60
76
  ::WebMock.after_request(:real_requests_only => true) do |request, response|
61
77
  unless VCR.library_hooks.disabled?(:webmock)
62
78
  http_interaction = VCR::HTTPInteraction.new \
63
- vcr_request_from(request),
79
+ request.send(:instance_variable_get, :@__typed_vcr_request),
64
80
  vcr_response_from(response)
65
81
 
66
82
  VCR.record_http_interaction(http_interaction)
@@ -69,21 +85,25 @@ module VCR
69
85
 
70
86
  ::WebMock.after_request do |request, response|
71
87
  unless VCR.library_hooks.disabled?(:webmock)
72
- VCR.configuration.invoke_hook(:after_http_request, vcr_request_from(request), vcr_response_from(response))
88
+ typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
89
+ VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response_from(response))
73
90
  end
74
91
  end
75
92
  end
76
93
  end
77
94
  end
78
95
 
79
- class << WebMock
80
- # ensure HTTP requests are always allowed; VCR takes care of disallowing
81
- # them at the appropriate times in its hook
82
- def net_connect_allowed_with_vcr?(*args)
83
- VCR.turned_on? ? true : net_connect_allowed_without_vcr?
84
- end
96
+ # @private
97
+ module WebMock
98
+ class << self
99
+ # ensure HTTP requests are always allowed; VCR takes care of disallowing
100
+ # them at the appropriate times in its hook
101
+ def net_connect_allowed_with_vcr?(*args)
102
+ VCR.turned_on? ? true : net_connect_allowed_without_vcr?
103
+ end
85
104
 
86
- alias net_connect_allowed_without_vcr? net_connect_allowed?
87
- alias net_connect_allowed? net_connect_allowed_with_vcr?
88
- end unless WebMock.respond_to?(:net_connect_allowed_with_vcr?)
105
+ alias net_connect_allowed_without_vcr? net_connect_allowed?
106
+ alias net_connect_allowed? net_connect_allowed_with_vcr?
107
+ end unless respond_to?(:net_connect_allowed_with_vcr?)
108
+ end
89
109