vcr 2.0.0.beta1 → 2.0.0.beta2
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/.gitignore +1 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +37 -2
- data/Gemfile +2 -2
- data/README.md +10 -1
- data/Rakefile +43 -7
- data/Upgrade.md +45 -0
- data/features/.nav +1 -0
- data/features/cassettes/automatic_re_recording.feature +19 -17
- data/features/cassettes/dynamic_erb.feature +32 -28
- data/features/cassettes/exclusive.feature +28 -24
- data/features/cassettes/format.feature +213 -31
- data/features/cassettes/update_content_length_header.feature +20 -18
- data/features/configuration/filter_sensitive_data.feature +4 -4
- data/features/configuration/hooks.feature +27 -23
- data/features/http_libraries/em_http_request.feature +79 -75
- data/features/record_modes/all.feature +14 -14
- data/features/record_modes/new_episodes.feature +15 -15
- data/features/record_modes/none.feature +15 -15
- data/features/record_modes/once.feature +15 -15
- data/features/request_matching/body.feature +25 -23
- data/features/request_matching/custom_matcher.feature +25 -23
- data/features/request_matching/headers.feature +32 -36
- data/features/request_matching/host.feature +27 -25
- data/features/request_matching/identical_request_sequence.feature +27 -25
- data/features/request_matching/method.feature +27 -25
- data/features/request_matching/path.feature +27 -25
- data/features/request_matching/playback_repeats.feature +27 -25
- data/features/request_matching/uri.feature +27 -25
- data/features/request_matching/uri_without_param.feature +28 -26
- data/features/step_definitions/cli_steps.rb +71 -17
- data/features/support/env.rb +3 -1
- data/features/support/http_lib_filters.rb +6 -3
- data/features/support/vcr_cucumber_helpers.rb +4 -2
- data/lib/vcr.rb +6 -2
- data/lib/vcr/cassette.rb +75 -51
- data/lib/vcr/cassette/migrator.rb +111 -0
- data/lib/vcr/cassette/serializers.rb +35 -0
- data/lib/vcr/cassette/serializers/json.rb +23 -0
- data/lib/vcr/cassette/serializers/psych.rb +24 -0
- data/lib/vcr/cassette/serializers/syck.rb +35 -0
- data/lib/vcr/cassette/serializers/yaml.rb +24 -0
- data/lib/vcr/configuration.rb +6 -1
- data/lib/vcr/errors.rb +1 -1
- data/lib/vcr/library_hooks/excon.rb +1 -7
- data/lib/vcr/library_hooks/typhoeus.rb +6 -22
- data/lib/vcr/library_hooks/webmock.rb +1 -1
- data/lib/vcr/middleware/faraday.rb +1 -1
- data/lib/vcr/request_matcher_registry.rb +43 -30
- data/lib/vcr/structs.rb +209 -0
- data/lib/vcr/tasks/vcr.rake +9 -0
- data/lib/vcr/version.rb +1 -1
- data/spec/fixtures/cassette_spec/1_x_cassette.yml +110 -0
- data/spec/fixtures/cassette_spec/example.yml +79 -78
- data/spec/fixtures/cassette_spec/with_localhost_requests.yml +79 -77
- data/spec/fixtures/fake_example.com_responses.yml +78 -76
- data/spec/fixtures/match_requests_on.yml +147 -145
- data/spec/monkey_patches.rb +5 -5
- data/spec/support/http_library_adapters.rb +48 -0
- data/spec/support/shared_example_groups/hook_into_http_library.rb +53 -20
- data/spec/support/sinatra_app.rb +12 -0
- data/spec/vcr/cassette/http_interaction_list_spec.rb +1 -1
- data/spec/vcr/cassette/migrator_spec.rb +183 -0
- data/spec/vcr/cassette/serializers_spec.rb +122 -0
- data/spec/vcr/cassette_spec.rb +147 -83
- data/spec/vcr/configuration_spec.rb +11 -1
- data/spec/vcr/library_hooks/typhoeus_spec.rb +3 -3
- data/spec/vcr/library_hooks/webmock_spec.rb +7 -1
- data/spec/vcr/request_ignorer_spec.rb +1 -1
- data/spec/vcr/request_matcher_registry_spec.rb +46 -4
- data/spec/vcr/structs_spec.rb +309 -0
- data/spec/vcr_spec.rb +7 -0
- data/vcr.gemspec +9 -12
- metadata +75 -61
- data/lib/vcr/structs/http_interaction.rb +0 -58
- data/lib/vcr/structs/normalizers/body.rb +0 -24
- data/lib/vcr/structs/normalizers/header.rb +0 -64
- data/lib/vcr/structs/normalizers/status_message.rb +0 -17
- data/lib/vcr/structs/normalizers/uri.rb +0 -34
- data/lib/vcr/structs/request.rb +0 -13
- data/lib/vcr/structs/response.rb +0 -13
- data/lib/vcr/structs/response_status.rb +0 -5
- data/lib/vcr/util/yaml.rb +0 -11
- data/spec/support/shared_example_groups/normalizers.rb +0 -94
- data/spec/vcr/structs/http_interaction_spec.rb +0 -89
- data/spec/vcr/structs/request_spec.rb +0 -39
- data/spec/vcr/structs/response_spec.rb +0 -44
- data/spec/vcr/structs/response_status_spec.rb +0 -9
data/lib/vcr/structs.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module VCR
|
5
|
+
module Normalizers
|
6
|
+
module Body
|
7
|
+
def initialize(*args)
|
8
|
+
super
|
9
|
+
# Ensure that the body is a raw string, in case the string instance
|
10
|
+
# has been subclassed or extended with additional instance variables
|
11
|
+
# or attributes, so that it is serialized to YAML as a raw string.
|
12
|
+
# This is needed for rest-client. See this ticket for more info:
|
13
|
+
# http://github.com/myronmarston/vcr/issues/4
|
14
|
+
self.body = String.new(body.to_s)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Header
|
19
|
+
def initialize(*args)
|
20
|
+
super
|
21
|
+
normalize_headers
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def normalize_headers
|
27
|
+
new_headers = {}
|
28
|
+
|
29
|
+
headers.each do |k, v|
|
30
|
+
val_array = case v
|
31
|
+
when Array then v
|
32
|
+
when nil then []
|
33
|
+
else [v]
|
34
|
+
end
|
35
|
+
|
36
|
+
new_headers[k] = convert_to_raw_strings(val_array)
|
37
|
+
end if headers
|
38
|
+
|
39
|
+
self.headers = new_headers
|
40
|
+
end
|
41
|
+
|
42
|
+
def convert_to_raw_strings(array)
|
43
|
+
# Ensure the values are raw strings.
|
44
|
+
# Apparently for Paperclip uploads to S3, headers
|
45
|
+
# get serialized with some extra stuff which leads
|
46
|
+
# to a seg fault. See this issue for more info:
|
47
|
+
# https://github.com/myronmarston/vcr/issues#issue/39
|
48
|
+
array.map do |v|
|
49
|
+
case v
|
50
|
+
when String; String.new(v)
|
51
|
+
when Array; convert_to_raw_strings(v)
|
52
|
+
else v
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module OrderedHashSerializer
|
60
|
+
def each
|
61
|
+
@ordered_keys.each do |key|
|
62
|
+
yield key, self[key]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if RUBY_VERSION =~ /1.9/
|
67
|
+
# 1.9 hashes are already ordered.
|
68
|
+
def self.apply_to(*args); end
|
69
|
+
else
|
70
|
+
def self.apply_to(hash, keys)
|
71
|
+
hash.instance_variable_set(:@ordered_keys, keys)
|
72
|
+
hash.extend self
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Request < Struct.new(:method, :uri, :body, :headers)
|
78
|
+
include Normalizers::Header
|
79
|
+
include Normalizers::Body
|
80
|
+
|
81
|
+
def to_hash
|
82
|
+
{
|
83
|
+
'method' => method.to_s,
|
84
|
+
'uri' => uri,
|
85
|
+
'body' => body,
|
86
|
+
'headers' => headers
|
87
|
+
}.tap { |h| OrderedHashSerializer.apply_to(h, members) }
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.from_hash(hash)
|
91
|
+
method = hash['method']
|
92
|
+
method &&= method.to_sym
|
93
|
+
new method,
|
94
|
+
hash['uri'],
|
95
|
+
hash['body'],
|
96
|
+
hash['headers']
|
97
|
+
end
|
98
|
+
|
99
|
+
@@object_method = Object.instance_method(:method)
|
100
|
+
def method(*args)
|
101
|
+
return super if args.empty?
|
102
|
+
@@object_method.bind(self).call(*args)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class HTTPInteraction < Struct.new(:request, :response, :recorded_at)
|
107
|
+
extend ::Forwardable
|
108
|
+
def_delegators :request, :uri, :method
|
109
|
+
|
110
|
+
def initialize(*args)
|
111
|
+
@ignored = false
|
112
|
+
super
|
113
|
+
self.recorded_at ||= Time.now
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_hash
|
117
|
+
{
|
118
|
+
'request' => request.to_hash,
|
119
|
+
'response' => response.to_hash,
|
120
|
+
'recorded_at' => recorded_at.httpdate
|
121
|
+
}.tap do |hash|
|
122
|
+
OrderedHashSerializer.apply_to(hash, members)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.from_hash(hash)
|
127
|
+
new Request.from_hash(hash.fetch('request', {})),
|
128
|
+
Response.from_hash(hash.fetch('response', {})),
|
129
|
+
Time.httpdate(hash.fetch('recorded_at'))
|
130
|
+
end
|
131
|
+
|
132
|
+
def ignore!
|
133
|
+
@ignored = true
|
134
|
+
end
|
135
|
+
|
136
|
+
def ignored?
|
137
|
+
!!@ignored
|
138
|
+
end
|
139
|
+
|
140
|
+
def filter!(text, replacement_text)
|
141
|
+
return self if [text, replacement_text].any? { |t| t.to_s.empty? }
|
142
|
+
filter_object!(self, text, replacement_text)
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def filter_object!(object, text, replacement_text)
|
148
|
+
if object.respond_to?(:gsub)
|
149
|
+
object.gsub!(text, replacement_text) if object.include?(text)
|
150
|
+
elsif Hash === object
|
151
|
+
filter_hash!(object, text, replacement_text)
|
152
|
+
elsif object.respond_to?(:each)
|
153
|
+
# This handles nested arrays and structs
|
154
|
+
object.each { |o| filter_object!(o, text, replacement_text) }
|
155
|
+
end
|
156
|
+
|
157
|
+
object
|
158
|
+
end
|
159
|
+
|
160
|
+
def filter_hash!(hash, text, replacement_text)
|
161
|
+
filter_object!(hash.values, text, replacement_text)
|
162
|
+
|
163
|
+
hash.keys.each do |k|
|
164
|
+
new_key = filter_object!(k.dup, text, replacement_text)
|
165
|
+
hash[new_key] = hash.delete(k) unless k == new_key
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class Response < Struct.new(:status, :headers, :body, :http_version)
|
171
|
+
include Normalizers::Header
|
172
|
+
include Normalizers::Body
|
173
|
+
|
174
|
+
def to_hash
|
175
|
+
{
|
176
|
+
'status' => status.to_hash,
|
177
|
+
'headers' => headers,
|
178
|
+
'body' => body,
|
179
|
+
'http_version' => http_version
|
180
|
+
}.tap { |h| OrderedHashSerializer.apply_to(h, members) }
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.from_hash(hash)
|
184
|
+
new ResponseStatus.from_hash(hash.fetch('status', {})),
|
185
|
+
hash['headers'],
|
186
|
+
hash['body'],
|
187
|
+
hash['http_version']
|
188
|
+
end
|
189
|
+
|
190
|
+
def update_content_length_header
|
191
|
+
# TODO: should this be the bytesize?
|
192
|
+
value = body ? body.length.to_s : '0'
|
193
|
+
key = %w[ Content-Length content-length ].find { |k| headers.has_key?(k) }
|
194
|
+
headers[key] = [value] if key
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class ResponseStatus < Struct.new(:code, :message)
|
199
|
+
def to_hash
|
200
|
+
{
|
201
|
+
'code' => code, 'message' => message
|
202
|
+
}.tap { |h| OrderedHashSerializer.apply_to(h, members) }
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.from_hash(hash)
|
206
|
+
new hash['code'], hash['message']
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
namespace :vcr do
|
2
|
+
desc "Migrate cassettes from the VCR 1.x format to the VCR 2.x format."
|
3
|
+
task :migrate_cassettes do
|
4
|
+
dir = ENV.fetch('DIR') { raise "You must pass the cassette library directory as DIR=<directory>" }
|
5
|
+
require 'vcr/cassette/migrator'
|
6
|
+
VCR::Cassette::Migrator.new(dir).migrate!
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
data/lib/vcr/version.rb
CHANGED
@@ -0,0 +1,110 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://example.com:80/
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
response: !ruby/struct:VCR::Response
|
9
|
+
status: !ruby/struct:VCR::ResponseStatus
|
10
|
+
code: 200
|
11
|
+
message: OK
|
12
|
+
headers:
|
13
|
+
last-modified:
|
14
|
+
- Tue, 15 Nov 2005 13:24:10 GMT
|
15
|
+
connection:
|
16
|
+
- Keep-Alive
|
17
|
+
date:
|
18
|
+
- Thu, 25 Feb 2010 07:52:38 GMT
|
19
|
+
content-type:
|
20
|
+
- text/html; charset=UTF-8
|
21
|
+
etag:
|
22
|
+
- "\"24ec5-1b6-4059a80bfd280\""
|
23
|
+
server:
|
24
|
+
- Apache/2.2.3 (CentOS)
|
25
|
+
content-length:
|
26
|
+
- "438"
|
27
|
+
age:
|
28
|
+
- "3009"
|
29
|
+
accept-ranges:
|
30
|
+
- bytes
|
31
|
+
body: |
|
32
|
+
<HTML>
|
33
|
+
<HEAD>
|
34
|
+
<TITLE>Example Web Page</TITLE>
|
35
|
+
</HEAD>
|
36
|
+
<body>
|
37
|
+
<p>You have reached this web page by typing "example.com",
|
38
|
+
"example.net",
|
39
|
+
or "example.org" into your web browser.</p>
|
40
|
+
<p>These domain names are reserved for use in documentation and are not available
|
41
|
+
for registration. See <a href="http://www.rfc-editor.org/rfc/rfc2606.txt">RFC
|
42
|
+
2606</a>, Section 3.</p>
|
43
|
+
</BODY>
|
44
|
+
</HTML>
|
45
|
+
|
46
|
+
http_version: "1.1"
|
47
|
+
- !ruby/struct:VCR::HTTPInteraction
|
48
|
+
request: !ruby/struct:VCR::Request
|
49
|
+
method: :get
|
50
|
+
uri: http://example.com:80/foo
|
51
|
+
body:
|
52
|
+
headers:
|
53
|
+
response: !ruby/struct:VCR::Response
|
54
|
+
status: !ruby/struct:VCR::ResponseStatus
|
55
|
+
code: 404
|
56
|
+
message: Not Found
|
57
|
+
headers:
|
58
|
+
connection:
|
59
|
+
- close
|
60
|
+
content-type:
|
61
|
+
- text/html; charset=iso-8859-1
|
62
|
+
date:
|
63
|
+
- Thu, 25 Feb 2010 07:52:38 GMT
|
64
|
+
server:
|
65
|
+
- Apache/2.2.3 (CentOS)
|
66
|
+
content-length:
|
67
|
+
- "277"
|
68
|
+
body: |
|
69
|
+
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
70
|
+
<html><head>
|
71
|
+
<title>404 Not Found</title>
|
72
|
+
</head><body>
|
73
|
+
<h1>Not Found</h1>
|
74
|
+
<p>The requested URL /foo was not found on this server.</p>
|
75
|
+
<hr>
|
76
|
+
<address>Apache/2.2.3 (CentOS) Server at example.com Port 80</address>
|
77
|
+
</body></html>
|
78
|
+
|
79
|
+
http_version: "1.1"
|
80
|
+
- !ruby/struct:VCR::HTTPInteraction
|
81
|
+
request: !ruby/struct:VCR::Request
|
82
|
+
method: :get
|
83
|
+
uri: http://example.com:80/
|
84
|
+
body:
|
85
|
+
headers:
|
86
|
+
response: !ruby/struct:VCR::Response
|
87
|
+
status: !ruby/struct:VCR::ResponseStatus
|
88
|
+
code: 200
|
89
|
+
message: OK
|
90
|
+
headers:
|
91
|
+
last-modified:
|
92
|
+
- Tue, 15 Nov 2005 13:24:10 GMT
|
93
|
+
connection:
|
94
|
+
- Keep-Alive
|
95
|
+
date:
|
96
|
+
- Thu, 25 Feb 2010 07:52:38 GMT
|
97
|
+
content-type:
|
98
|
+
- text/html; charset=UTF-8
|
99
|
+
etag:
|
100
|
+
- "\"24ec5-1b6-4059a80bfd280\""
|
101
|
+
server:
|
102
|
+
- Apache/2.2.3 (CentOS)
|
103
|
+
content-length:
|
104
|
+
- "438"
|
105
|
+
age:
|
106
|
+
- "3009"
|
107
|
+
accept-ranges:
|
108
|
+
- bytes
|
109
|
+
body: Another example.com response
|
110
|
+
http_version: "1.1"
|
@@ -1,110 +1,111 @@
|
|
1
|
-
---
|
2
|
-
|
3
|
-
|
4
|
-
method:
|
5
|
-
uri: http://example.com
|
6
|
-
body:
|
7
|
-
headers:
|
8
|
-
response:
|
9
|
-
status:
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/
|
6
|
+
body: ''
|
7
|
+
headers: {}
|
8
|
+
response:
|
9
|
+
status:
|
10
10
|
code: 200
|
11
11
|
message: OK
|
12
|
-
headers:
|
13
|
-
|
12
|
+
headers:
|
13
|
+
Last-Modified:
|
14
14
|
- Tue, 15 Nov 2005 13:24:10 GMT
|
15
|
-
|
15
|
+
Connection:
|
16
16
|
- Keep-Alive
|
17
|
-
|
17
|
+
Date:
|
18
18
|
- Thu, 25 Feb 2010 07:52:38 GMT
|
19
|
-
|
19
|
+
Content-Type:
|
20
20
|
- text/html; charset=UTF-8
|
21
|
-
|
22
|
-
- "
|
23
|
-
|
21
|
+
Etag:
|
22
|
+
- ! '"24ec5-1b6-4059a80bfd280"'
|
23
|
+
Server:
|
24
24
|
- Apache/2.2.3 (CentOS)
|
25
|
-
|
26
|
-
-
|
27
|
-
|
28
|
-
-
|
29
|
-
|
25
|
+
Content-Length:
|
26
|
+
- '438'
|
27
|
+
Age:
|
28
|
+
- '3009'
|
29
|
+
Accept-Ranges:
|
30
30
|
- bytes
|
31
|
-
body:
|
32
|
-
|
33
|
-
<
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
http_version: "1.1"
|
47
|
-
- !ruby/struct:VCR::HTTPInteraction
|
48
|
-
request: !ruby/struct:VCR::Request
|
49
|
-
method: :get
|
50
|
-
uri: http://example.com:80/foo
|
51
|
-
body:
|
52
|
-
headers:
|
53
|
-
response: !ruby/struct:VCR::Response
|
54
|
-
status: !ruby/struct:VCR::ResponseStatus
|
31
|
+
body: ! "<HTML>\n<HEAD>\n <TITLE>Example Web Page</TITLE>\n</HEAD> \n<body> \n<p>You
|
32
|
+
have reached this web page by typing "example.com",\n"example.net",\n
|
33
|
+
\ or "example.org" into your web browser.</p>\n<p>These domain names
|
34
|
+
are reserved for use in documentation and are not available \n for registration.
|
35
|
+
See <a href=\"http://www.rfc-editor.org/rfc/rfc2606.txt\">RFC \n 2606</a>,
|
36
|
+
Section 3.</p>\n</BODY>\n</HTML>\n"
|
37
|
+
http_version: '1.1'
|
38
|
+
recorded_at: Tue, 01 Nov 2011 04:49:54 GMT
|
39
|
+
- request:
|
40
|
+
method: get
|
41
|
+
uri: http://example.com/foo
|
42
|
+
body: ''
|
43
|
+
headers: {}
|
44
|
+
response:
|
45
|
+
status:
|
55
46
|
code: 404
|
56
47
|
message: Not Found
|
57
|
-
headers:
|
58
|
-
|
48
|
+
headers:
|
49
|
+
Connection:
|
59
50
|
- close
|
60
|
-
|
51
|
+
Content-Type:
|
61
52
|
- text/html; charset=iso-8859-1
|
62
|
-
|
53
|
+
Date:
|
63
54
|
- Thu, 25 Feb 2010 07:52:38 GMT
|
64
|
-
|
55
|
+
Server:
|
65
56
|
- Apache/2.2.3 (CentOS)
|
66
|
-
|
67
|
-
-
|
68
|
-
body:
|
69
|
-
|
57
|
+
Content-Length:
|
58
|
+
- '277'
|
59
|
+
body: ! '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
60
|
+
|
70
61
|
<html><head>
|
62
|
+
|
71
63
|
<title>404 Not Found</title>
|
64
|
+
|
72
65
|
</head><body>
|
66
|
+
|
73
67
|
<h1>Not Found</h1>
|
68
|
+
|
74
69
|
<p>The requested URL /foo was not found on this server.</p>
|
70
|
+
|
75
71
|
<hr>
|
72
|
+
|
76
73
|
<address>Apache/2.2.3 (CentOS) Server at example.com Port 80</address>
|
74
|
+
|
77
75
|
</body></html>
|
78
76
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
77
|
+
'
|
78
|
+
http_version: '1.1'
|
79
|
+
recorded_at: Tue, 01 Nov 2011 04:49:54 GMT
|
80
|
+
- request:
|
81
|
+
method: get
|
82
|
+
uri: http://example.com/
|
83
|
+
body: ''
|
84
|
+
headers: {}
|
85
|
+
response:
|
86
|
+
status:
|
88
87
|
code: 200
|
89
88
|
message: OK
|
90
|
-
headers:
|
91
|
-
|
89
|
+
headers:
|
90
|
+
Last-Modified:
|
92
91
|
- Tue, 15 Nov 2005 13:24:10 GMT
|
93
|
-
|
92
|
+
Connection:
|
94
93
|
- Keep-Alive
|
95
|
-
|
94
|
+
Date:
|
96
95
|
- Thu, 25 Feb 2010 07:52:38 GMT
|
97
|
-
|
96
|
+
Content-Type:
|
98
97
|
- text/html; charset=UTF-8
|
99
|
-
|
100
|
-
- "
|
101
|
-
|
98
|
+
Etag:
|
99
|
+
- ! '"24ec5-1b6-4059a80bfd280"'
|
100
|
+
Server:
|
102
101
|
- Apache/2.2.3 (CentOS)
|
103
|
-
|
104
|
-
-
|
105
|
-
|
106
|
-
-
|
107
|
-
|
102
|
+
Content-Length:
|
103
|
+
- '438'
|
104
|
+
Age:
|
105
|
+
- '3009'
|
106
|
+
Accept-Ranges:
|
108
107
|
- bytes
|
109
108
|
body: Another example.com response
|
110
|
-
http_version:
|
109
|
+
http_version: '1.1'
|
110
|
+
recorded_at: Tue, 01 Nov 2011 04:49:54 GMT
|
111
|
+
recorded_with: VCR 1.11.3
|