puffing-billy 2.2.0 → 2.3.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +27 -24
- data/examples/tumblr_api_https.html +22 -0
- data/lib/billy/browsers/capybara.rb +2 -0
- data/lib/billy/config.rb +2 -1
- data/lib/billy/handlers/proxy_handler.rb +11 -1
- data/lib/billy/version.rb +1 -1
- data/spec/lib/billy/browsers/capybara_spec.rb +28 -0
- data/spec/lib/billy/handlers/proxy_handler_spec.rb +28 -0
- data/spec/lib/proxy_spec.rb +23 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9abe93dc66216bc06e928bc9b61d92c52aaa718c196664afbaece19ef9dedd06
|
4
|
+
data.tar.gz: 76967de33848f166cc247c0a20ac917537331293237e33d8a5693fd1756221ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 234b170df43cc3954a49e7fdae65593b1de7e07b0ae4fc3e68dfc9da620c348d700af14f533d379448f1da764cd484f2e07752b2254d59c602b76d96ebb14449
|
7
|
+
data.tar.gz: 21e5760521c6c6d74d9a969834cc1856f780f98350665793a3028140f8b2f738a4df6060a2d8043946d977b6f504c74625df12a763fc7e8b29619f9aba7c8423
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
v2.3.0, 2019-12-26
|
2
|
+
-------------------
|
3
|
+
* Add `cache_whitelist` config option [#279](https://github.com/oesmith/puffing-billy/pull/279)
|
4
|
+
* Ignore certificate errors in Chrome [#280](https://github.com/oesmith/puffing-billy/pull/280)
|
5
|
+
|
1
6
|
v2.2.0, 2019-10-26
|
2
7
|
-------------------
|
3
8
|
* Before handle request method [#273](https://github.com/oesmith/puffing-billy/pull/273)
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ you can test it!
|
|
21
21
|
|
22
22
|
```ruby
|
23
23
|
it 'should stub google' do
|
24
|
-
proxy.stub('http://www.google.com/').and_return(:
|
24
|
+
proxy.stub('http://www.google.com/').and_return(text: "I'm not Google!")
|
25
25
|
visit 'http://www.google.com/'
|
26
26
|
expect(page).to have_content("I'm not Google!")
|
27
27
|
end
|
@@ -85,21 +85,21 @@ require 'billy/watir/rspec'
|
|
85
85
|
|
86
86
|
```ruby
|
87
87
|
# Stub and return text, json, jsonp (or anything else)
|
88
|
-
proxy.stub('http://example.com/text/').and_return(:
|
89
|
-
proxy.stub('http://example.com/json/').and_return(:
|
90
|
-
proxy.stub('http://example.com/jsonp/').and_return(:
|
91
|
-
proxy.stub('http://example.com/headers/').and_return(
|
92
|
-
:
|
93
|
-
:
|
94
|
-
|
95
|
-
proxy.stub('http://example.com/wtf/').and_return(:
|
88
|
+
proxy.stub('http://example.com/text/').and_return(text: 'Foobar')
|
89
|
+
proxy.stub('http://example.com/json/').and_return(json: { foo: 'bar' })
|
90
|
+
proxy.stub('http://example.com/jsonp/').and_return(jsonp: { foo: 'bar' })
|
91
|
+
proxy.stub('http://example.com/headers/').and_return(
|
92
|
+
headers: { 'Access-Control-Allow-Origin' => '*' },
|
93
|
+
json: { foo: 'bar' }
|
94
|
+
)
|
95
|
+
proxy.stub('http://example.com/wtf/').and_return(body: 'WTF!?', content_type: 'text/wtf')
|
96
96
|
|
97
97
|
# Stub redirections and other return codes
|
98
|
-
proxy.stub('http://example.com/redirect/').and_return(:
|
99
|
-
proxy.stub('http://example.com/missing/').and_return(:
|
98
|
+
proxy.stub('http://example.com/redirect/').and_return(redirect_to: 'http://example.com/other')
|
99
|
+
proxy.stub('http://example.com/missing/').and_return(code: 404, body: 'Not found')
|
100
100
|
|
101
101
|
# Even stub HTTPS!
|
102
|
-
proxy.stub('https://example.com:443/secure/').and_return(:
|
102
|
+
proxy.stub('https://example.com:443/secure/').and_return(text: 'secrets!!1!')
|
103
103
|
|
104
104
|
# Pass a Proc (or Proc-style object) to create dynamic responses.
|
105
105
|
#
|
@@ -111,8 +111,8 @@ proxy.stub('https://example.com:443/secure/').and_return(:text => 'secrets!!1!')
|
|
111
111
|
# method: The HTTP verb which was requested
|
112
112
|
proxy.stub('https://example.com/proc/').and_return(Proc.new { |params, headers, body, url, method|
|
113
113
|
{
|
114
|
-
:
|
115
|
-
:
|
114
|
+
code: 200,
|
115
|
+
text: "Hello, #{params['name'][0]}"
|
116
116
|
}
|
117
117
|
})
|
118
118
|
|
@@ -122,7 +122,7 @@ proxy.stub('https://example.com/proc/').and_return(Proc.new { |params, headers,
|
|
122
122
|
# server. The scope of the delivered callable is the user scope where
|
123
123
|
# it was defined. Setting method to 'all' will intercept requests regardless of
|
124
124
|
# the method.
|
125
|
-
proxy.stub('http://example.com/', method
|
125
|
+
proxy.stub('http://example.com/', method: 'all').and_return(Proc.new { |*args|
|
126
126
|
response = Billy.pass_request(*args)
|
127
127
|
response[:headers]['Content-Type'] = 'text/plain'
|
128
128
|
response[:body] = 'Hello World!'
|
@@ -131,19 +131,19 @@ proxy.stub('http://example.com/', method => 'all').and_return(Proc.new { |*args|
|
|
131
131
|
})
|
132
132
|
|
133
133
|
# Stub out a POST. Don't forget to allow a CORS request and set the method to 'post'
|
134
|
-
proxy.stub('http://example.com/api', :
|
135
|
-
:
|
136
|
-
:
|
134
|
+
proxy.stub('http://example.com/api', method: 'post').and_return(
|
135
|
+
headers: { 'Access-Control-Allow-Origin' => '*' },
|
136
|
+
code: 201
|
137
137
|
)
|
138
138
|
|
139
139
|
# Stub out an OPTIONS request. Set the headers to the values you require.
|
140
|
-
proxy.stub('http://example.com/api', :
|
141
|
-
:
|
140
|
+
proxy.stub('http://example.com/api', method: 'options').and_return(
|
141
|
+
headers: {
|
142
142
|
'Access-Control-Allow-Methods' => 'GET, PATCH, POST, PUT, OPTIONS',
|
143
143
|
'Access-Control-Allow-Headers' => 'X-Requested-With, X-Prototype-Version, Content-Type',
|
144
144
|
'Access-Control-Allow-Origin' => '*'
|
145
145
|
},
|
146
|
-
:
|
146
|
+
code: 200
|
147
147
|
)
|
148
148
|
```
|
149
149
|
|
@@ -154,7 +154,7 @@ If for any reason you'd need to reset stubs manually you can do it in two ways:
|
|
154
154
|
|
155
155
|
```ruby
|
156
156
|
# reset a single stub
|
157
|
-
example_stub = proxy.stub('http://example.com/text/').and_return(:
|
157
|
+
example_stub = proxy.stub('http://example.com/text/').and_return(text: 'Foobar')
|
158
158
|
proxy.unstub example_stub
|
159
159
|
|
160
160
|
# reset all stubs
|
@@ -193,7 +193,7 @@ Before('@billy') do
|
|
193
193
|
end
|
194
194
|
|
195
195
|
And /^a stub for google$/ do
|
196
|
-
proxy.stub('http://www.google.com/').and_return(:
|
196
|
+
proxy.stub('http://www.google.com/').and_return(text: "I'm not Google!")
|
197
197
|
visit 'http://www.google.com/'
|
198
198
|
expect(page).to have_content("I'm not Google!")
|
199
199
|
end
|
@@ -224,7 +224,7 @@ Before('@billy') do
|
|
224
224
|
end
|
225
225
|
|
226
226
|
And /^a stub for google$/ do
|
227
|
-
proxy.stub('http://www.google.com/').and_return(:
|
227
|
+
proxy.stub('http://www.google.com/').and_return(text: "I'm not Google!")
|
228
228
|
@browser.goto 'http://www.google.com/'
|
229
229
|
expect(@browser.text).to eq("I'm not Google!")
|
230
230
|
end
|
@@ -263,6 +263,8 @@ server = Capybara.current_session.server
|
|
263
263
|
Billy.config.whitelist = ["#{server.host}:#{server.port}"]
|
264
264
|
```
|
265
265
|
|
266
|
+
If you would like to cache whitelisted URLs, you can define them in `c.cache_whitelist`. This is useful for scenarios where you may want to set `c.non_whitelisted_requests_disabled` to `true` to only allow whitelisted URLs to be accessed, but still allow specific URLs to be treated as if they were non-whitelisted.
|
267
|
+
|
266
268
|
If you want to use puffing-billy like you would [VCR](https://github.com/vcr/vcr)
|
267
269
|
you can turn on cache persistence. This way you don't have to manually mock out
|
268
270
|
everything as requests are automatically recorded and played back. With cache
|
@@ -292,6 +294,7 @@ Billy.configure do |c|
|
|
292
294
|
c.proxy_port = 12345 # defaults to random
|
293
295
|
c.proxied_request_host = nil
|
294
296
|
c.proxied_request_port = 80
|
297
|
+
c.cache_whitelist = []
|
295
298
|
c.record_requests = true # defaults to false
|
296
299
|
c.cache_request_body_methods = ['post', 'patch', 'put'] # defaults to ['post']
|
297
300
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<body>
|
3
|
+
<h1>Latest news</h1>
|
4
|
+
<div id="news"></div>
|
5
|
+
|
6
|
+
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.min.js'></script>
|
7
|
+
<script type='text/javascript'>
|
8
|
+
$(function () {
|
9
|
+
var url = 'https://blog.howmanyleft.co.uk/api/read/json?callback=?&type=text&num=3&filter=text';
|
10
|
+
$.getJSON(url, function (data) {
|
11
|
+
$.each(data.posts, function (idx, post) {
|
12
|
+
var title = post['regular-title'];
|
13
|
+
var href = post['url-with-slug'];
|
14
|
+
var body = post['regular-body'];
|
15
|
+
$('#news').append(
|
16
|
+
'<h3><a href="' + href + '">' + title + '</a></h3>' +
|
17
|
+
'<p>' + body + '</p>');
|
18
|
+
});
|
19
|
+
});
|
20
|
+
})
|
21
|
+
</script>
|
22
|
+
</body>
|
@@ -64,6 +64,7 @@ module Billy
|
|
64
64
|
|
65
65
|
::Capybara.register_driver :selenium_chrome_billy do |app|
|
66
66
|
options = Selenium::WebDriver::Chrome::Options.new
|
67
|
+
options.add_argument('--ignore-certificate-errors')
|
67
68
|
options.add_argument("--proxy-server=#{Billy.proxy.host}:#{Billy.proxy.port}")
|
68
69
|
|
69
70
|
::Capybara::Selenium::Driver.new(
|
@@ -79,6 +80,7 @@ module Billy
|
|
79
80
|
options = Selenium::WebDriver::Chrome::Options.new
|
80
81
|
options.headless!
|
81
82
|
options.add_argument('--enable-features=NetworkService,NetworkServiceInProcess')
|
83
|
+
options.add_argument('--ignore-certificate-errors')
|
82
84
|
options.add_argument("--proxy-server=#{Billy.proxy.host}:#{Billy.proxy.port}")
|
83
85
|
options.add_argument('--disable-gpu') if Gem.win_platform?
|
84
86
|
options.add_argument('--no-sandbox') if ENV['CI']
|
data/lib/billy/config.rb
CHANGED
@@ -6,7 +6,7 @@ module Billy
|
|
6
6
|
DEFAULT_WHITELIST = ['127.0.0.1', 'localhost']
|
7
7
|
RANDOM_AVAILABLE_PORT = 0 # https://github.com/eventmachine/eventmachine/wiki/FAQ#wiki-can-i-start-a-server-on-a-random-available-port
|
8
8
|
|
9
|
-
attr_accessor :logger, :cache, :cache_request_headers, :whitelist, :path_blacklist, :ignore_params, :allow_params,
|
9
|
+
attr_accessor :logger, :cache, :cache_request_headers, :whitelist, :cache_whitelist, :path_blacklist, :ignore_params, :allow_params,
|
10
10
|
:persist_cache, :ignore_cache_port, :non_successful_cache_disabled, :non_successful_error_level,
|
11
11
|
:non_whitelisted_requests_disabled, :cache_path, :certs_path, :proxy_host, :proxy_port, :proxied_request_inactivity_timeout,
|
12
12
|
:proxied_request_connect_timeout, :dynamic_jsonp, :dynamic_jsonp_keys, :dynamic_jsonp_callback_name, :merge_cached_responses_whitelist,
|
@@ -21,6 +21,7 @@ module Billy
|
|
21
21
|
def reset
|
22
22
|
@cache = true
|
23
23
|
@cache_request_headers = false
|
24
|
+
@cache_whitelist = []
|
24
25
|
@whitelist = DEFAULT_WHITELIST
|
25
26
|
@path_blacklist = []
|
26
27
|
@merge_cached_responses_whitelist = []
|
@@ -110,7 +110,7 @@ module Billy
|
|
110
110
|
|
111
111
|
url = Addressable::URI.parse(url)
|
112
112
|
# Cache the responses if they aren't whitelisted host[:port]s but always cache blacklisted paths on any hosts
|
113
|
-
cacheable_status?(status) && (!whitelisted_url?(url) || blacklisted_path?(url.path))
|
113
|
+
cacheable_status?(status) && (!whitelisted_url?(url) || blacklisted_path?(url.path) || cache_whitelisted_url?(url))
|
114
114
|
end
|
115
115
|
|
116
116
|
def whitelisted_url?(url)
|
@@ -123,6 +123,16 @@ module Billy
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
def cache_whitelisted_url?(url)
|
127
|
+
Billy.config.cache_whitelist.any? do |value|
|
128
|
+
if value.is_a?(Regexp)
|
129
|
+
url.to_s =~ value || url.omit(:port).to_s =~ value
|
130
|
+
else
|
131
|
+
value =~ /^#{url.host}(?::#{url.port})?$/
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
126
136
|
def blacklisted_path?(path)
|
127
137
|
!Billy.config.path_blacklist.index { |bl| bl.is_a?(Regexp) ? path =~ bl : path.include?(bl) }.nil?
|
128
138
|
end
|
data/lib/billy/version.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Capybara drivers', type: :feature, js: true do
|
4
|
+
it 'allows HTTPS calls' do
|
5
|
+
proxy.stub('https://blog.howmanyleft.co.uk:443/api/read/json').and_return(
|
6
|
+
jsonp: {
|
7
|
+
posts: [
|
8
|
+
{
|
9
|
+
'regular-title' => 'News Item 1',
|
10
|
+
'url-with-slug' => 'http://example.com/news/1',
|
11
|
+
'regular-body' => 'News item 1 content here'
|
12
|
+
},
|
13
|
+
{
|
14
|
+
'regular-title' => 'News Item 2',
|
15
|
+
'url-with-slug' => 'http://example.com/news/2',
|
16
|
+
'regular-body' => 'News item 2 content here'
|
17
|
+
}
|
18
|
+
]
|
19
|
+
})
|
20
|
+
|
21
|
+
visit '/tumblr_api_https.html'
|
22
|
+
|
23
|
+
expect(page).to have_link('News Item 1', href: 'http://example.com/news/1')
|
24
|
+
expect(page).to have_content('News item 1 content here')
|
25
|
+
expect(page).to have_link('News Item 2', href: 'http://example.com/news/2')
|
26
|
+
expect(page).to have_content('News item 2 content here')
|
27
|
+
end
|
28
|
+
end
|
@@ -175,6 +175,34 @@ describe Billy::ProxyHandler do
|
|
175
175
|
request[:body])
|
176
176
|
end
|
177
177
|
|
178
|
+
it 'does NOT cache the response if the host is whitelisted but not cache_whitelisted' do
|
179
|
+
uri = Addressable::URI.parse(request[:url])
|
180
|
+
|
181
|
+
expect(subject).to receive(:allowed_response_code?).and_return(true)
|
182
|
+
expect(Billy.config).to receive(:whitelist).and_return([uri.host])
|
183
|
+
expect(Billy.config).to receive(:cache_whitelist).and_return([])
|
184
|
+
|
185
|
+
expect(Billy::Cache.instance).not_to receive(:store)
|
186
|
+
subject.handle_request(request[:method],
|
187
|
+
request[:url],
|
188
|
+
request[:headers],
|
189
|
+
request[:body])
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'caches the response if the host is whitelisted AND cache_whitelisted' do
|
193
|
+
uri = Addressable::URI.parse(request[:url])
|
194
|
+
|
195
|
+
expect(subject).to receive(:allowed_response_code?).and_return(true)
|
196
|
+
expect(Billy.config).to receive(:whitelist).and_return([uri.host])
|
197
|
+
expect(Billy.config).to receive(:cache_whitelist).and_return([uri.host])
|
198
|
+
|
199
|
+
expect(Billy::Cache.instance).to receive(:store)
|
200
|
+
subject.handle_request(request[:method],
|
201
|
+
request[:url],
|
202
|
+
request[:headers],
|
203
|
+
request[:body])
|
204
|
+
end
|
205
|
+
|
178
206
|
it 'uses the timeouts defined in configuration' do
|
179
207
|
allow(Billy.config).to receive(:proxied_request_inactivity_timeout).and_return(42)
|
180
208
|
allow(Billy.config).to receive(:proxied_request_connect_timeout).and_return(24)
|
data/spec/lib/proxy_spec.rb
CHANGED
@@ -118,6 +118,29 @@ shared_examples_for 'a cache' do
|
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
|
+
context 'cache_whitelist GET requests' do
|
122
|
+
before do
|
123
|
+
Billy.config.whitelist = [http.host]
|
124
|
+
Billy.config.cache_whitelist = [http.host]
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should be cached' do
|
128
|
+
assert_cached_url
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'with ports' do
|
132
|
+
before do
|
133
|
+
rack_app_url = URI(http.url_prefix)
|
134
|
+
Billy.config.whitelist = ["#{rack_app_url.host}:#{rack_app_url.port + 1}"]
|
135
|
+
Billy.config.cache_whitelist = Billy.config.whitelist
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should be cached' do
|
139
|
+
assert_cached_url
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
121
144
|
context 'ignore_params GET requests' do
|
122
145
|
before do
|
123
146
|
Billy.config.ignore_params = ['/analytics']
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puffing-billy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Olly Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -336,6 +336,7 @@ files:
|
|
336
336
|
- examples/post_api.html
|
337
337
|
- examples/preflight_request.html
|
338
338
|
- examples/tumblr_api.html
|
339
|
+
- examples/tumblr_api_https.html
|
339
340
|
- lib/billy.rb
|
340
341
|
- lib/billy/browsers/capybara.rb
|
341
342
|
- lib/billy/browsers/watir.rb
|
@@ -375,6 +376,7 @@ files:
|
|
375
376
|
- spec/features/examples/post_api_spec.rb
|
376
377
|
- spec/features/examples/preflight_request_spec.rb
|
377
378
|
- spec/features/examples/tumblr_api_spec.rb
|
379
|
+
- spec/lib/billy/browsers/capybara_spec.rb
|
378
380
|
- spec/lib/billy/cache_spec.rb
|
379
381
|
- spec/lib/billy/handlers/cache_handler_spec.rb
|
380
382
|
- spec/lib/billy/handlers/handler_spec.rb
|
@@ -421,6 +423,7 @@ test_files:
|
|
421
423
|
- spec/features/examples/post_api_spec.rb
|
422
424
|
- spec/features/examples/preflight_request_spec.rb
|
423
425
|
- spec/features/examples/tumblr_api_spec.rb
|
426
|
+
- spec/lib/billy/browsers/capybara_spec.rb
|
424
427
|
- spec/lib/billy/cache_spec.rb
|
425
428
|
- spec/lib/billy/handlers/cache_handler_spec.rb
|
426
429
|
- spec/lib/billy/handlers/handler_spec.rb
|