puffing-billy 0.7.0 → 0.8.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 +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +42 -2
- data/examples/intercept_request.html +10 -0
- data/lib/billy/config.rb +4 -1
- data/lib/billy/handlers/cache_handler.rb +5 -0
- data/lib/billy/handlers/stub_handler.rb +1 -1
- data/lib/billy/proxy_request_stub.rb +26 -1
- data/lib/billy/version.rb +1 -1
- data/spec/features/examples/intercept_request_spec.rb +31 -0
- data/spec/lib/billy/handlers/cache_handler_spec.rb +17 -0
- data/spec/lib/billy/proxy_request_stub_spec.rb +52 -11
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab6b245ca1fa1295379ac58fcc023b9ae2d4be4b
|
4
|
+
data.tar.gz: d2ed68617bba9beca40b228fbfb116bed58f8641
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d4919dba7d0619860e035edf00580479228b3de38da97185b21356ba077f39c42add963de90f1521f30933e08f20c0e3494de359c892bb3b1e5fa1029bca704
|
7
|
+
data.tar.gz: dc18d1801cf9bb821a7fefa6f093cfdfe748f8ea500058f2d60f59e422c78c5135114bacf7f110acf9001c8ea0495e0899311e364d2cea7f84bf6110814db7b6
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
v0.8.0, 2016-06-02
|
2
|
+
------------------
|
3
|
+
* Add optional after_cache_handles_request callback for manipulating cached responses [#149](https://github.com/oesmith/puffing-billy/pull/149)
|
4
|
+
* Remove rspec-expectations deprecation warning for README example [#153](https://github.com/oesmith/puffing-billy/pull/153)
|
5
|
+
* Make stub requests accessible [#154](https://github.com/oesmith/puffing-billy/pull/154)
|
6
|
+
|
1
7
|
v0.7.0, 2016-05-05
|
2
8
|
------------------
|
3
9
|
* Change WebKit driver to ignore SSL errors [#140](https://github.com/oesmith/puffing-billy/pull/140)
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -23,7 +23,7 @@ you can test it!
|
|
23
23
|
it 'should stub google' do
|
24
24
|
proxy.stub('http://www.google.com/').and_return(:text => "I'm not Google!")
|
25
25
|
visit 'http://www.google.com/'
|
26
|
-
page.
|
26
|
+
expect(page).to have_content("I'm not Google!")
|
27
27
|
end
|
28
28
|
```
|
29
29
|
|
@@ -145,7 +145,7 @@ end
|
|
145
145
|
And /^a stub for google$/ do
|
146
146
|
proxy.stub('http://www.google.com/').and_return(:text => "I'm not Google!")
|
147
147
|
visit 'http://www.google.com/'
|
148
|
-
page.
|
148
|
+
expect(page).to have_content("I'm not Google!")
|
149
149
|
end
|
150
150
|
```
|
151
151
|
|
@@ -284,6 +284,25 @@ server is required to access the internet. Most common in larger companies.
|
|
284
284
|
|
285
285
|
`c.cache_request_body_methods` is used to specify HTTP methods of requests that you would like to cache separately based on the contents of the request body. The default is ['post'].
|
286
286
|
|
287
|
+
`c.after_cache_handles_request` is used to configure a callback that can operate on the response after it has been retrieved from the cache but before it is returned. The callback receives the request and response as arguments, with a request object like: `{ method: method, url: url, headers: headers, body: body }`. An example usage would be manipulating the Access-Control-Allow-Origin header so that your test server doesn't always have to run on the same port in order to accept cached responses to CORS requests:
|
288
|
+
|
289
|
+
```
|
290
|
+
Billy.configure do |c|
|
291
|
+
...
|
292
|
+
fix_cors_header = proc do |_request, response|
|
293
|
+
allowed_origins = response[:headers]['Access-Control-Allow-Origin']
|
294
|
+
if allowed_origins.present?
|
295
|
+
localhost_port_pattern = %r{(?<=http://127\.0\.0\.1:)(\d+)}
|
296
|
+
allowed_origins.sub!(
|
297
|
+
localhost_port_pattern, Capybara.current_session.server.port.to_s
|
298
|
+
)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
c.after_cache_handles_request = fix_cors_header
|
302
|
+
...
|
303
|
+
end
|
304
|
+
```
|
305
|
+
|
287
306
|
### Cache Scopes
|
288
307
|
|
289
308
|
If you need to cache different responses to the same HTTP request, you can use
|
@@ -346,6 +365,27 @@ RSpec.configure do |config|
|
|
346
365
|
end
|
347
366
|
```
|
348
367
|
|
368
|
+
## Stub requests recording
|
369
|
+
|
370
|
+
If you want to record requests to stubbed URIs, set the following configuration option:
|
371
|
+
|
372
|
+
```ruby
|
373
|
+
Billy.configure do |c|
|
374
|
+
c.record_stub_requests = true
|
375
|
+
end
|
376
|
+
```
|
377
|
+
|
378
|
+
Example usage:
|
379
|
+
|
380
|
+
```ruby
|
381
|
+
it 'should intercept a GET request' do
|
382
|
+
stub = proxy.stub('http://example.com/')
|
383
|
+
visit 'http://example.com/'
|
384
|
+
expect(stub.has_requests?).to be true
|
385
|
+
expect(stub.requests).not_to be_empty
|
386
|
+
end
|
387
|
+
```
|
388
|
+
|
349
389
|
## Proxy timeouts
|
350
390
|
|
351
391
|
By default, the Puffing Billy proxy will use the EventMachine:HttpRequest timeouts of 5 seconds
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<body>
|
3
|
+
<h1>Intercept request example</h1>
|
4
|
+
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.min.js'></script>
|
5
|
+
<script type='text/javascript'>
|
6
|
+
$(function () {
|
7
|
+
$.post('http://example.com/', { foo: 'bar' });
|
8
|
+
})
|
9
|
+
</script>
|
10
|
+
</body>
|
data/lib/billy/config.rb
CHANGED
@@ -10,7 +10,8 @@ module Billy
|
|
10
10
|
:persist_cache, :ignore_cache_port, :non_successful_cache_disabled, :non_successful_error_level,
|
11
11
|
:non_whitelisted_requests_disabled, :cache_path, :proxy_host, :proxy_port, :proxied_request_inactivity_timeout,
|
12
12
|
:proxied_request_connect_timeout, :dynamic_jsonp, :dynamic_jsonp_keys, :merge_cached_responses_whitelist,
|
13
|
-
:strip_query_params, :proxied_request_host, :proxied_request_port, :cache_request_body_methods
|
13
|
+
:strip_query_params, :proxied_request_host, :proxied_request_port, :cache_request_body_methods, :after_cache_handles_request,
|
14
|
+
:record_stub_requests
|
14
15
|
|
15
16
|
def initialize
|
16
17
|
@logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
|
@@ -40,6 +41,8 @@ module Billy
|
|
40
41
|
@proxied_request_host = nil
|
41
42
|
@proxied_request_port = 80
|
42
43
|
@cache_request_body_methods = ['post']
|
44
|
+
@after_cache_handles_request = nil
|
45
|
+
@record_stub_requests = false
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
@@ -25,6 +25,11 @@ module Billy
|
|
25
25
|
replace_response_callback(response, url)
|
26
26
|
end
|
27
27
|
|
28
|
+
if Billy.config.after_cache_handles_request
|
29
|
+
request = { method: method, url: url, headers: headers, body: body }
|
30
|
+
Billy.config.after_cache_handles_request.call(request, response)
|
31
|
+
end
|
32
|
+
|
28
33
|
return response
|
29
34
|
end
|
30
35
|
end
|
@@ -10,7 +10,7 @@ module Billy
|
|
10
10
|
if (stub = find_stub(method, url))
|
11
11
|
query_string = Addressable::URI.parse(url).query || ''
|
12
12
|
params = CGI.parse(query_string)
|
13
|
-
stub.call(params, headers, body).tap do |response|
|
13
|
+
stub.call(method, url, params, headers, body).tap do |response|
|
14
14
|
Billy.log(:info, "puffing-billy: STUB #{method} for '#{url}'")
|
15
15
|
return { status: response[0], headers: response[1], content: response[2] }
|
16
16
|
end
|
@@ -2,10 +2,13 @@ require 'multi_json'
|
|
2
2
|
|
3
3
|
module Billy
|
4
4
|
class ProxyRequestStub
|
5
|
+
attr_reader :requests
|
6
|
+
|
5
7
|
def initialize(url, options = {})
|
6
8
|
@options = { method: :get }.merge(options)
|
7
9
|
@method = @options[:method].to_s.upcase
|
8
10
|
@url = url
|
11
|
+
@requests = []
|
9
12
|
@response = { code: 204, headers: {}, text: '' }
|
10
13
|
end
|
11
14
|
|
@@ -14,7 +17,9 @@ module Billy
|
|
14
17
|
self
|
15
18
|
end
|
16
19
|
|
17
|
-
def call(params, headers, body)
|
20
|
+
def call(method, url, params, headers, body)
|
21
|
+
push_request(method, url, params, headers, body)
|
22
|
+
|
18
23
|
if @response.respond_to?(:call)
|
19
24
|
res = @response.call(params, headers, body)
|
20
25
|
else
|
@@ -52,6 +57,10 @@ module Billy
|
|
52
57
|
[code, headers, body]
|
53
58
|
end
|
54
59
|
|
60
|
+
def has_requests?
|
61
|
+
@requests.any?
|
62
|
+
end
|
63
|
+
|
55
64
|
def matches?(method, url)
|
56
65
|
if method == @method
|
57
66
|
if @url.is_a?(Regexp)
|
@@ -61,5 +70,21 @@ module Billy
|
|
61
70
|
end
|
62
71
|
end
|
63
72
|
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
attr_writer :requests
|
77
|
+
|
78
|
+
def push_request(method, url, params, headers, body)
|
79
|
+
if Billy.config.record_stub_requests
|
80
|
+
@requests.push({
|
81
|
+
method: method,
|
82
|
+
url: url,
|
83
|
+
params: params,
|
84
|
+
headers: headers,
|
85
|
+
body: body
|
86
|
+
})
|
87
|
+
end
|
88
|
+
end
|
64
89
|
end
|
65
90
|
end
|
data/lib/billy/version.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
describe 'intercept request example', type: :feature, js: true do
|
5
|
+
before do
|
6
|
+
Billy.config.record_stub_requests = true
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should intercept a GET request directly' do
|
10
|
+
stub = proxy.stub('http://example.com/').and_return(
|
11
|
+
headers: { 'Access-Control-Allow-Origin' => '*' },
|
12
|
+
code: 200
|
13
|
+
)
|
14
|
+
visit 'http://example.com/'
|
15
|
+
expect(stub.has_requests?).to be true
|
16
|
+
expect(stub.requests).not_to be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should intercept a POST request through an intermediary page' do
|
20
|
+
stub = proxy.stub('http://example.com/', method: 'post').and_return(
|
21
|
+
headers: { 'Access-Control-Allow-Origin' => '*' },
|
22
|
+
code: 200
|
23
|
+
)
|
24
|
+
visit '/intercept_request.html'
|
25
|
+
Timeout::timeout(5) do
|
26
|
+
sleep(0.1) until stub.has_requests?
|
27
|
+
end
|
28
|
+
request = stub.requests.shift
|
29
|
+
expect(request[:body]).to eql 'foo=bar'
|
30
|
+
end
|
31
|
+
end
|
@@ -97,6 +97,23 @@ describe Billy::CacheHandler do
|
|
97
97
|
other_request[:headers],
|
98
98
|
other_request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'no jsonp but has parentheses()')
|
99
99
|
end
|
100
|
+
|
101
|
+
context 'when after_cache_handles_request is set' do
|
102
|
+
it "should call the callback with the request and response" do
|
103
|
+
allow(Billy.config).to receive(:after_cache_handles_request) do
|
104
|
+
proc do |request, response|
|
105
|
+
response[:headers]['Access-Control-Allow-Origin'] = "*"
|
106
|
+
response[:content] = request[:body]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
|
110
|
+
expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'The response body')
|
111
|
+
expect(handler.handle_request(request[:method],
|
112
|
+
request[:url],
|
113
|
+
request[:headers],
|
114
|
+
request[:body])).to eql(status: 200, headers: { 'Connection' => 'close', 'Access-Control-Allow-Origin' => "*" }, content: 'Some body')
|
115
|
+
end
|
116
|
+
end
|
100
117
|
end
|
101
118
|
|
102
119
|
context 'updating jsonp callback names disabled' do
|
@@ -62,7 +62,7 @@ describe Billy::ProxyRequestStub do
|
|
62
62
|
let(:subject) { Billy::ProxyRequestStub.new('url') }
|
63
63
|
|
64
64
|
it 'returns a 204 empty response' do
|
65
|
-
expect(subject.call({}, {}, nil)).to eql [204, { 'Content-Type' => 'text/plain' }, '']
|
65
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [204, { 'Content-Type' => 'text/plain' }, '']
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -71,7 +71,7 @@ describe Billy::ProxyRequestStub do
|
|
71
71
|
|
72
72
|
it 'should generate bare responses' do
|
73
73
|
subject.and_return body: 'baz foo bar'
|
74
|
-
expect(subject.call({}, {}, nil)).to eql [
|
74
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [
|
75
75
|
200,
|
76
76
|
{},
|
77
77
|
'baz foo bar'
|
@@ -80,7 +80,7 @@ describe Billy::ProxyRequestStub do
|
|
80
80
|
|
81
81
|
it 'should generate text responses' do
|
82
82
|
subject.and_return text: 'foo bar baz'
|
83
|
-
expect(subject.call({}, {}, nil)).to eql [
|
83
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [
|
84
84
|
200,
|
85
85
|
{ 'Content-Type' => 'text/plain' },
|
86
86
|
'foo bar baz'
|
@@ -89,7 +89,7 @@ describe Billy::ProxyRequestStub do
|
|
89
89
|
|
90
90
|
it 'should generate JSON responses' do
|
91
91
|
subject.and_return json: { foo: 'bar' }
|
92
|
-
expect(subject.call({}, {}, nil)).to eql [
|
92
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [
|
93
93
|
200,
|
94
94
|
{ 'Content-Type' => 'application/json' },
|
95
95
|
'{"foo":"bar"}'
|
@@ -99,7 +99,7 @@ describe Billy::ProxyRequestStub do
|
|
99
99
|
context 'JSONP' do
|
100
100
|
it 'should generate JSONP responses' do
|
101
101
|
subject.and_return jsonp: { foo: 'bar' }
|
102
|
-
expect(subject.call({ 'callback' => ['baz'] }, {}, nil)).to eql [
|
102
|
+
expect(subject.call('', '', { 'callback' => ['baz'] }, {}, nil)).to eql [
|
103
103
|
200,
|
104
104
|
{ 'Content-Type' => 'application/javascript' },
|
105
105
|
'baz({"foo":"bar"})'
|
@@ -108,7 +108,7 @@ describe Billy::ProxyRequestStub do
|
|
108
108
|
|
109
109
|
it 'should generate JSONP responses with custom callback parameter' do
|
110
110
|
subject.and_return jsonp: { foo: 'bar' }, callback_param: 'cb'
|
111
|
-
expect(subject.call({ 'cb' => ['bap'] }, {}, nil)).to eql [
|
111
|
+
expect(subject.call('', '', { 'cb' => ['bap'] }, {}, nil)).to eql [
|
112
112
|
200,
|
113
113
|
{ 'Content-Type' => 'application/javascript' },
|
114
114
|
'bap({"foo":"bar"})'
|
@@ -117,7 +117,7 @@ describe Billy::ProxyRequestStub do
|
|
117
117
|
|
118
118
|
it 'should generate JSONP responses with custom callback name' do
|
119
119
|
subject.and_return jsonp: { foo: 'bar' }, callback: 'cb'
|
120
|
-
expect(subject.call({}, {}, nil)).to eql [
|
120
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [
|
121
121
|
200,
|
122
122
|
{ 'Content-Type' => 'application/javascript' },
|
123
123
|
'cb({"foo":"bar"})'
|
@@ -127,7 +127,7 @@ describe Billy::ProxyRequestStub do
|
|
127
127
|
|
128
128
|
it 'should generate redirection responses' do
|
129
129
|
subject.and_return redirect_to: 'http://example.com'
|
130
|
-
expect(subject.call({}, {}, nil)).to eql [
|
130
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [
|
131
131
|
302,
|
132
132
|
{ 'Location' => 'http://example.com' },
|
133
133
|
nil
|
@@ -136,7 +136,7 @@ describe Billy::ProxyRequestStub do
|
|
136
136
|
|
137
137
|
it 'should set headers' do
|
138
138
|
subject.and_return text: 'foo', headers: { 'HTTP-X-Foo' => 'bar' }
|
139
|
-
expect(subject.call({}, {}, nil)).to eql [
|
139
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [
|
140
140
|
200,
|
141
141
|
{ 'Content-Type' => 'text/plain', 'HTTP-X-Foo' => 'bar' },
|
142
142
|
'foo'
|
@@ -145,7 +145,7 @@ describe Billy::ProxyRequestStub do
|
|
145
145
|
|
146
146
|
it 'should set status codes' do
|
147
147
|
subject.and_return text: 'baz', code: 410
|
148
|
-
expect(subject.call({}, {}, nil)).to eql [
|
148
|
+
expect(subject.call('', '', {}, {}, nil)).to eql [
|
149
149
|
410,
|
150
150
|
{ 'Content-Type' => 'text/plain' },
|
151
151
|
'baz'
|
@@ -163,11 +163,52 @@ describe Billy::ProxyRequestStub do
|
|
163
163
|
expect(body).to eql 'body text'
|
164
164
|
{ code: 418, text: 'success' }
|
165
165
|
end)
|
166
|
-
expect(subject.call(expected_params, expected_headers, expected_body)).to eql [
|
166
|
+
expect(subject.call('', '', expected_params, expected_headers, expected_body)).to eql [
|
167
167
|
418,
|
168
168
|
{ 'Content-Type' => 'text/plain' },
|
169
169
|
'success'
|
170
170
|
]
|
171
171
|
end
|
172
172
|
end
|
173
|
+
|
174
|
+
context '#stub_requests' do
|
175
|
+
let(:subject) { Billy::ProxyRequestStub.new('url') }
|
176
|
+
|
177
|
+
before :each do
|
178
|
+
Billy.config.record_stub_requests = true
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should record requests' do
|
182
|
+
subject.call('', '', {}, {}, nil)
|
183
|
+
expect(subject.has_requests?).to be true
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should record multiple requests' do
|
187
|
+
expected_amount = 3
|
188
|
+
expected_amount.times do
|
189
|
+
subject.call('', '', {}, {}, nil)
|
190
|
+
end
|
191
|
+
|
192
|
+
expect(subject.requests.length).to eql expected_amount
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should set a request' do
|
196
|
+
expected_request = {
|
197
|
+
method: 'POST',
|
198
|
+
url: 'test-url',
|
199
|
+
params: { 'param1' => ['one'], 'param2' => ['two'] },
|
200
|
+
headers: { 'header1' => 'three', 'header2' => 'four' },
|
201
|
+
body: 'body text'
|
202
|
+
}
|
203
|
+
|
204
|
+
subject.call(
|
205
|
+
expected_request[:method],
|
206
|
+
expected_request[:url],
|
207
|
+
expected_request[:params],
|
208
|
+
expected_request[:headers],
|
209
|
+
expected_request[:body]
|
210
|
+
)
|
211
|
+
expect(subject.requests[0]).to eql expected_request
|
212
|
+
end
|
213
|
+
end
|
173
214
|
end
|
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: 0.
|
4
|
+
version: 0.8.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: 2016-
|
11
|
+
date: 2016-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -298,6 +298,7 @@ files:
|
|
298
298
|
- bin/proxy.rb
|
299
299
|
- examples/README.md
|
300
300
|
- examples/facebook_api.html
|
301
|
+
- examples/intercept_request.html
|
301
302
|
- examples/post_api.html
|
302
303
|
- examples/preflight_request.html
|
303
304
|
- examples/tumblr_api.html
|
@@ -325,6 +326,7 @@ files:
|
|
325
326
|
- log/.gitkeep
|
326
327
|
- puffing-billy.gemspec
|
327
328
|
- spec/features/examples/facebook_api_spec.rb
|
329
|
+
- spec/features/examples/intercept_request_spec.rb
|
328
330
|
- spec/features/examples/post_api_spec.rb
|
329
331
|
- spec/features/examples/preflight_request_spec.rb
|
330
332
|
- spec/features/examples/tumblr_api_spec.rb
|
@@ -366,6 +368,7 @@ specification_version: 4
|
|
366
368
|
summary: Easy request stubs for browser tests.
|
367
369
|
test_files:
|
368
370
|
- spec/features/examples/facebook_api_spec.rb
|
371
|
+
- spec/features/examples/intercept_request_spec.rb
|
369
372
|
- spec/features/examples/post_api_spec.rb
|
370
373
|
- spec/features/examples/preflight_request_spec.rb
|
371
374
|
- spec/features/examples/tumblr_api_spec.rb
|