puffing-billy 3.0.0 → 3.0.1

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/billy/browsers/capybara.rb +13 -9
  4. data/lib/billy/version.rb +1 -1
  5. metadata +9 -73
  6. data/.github/workflows/ci.yml +0 -27
  7. data/.gitignore +0 -6
  8. data/.rspec +0 -2
  9. data/Dockerfile +0 -14
  10. data/Gemfile +0 -4
  11. data/Guardfile +0 -23
  12. data/Rakefile +0 -11
  13. data/bin/proxy.rb +0 -3
  14. data/examples/README.md +0 -1
  15. data/examples/facebook_api.html +0 -59
  16. data/examples/intercept_request.html +0 -10
  17. data/examples/post_api.html +0 -16
  18. data/examples/preflight_request.html +0 -22
  19. data/examples/tumblr_api.html +0 -22
  20. data/examples/tumblr_api_https.html +0 -22
  21. data/lib/tasks/billy.rake +0 -87
  22. data/log/.gitkeep +0 -0
  23. data/puffing-billy.gemspec +0 -41
  24. data/spec/features/examples/facebook_api_spec.rb +0 -23
  25. data/spec/features/examples/intercept_request_spec.rb +0 -31
  26. data/spec/features/examples/post_api_spec.rb +0 -15
  27. data/spec/features/examples/preflight_request_spec.rb +0 -29
  28. data/spec/features/examples/tumblr_api_spec.rb +0 -59
  29. data/spec/lib/billy/browsers/capybara_spec.rb +0 -28
  30. data/spec/lib/billy/cache_spec.rb +0 -158
  31. data/spec/lib/billy/handlers/cache_handler_spec.rb +0 -191
  32. data/spec/lib/billy/handlers/handler_spec.rb +0 -16
  33. data/spec/lib/billy/handlers/proxy_handler_spec.rb +0 -258
  34. data/spec/lib/billy/handlers/request_handler_spec.rb +0 -200
  35. data/spec/lib/billy/handlers/request_log_spec.rb +0 -74
  36. data/spec/lib/billy/handlers/stub_handler_spec.rb +0 -117
  37. data/spec/lib/billy/proxy_connection_spec.rb +0 -20
  38. data/spec/lib/billy/proxy_request_stub_spec.rb +0 -252
  39. data/spec/lib/billy/resource_utils_spec.rb +0 -55
  40. data/spec/lib/billy/ssl/authority_spec.rb +0 -84
  41. data/spec/lib/billy/ssl/certificate_chain_spec.rb +0 -39
  42. data/spec/lib/billy/ssl/certificate_spec.rb +0 -89
  43. data/spec/lib/billy/watir/watir_spec.rb +0 -18
  44. data/spec/lib/proxy_spec.rb +0 -431
  45. data/spec/spec_helper.rb +0 -52
  46. data/spec/support/test_server.rb +0 -79
@@ -1,431 +0,0 @@
1
- require 'spec_helper'
2
- require 'resolv'
3
-
4
- shared_examples_for 'a proxy server' do
5
- it 'should proxy GET requests' do
6
- expect(http.get('/echo').body).to eql 'GET /echo'
7
- end
8
-
9
- it 'should proxy POST requests' do
10
- expect(http.post('/echo', foo: 'bar').body).to eql "POST /echo\nfoo=bar"
11
- end
12
-
13
- it 'should proxy PUT requests' do
14
- expect(http.post('/echo', foo: 'bar').body).to eql "POST /echo\nfoo=bar"
15
- end
16
-
17
- it 'should proxy HEAD requests' do
18
- expect(http.head('/echo').headers['HTTP-X-EchoServer']).to eql 'HEAD /echo'
19
- end
20
-
21
- it 'should proxy DELETE requests' do
22
- expect(http.delete('/echo').body).to eql 'DELETE /echo'
23
- end
24
-
25
- it 'should proxy OPTIONS requests' do
26
- expect(http.run_request(:options, '/echo', nil, nil).body).to eql 'OPTIONS /echo'
27
- end
28
- end
29
-
30
- shared_examples_for 'a request stub' do
31
- it 'should stub GET requests' do
32
- proxy.stub("#{url}/foo")
33
- .and_return(text: 'hello, GET!')
34
- expect(http.get('/foo').body).to eql 'hello, GET!'
35
- end
36
-
37
- it 'should stub GET response statuses' do
38
- proxy.stub("#{url}/foo")
39
- .and_return(code: 200)
40
- expect(http.get('/foo').status).to eql 200
41
- end
42
-
43
- it 'should stub POST requests' do
44
- proxy.stub("#{url}/bar", method: :post)
45
- .and_return(text: 'hello, POST!')
46
- expect(http.post('/bar', foo: :bar).body).to eql 'hello, POST!'
47
- end
48
-
49
- it 'should stub PUT requests' do
50
- proxy.stub("#{url}/baz", method: :put)
51
- .and_return(text: 'hello, PUT!')
52
- expect(http.put('/baz', foo: :bar).body).to eql 'hello, PUT!'
53
- end
54
-
55
- it 'should stub HEAD requests' do
56
- proxy.stub("#{url}/bap", method: :head)
57
- .and_return(headers: { 'HTTP-X-Hello' => 'hello, HEAD!' })
58
- expect(http.head('/bap').headers['http-x-hello']).to eql 'hello, HEAD!'
59
- end
60
-
61
- it 'should stub DELETE requests' do
62
- proxy.stub("#{url}/bam", method: :delete)
63
- .and_return(text: 'hello, DELETE!')
64
- expect(http.delete('/bam').body).to eql 'hello, DELETE!'
65
- end
66
-
67
- it 'should stub OPTIONS requests' do
68
- proxy.stub("#{url}/bim", method: :options)
69
- .and_return(text: 'hello, OPTIONS!')
70
- expect(http.run_request(:options, '/bim', nil, nil).body).to eql 'hello, OPTIONS!'
71
- end
72
-
73
- it 'should expose the currently registered stubs' do
74
- stub1 = proxy.stub("#{url}/foo", method: :options)
75
- .and_return(text: 'hello, OPTIONS!')
76
- stub2 = proxy.stub("#{url}/bar", method: :options)
77
- .and_return(text: 'hello, OPTIONS!')
78
- expect(proxy.stubs).to eql([stub2, stub1])
79
- end
80
- end
81
-
82
- shared_examples_for 'a cache' do
83
- context 'whitelisted GET requests' do
84
- it 'should not be cached' do
85
- assert_noncached_url
86
- end
87
-
88
- context 'with ports' do
89
- before do
90
- rack_app_url = URI(http.url_prefix)
91
- Billy.config.whitelist = ["#{rack_app_url.host}:#{rack_app_url.port}"]
92
- end
93
-
94
- it 'should not be cached ' do
95
- assert_noncached_url
96
- end
97
- end
98
- end
99
-
100
- context 'non-whitelisted GET requests' do
101
- before do
102
- Billy.config.whitelist = []
103
- end
104
-
105
- it 'should be cached' do
106
- assert_cached_url
107
- end
108
-
109
- context 'with ports' do
110
- before do
111
- rack_app_url = URI(http.url_prefix)
112
- Billy.config.whitelist = ["#{rack_app_url.host}:#{rack_app_url.port + 1}"]
113
- end
114
-
115
- it 'should be cached' do
116
- assert_cached_url
117
- end
118
- end
119
- end
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
-
144
- context 'ignore_params GET requests' do
145
- before do
146
- Billy.config.ignore_params = ['/analytics']
147
- end
148
-
149
- it 'should be cached' do
150
- r = http.get('/analytics?some_param=5')
151
- expect(r.body).to eql 'GET /analytics'
152
- expect do
153
- expect do
154
- r = http.get('/analytics?some_param=20')
155
- end.to change { r.headers['HTTP-X-EchoCount'].to_i }.by(1)
156
- end.to_not change { r.body }
157
- end
158
- end
159
-
160
- context 'path_blacklist GET requests' do
161
- before do
162
- Billy.config.path_blacklist = ['/api']
163
- end
164
-
165
- it 'should be cached' do
166
- assert_cached_url('/api')
167
- end
168
-
169
- context 'path_blacklist includes regex' do
170
- before do
171
- Billy.config.path_blacklist = [/widgets$/]
172
- end
173
-
174
- it 'should not cache a non-match' do
175
- assert_noncached_url('/widgets/5/edit')
176
- end
177
-
178
- it 'should cache a match' do
179
- assert_cached_url('/widgets')
180
- end
181
- end
182
- end
183
-
184
- context 'cache persistence' do
185
- let(:cache_path) { Billy.config.cache_path }
186
- let(:cached_key) { proxy.cache.key('get', "#{url}/foo", '') }
187
- let(:cached_file) do
188
- f = cached_key + '.yml'
189
- File.join(cache_path, f)
190
- end
191
-
192
- before do
193
- Billy.config.whitelist = []
194
- Dir.mkdir(cache_path) unless Dir.exist?(cache_path)
195
- end
196
-
197
- after do
198
- File.delete(cached_file) if File.exist?(cached_file)
199
- end
200
-
201
- context 'enabled' do
202
- before { Billy.config.persist_cache = true }
203
-
204
- it 'should persist' do
205
- http.get('/foo')
206
- expect(File.exist?(cached_file)).to be true
207
- end
208
-
209
- it 'should be read initially from persistent cache' do
210
- File.open(cached_file, 'w') do |f|
211
- cached = {
212
- headers: {},
213
- content: 'GET /foo cached'
214
- }
215
- f.write(cached.to_yaml(Encoding: :Utf8))
216
- end
217
-
218
- r = http.get('/foo')
219
- expect(r.body).to eql 'GET /foo cached'
220
- end
221
-
222
- context 'cache_request_headers requests' do
223
- it 'should not be cached by default' do
224
- http.get('/foo')
225
- saved_cache = Billy.proxy.cache.fetch_from_persistence(cached_key)
226
- expect(saved_cache.keys).not_to include :request_headers
227
- end
228
-
229
- context 'when enabled' do
230
- before do
231
- Billy.config.cache_request_headers = true
232
- end
233
-
234
- it 'should be cached' do
235
- http.get('/foo')
236
- saved_cache = Billy.proxy.cache.fetch_from_persistence(cached_key)
237
- expect(saved_cache.keys).to include :request_headers
238
- end
239
- end
240
- end
241
-
242
- context 'ignore_cache_port requests' do
243
- it 'should be cached without port' do
244
- r = http.get('/foo')
245
- url = URI(r.env[:url])
246
- saved_cache = Billy.proxy.cache.fetch_from_persistence(cached_key)
247
-
248
- expect(saved_cache[:url]).to_not eql(url.to_s)
249
- expect(saved_cache[:url]).to eql(url.to_s.gsub(":#{url.port}", ''))
250
- end
251
- end
252
-
253
- context 'non_whitelisted_requests_disabled requests' do
254
- before { Billy.config.non_whitelisted_requests_disabled = true }
255
-
256
- it 'should raise error when disabled' do
257
- # TODO: Suppress stderr output: https://gist.github.com/adamstegman/926858
258
- expect { http.get('/foo') }.to raise_error(Faraday::ConnectionFailed, 'end of file reached')
259
- end
260
- end
261
-
262
- context 'non_successful_cache_disabled requests' do
263
- before do
264
- rack_app_url = URI(http_error.url_prefix)
265
- Billy.config.whitelist = ["#{rack_app_url.host}:#{rack_app_url.port}"]
266
- Billy.config.non_successful_cache_disabled = true
267
- end
268
-
269
- it 'should not cache non-successful response when enabled' do
270
- http_error.get('/foo')
271
- expect(File.exist?(cached_file)).to be false
272
- end
273
-
274
- it 'should cache successful response when enabled' do
275
- assert_cached_url
276
- end
277
- end
278
-
279
- context 'non_successful_error_level requests' do
280
- before do
281
- rack_app_url = URI(http_error.url_prefix)
282
- Billy.config.whitelist = ["#{rack_app_url.host}:#{rack_app_url.port}"]
283
- Billy.config.non_successful_error_level = :error
284
- end
285
-
286
- it 'should raise error for non-successful responses when :error' do
287
- expect { http_error.get('/foo') }.to raise_error(Faraday::ConnectionFailed)
288
- end
289
- end
290
- end
291
-
292
- context 'disabled' do
293
- before { Billy.config.persist_cache = false }
294
-
295
- it 'shouldnt persist' do
296
- http.get('/foo')
297
- expect(File.exist?(cached_file)).to be false
298
- end
299
- end
300
- end
301
-
302
- def assert_noncached_url(url = '/foo')
303
- r = http.get(url)
304
- expect(r.body).to eql "GET #{url}"
305
- expect do
306
- expect do
307
- r = http.get(url)
308
- end.to change { r.headers['HTTP-X-EchoCount'].to_i }.by(1)
309
- end.to_not change { r.body }
310
- end
311
-
312
- def assert_cached_url(url = '/foo')
313
- r = http.get(url)
314
- expect(r.body).to eql "GET #{url}"
315
- expect do
316
- expect do
317
- r = http.get(url)
318
- end.to_not change { r.headers['HTTP-X-EchoCount'] }
319
- end.to_not change { r.body }
320
- end
321
- end
322
-
323
- describe Billy::Proxy do
324
- before do
325
- # Adding non-valid Faraday options throw an error: https://github.com/arsduo/koala/pull/311
326
- # Valid options: :request, :proxy, :ssl, :builder, :url, :parallel_manager, :params, :headers, :builder_class
327
- faraday_options = {
328
- proxy: { uri: proxy.url },
329
- request: { timeout: 1.0 }
330
- }
331
- faraday_ssl_options = faraday_options.merge(ssl: {
332
- verify: true,
333
- ca_file: Billy.certificate_authority.cert_file
334
- })
335
-
336
- @http = Faraday.new @http_url, faraday_options
337
- @https = Faraday.new @https_url, faraday_ssl_options
338
- @http_error = Faraday.new @error_url, faraday_options
339
- end
340
-
341
- context 'proxying' do
342
- context 'HTTP' do
343
- let!(:http) { @http }
344
- it_should_behave_like 'a proxy server'
345
- end
346
-
347
- context 'HTTPS' do
348
- let!(:http) { @https }
349
- it_should_behave_like 'a proxy server'
350
- end
351
- end
352
-
353
- context 'stubbing' do
354
- context 'HTTP' do
355
- let!(:url) { @http_url }
356
- let!(:http) { @http }
357
- it_should_behave_like 'a request stub'
358
- end
359
-
360
- context 'HTTPS' do
361
- let!(:url) { @https_url }
362
- let!(:http) { @https }
363
- it_should_behave_like 'a request stub'
364
- end
365
- end
366
-
367
- context 'caching' do
368
- it 'defaults to nil scope' do
369
- expect(proxy.cache.scope).to be nil
370
- end
371
-
372
- context 'HTTP' do
373
- let!(:url) { @http_url }
374
- let!(:http) { @http }
375
- let!(:http_error) { @http_error }
376
- it_should_behave_like 'a cache'
377
- end
378
-
379
- context 'HTTPS' do
380
- let!(:url) { @https_url }
381
- let!(:http) { @https }
382
- let!(:http_error) { @http_error }
383
- it_should_behave_like 'a cache'
384
- end
385
-
386
- context 'with a cache scope' do
387
- let!(:url) { @http_url }
388
- let!(:http) { @http }
389
- let!(:http_error) { @http_error }
390
-
391
- before do
392
- proxy.cache.scope_to 'my_cache'
393
- end
394
-
395
- after do
396
- proxy.cache.use_default_scope
397
- end
398
-
399
- it_should_behave_like 'a cache'
400
-
401
- it 'uses the cache scope' do
402
- expect(proxy.cache.scope).to eq('my_cache')
403
- end
404
-
405
- it 'can be reset to the default scope' do
406
- proxy.cache.use_default_scope
407
- expect(proxy.cache.scope).to be nil
408
- end
409
-
410
- it 'can execute a block against a cache scope' do
411
- expect(proxy.cache.scope).to eq 'my_cache'
412
- proxy.cache.with_scope 'another_cache' do
413
- expect(proxy.cache.scope).to eq 'another_cache'
414
- end
415
- expect(proxy.cache.scope).to eq 'my_cache'
416
- end
417
-
418
- it 'requires a block to be passed to with_scope' do
419
- expect { proxy.cache.with_scope 'some_scope' }.to raise_error ArgumentError
420
- end
421
-
422
- it 'should have different keys for the same request under a different scope' do
423
- args = ['get', "#{url}/foo", '']
424
- key = proxy.cache.key(*args)
425
- proxy.cache.with_scope 'another_cache' do
426
- expect(proxy.cache.key(*args)).to_not eq key
427
- end
428
- end
429
- end
430
- end
431
- end
data/spec/spec_helper.rb DELETED
@@ -1,52 +0,0 @@
1
- Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
2
-
3
- require 'pry'
4
- require 'billy/capybara/rspec'
5
- require 'billy/watir/rspec'
6
- require 'rack'
7
- require 'logger'
8
- require 'fileutils'
9
- require 'webdrivers'
10
-
11
- $stdout.puts `#{::Selenium::WebDriver::Chrome::Service.driver_path.call} --version` if ENV['CI']
12
-
13
- browser = Billy::Browsers::Watir.new :chrome
14
-
15
- Capybara.configure do |config|
16
- config.app = Rack::Directory.new(File.expand_path('../../examples', __FILE__))
17
- config.server = :webrick
18
- config.javascript_driver = :selenium_chrome_headless_billy
19
- end
20
-
21
- Billy.configure do |config|
22
- config.logger = Logger.new(File.expand_path('../../log/test.log', __FILE__))
23
- end
24
-
25
- RSpec.configure do |config|
26
- include Billy::TestServer
27
- config.run_all_when_everything_filtered = true
28
- config.filter_run :focus
29
- config.order = 'random'
30
-
31
- config.before :suite do
32
- FileUtils.rm_rf(Billy.config.certs_path)
33
- FileUtils.rm_rf(Billy.config.cache_path)
34
- end
35
-
36
- config.before :all do
37
- start_test_servers
38
- @browser = browser
39
- end
40
-
41
- config.before :each do
42
- proxy.reset_cache
43
- end
44
-
45
- config.after :each do
46
- Billy.config.reset
47
- end
48
-
49
- config.after :suite do
50
- browser.close
51
- end
52
- end
@@ -1,79 +0,0 @@
1
- require 'eventmachine'
2
- require 'thin'
3
- require 'faraday'
4
-
5
- module Thin::Backends
6
- class TcpServer
7
- def get_port
8
- # seriously, eventmachine, how hard does getting a port have to be?
9
- Socket.unpack_sockaddr_in(EM.get_sockname(@signature)).first
10
- end
11
- end
12
- end
13
-
14
- module Billy
15
- module TestServer
16
- def initialize
17
- Thin::Logging.silent = true
18
- end
19
-
20
- def start_test_servers
21
- q = Queue.new
22
- Thread.new do
23
- EM.run do
24
- echo = echo_app_setup
25
-
26
- http_server = start_server(echo)
27
- q.push http_server.backend.get_port
28
-
29
- https_server = start_server(echo, true)
30
- q.push https_server.backend.get_port
31
-
32
- echo_error = echo_app_setup(500)
33
- error_server = start_server(echo_error)
34
- q.push error_server.backend.get_port
35
- end
36
- end
37
-
38
- @http_url = "http://127.0.0.1:#{q.pop}"
39
- @https_url = "https://127.0.0.1:#{q.pop}"
40
- @error_url = "http://127.0.0.1:#{q.pop}"
41
- end
42
-
43
- def echo_app_setup(response_code = 200)
44
- counter = 0
45
- Proc.new do |env|
46
- req_body = env['rack.input'].read
47
- request_info = "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"
48
- res_body = request_info
49
- res_body += "\n#{req_body}" unless req_body.empty?
50
- counter += 1
51
- [
52
- response_code,
53
- { 'HTTP-X-EchoServer' => request_info,
54
- 'HTTP-X-EchoCount' => "#{counter}" },
55
- [res_body]
56
- ]
57
- end
58
- end
59
-
60
- def certificate_chain(domain)
61
- ca = Billy.certificate_authority.cert
62
- cert = Billy::Certificate.new(domain)
63
- chain = Billy::CertificateChain.new(domain, cert.cert, ca)
64
- { private_key_file: cert.key_file,
65
- cert_chain_file: chain.file }
66
-
67
- end
68
-
69
- def start_server(echo, ssl = false)
70
- http_server = Thin::Server.new '127.0.0.1', 0, echo
71
- if ssl
72
- http_server.ssl = true
73
- http_server.ssl_options = certificate_chain('localhost')
74
- end
75
- http_server.start
76
- http_server
77
- end
78
- end
79
- end