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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
Feature: Filter sensitive data
Note: this config option is also available as `define_cassette_placeholder`
to reflect the fact that it is useful for more than just sensitive data.
The `filter_sensitive_data` configuration option can be used to prevent
sensitive data from being written to your cassette files. This may be
important if you commit your cassettes files to source control and do
not want your sensitive data exposed. Pass the following arguments to
`filter_sensitive_data`:
- A substitution string. This is the string that will be written to
the cassettte file as a placeholder. It should be unique and you
may want to wrap it in special characters like `{ }` or `< >`.
- A symbol specifying a tag (optional). If a tag is given, the
filtering will only be applied to cassettes with the given tag.
- A block. The block should return the sensitive text that you want
replaced with the substitution string. If your block accepts an
argument, the HTTP interaction will be yielded so that you can
dynamically specify the sensitive text based on the interaction
(see the last scenario for an example of this).
When the interactions are replayed, the sensitive text will replace the
substitution string so that the interaction will be identical to what was
originally recorded.
You can specify as many filterings as you want.
Scenario: Multiple filterings
Given a file named "filtering.rb" with:
"""ruby
if ARGV.include?('--with-server')
$server = start_sinatra_app do
get('/') { "Hello World" }
end
end
require 'vcr'
VCR.configure do |c|
c.hook_into :webmock
c.cassette_library_dir = 'cassettes'
c.filter_sensitive_data('<GREETING>') { 'Hello' }
c.filter_sensitive_data('<LOCATION>') { 'World' }
end
VCR.use_cassette('filtering') do
response = Net::HTTP.get_response('localhost', '/', $server ? $server.port : 0)
puts "Response: #{response.body}"
end
"""
When I run `ruby filtering.rb --with-server`
Then the output should contain "Response: Hello World"
And the file "cassettes/filtering.yml" should contain "<GREETING> <LOCATION>"
And the file "cassettes/filtering.yml" should not contain "Hello"
And the file "cassettes/filtering.yml" should not contain "World"
When I run `ruby filtering.rb`
Then the output should contain "Hello World"
Scenario: Filter tagged cassettes
Given a file named "tagged_filtering.rb" with:
"""ruby
if ARGV.include?('--with-server')
response_count = 0
$server = start_sinatra_app do
get('/') { "Hello World #{response_count += 1 }" }
end
end
require 'vcr'
VCR.configure do |c|
c.hook_into :webmock
c.cassette_library_dir = 'cassettes'
c.filter_sensitive_data('<LOCATION>', :my_tag) { 'World' }
end
VCR.use_cassette('tagged', :tag => :my_tag) do
response = Net::HTTP.get_response('localhost', '/', $server ? $server.port : 0)
puts "Tagged Response: #{response.body}"
end
VCR.use_cassette('untagged', :record => :new_episodes) do
response = Net::HTTP.get_response('localhost', '/', $server ? $server.port : 0)
puts "Untagged Response: #{response.body}"
end
"""
When I run `ruby tagged_filtering.rb --with-server`
Then the output should contain each of the following:
| Tagged Response: Hello World 1 |
| Untagged Response: Hello World 2 |
And the file "cassettes/tagged.yml" should contain "Hello <LOCATION> 1"
And the file "cassettes/untagged.yml" should contain "Hello World 2"
When I run `ruby tagged_filtering.rb`
Then the output should contain each of the following:
| Tagged Response: Hello World 1 |
| Untagged Response: Hello World 2 |
Scenario: Filter dynamic data based on yielded HTTP interaction
Given a file named "dynamic_filtering.rb" with:
"""ruby
include_http_adapter_for('net/http')
if ARGV.include?('--with-server')
$server = start_sinatra_app do
helpers do
def request_header_for(header_key_fragment)
key = env.keys.find { |k| k =~ /#{header_key_fragment}/i }
env[key]
end
end
get('/') { "#{request_header_for('username')}/#{request_header_for('password')}" }
end
end
require 'vcr'
USER_PASSWORDS = {
'john.doe' => 'monkey',
'jane.doe' => 'cheetah'
}
VCR.configure do |c|
c.hook_into :webmock
c.cassette_library_dir = 'cassettes'
c.filter_sensitive_data('<PASSWORD>') do |interaction|
USER_PASSWORDS[interaction.request.headers['X-Http-Username'].first]
end
end
VCR.use_cassette('example', :match_requests_on => [:method, :uri, :headers]) do
port = $server ? $server.port : 0
puts "Response: " + response_body_for(
:get, "http://localhost:#{port}/", nil,
'X-Http-Username' => 'john.doe',
'X-Http-Password' => USER_PASSWORDS['john.doe']
)
end
"""
When I run `ruby dynamic_filtering.rb --with-server`
Then the output should contain "john.doe/monkey"
And the file "cassettes/example.yml" should contain "john.doe/<PASSWORD>"
And the file "cassettes/example.yml" should contain a YAML fragment like:
"""
X-Http-Password:
- <PASSWORD>
"""
When I run `ruby dynamic_filtering.rb`
Then the output should contain "john.doe/monkey"
|