puffing-billy 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +2 -2
- data/Guardfile +5 -5
- data/README.md +19 -1
- data/Rakefile +1 -1
- data/lib/billy.rb +17 -17
- data/lib/billy/cache.rb +30 -31
- data/lib/billy/config.rb +4 -2
- data/lib/billy/handlers/cache_handler.rb +5 -7
- data/lib/billy/handlers/handler.rb +2 -2
- data/lib/billy/handlers/proxy_handler.rb +16 -16
- data/lib/billy/handlers/request_handler.rb +6 -8
- data/lib/billy/handlers/stub_handler.rb +2 -2
- data/lib/billy/json_utils.rb +1 -2
- data/lib/billy/proxy_connection.rb +5 -5
- data/lib/billy/proxy_request_stub.rb +7 -7
- data/lib/billy/version.rb +1 -1
- data/lib/tasks/billy.rake +13 -15
- data/puffing-billy.gemspec +28 -28
- data/spec/features/examples/facebook_api_spec.rb +7 -7
- data/spec/features/examples/tumblr_api_spec.rb +6 -6
- data/spec/lib/billy/cache_spec.rb +14 -16
- data/spec/lib/billy/handlers/cache_handler_spec.rb +26 -24
- data/spec/lib/billy/handlers/handler_spec.rb +3 -3
- data/spec/lib/billy/handlers/proxy_handler_spec.rb +18 -16
- data/spec/lib/billy/handlers/request_handler_spec.rb +44 -42
- data/spec/lib/billy/handlers/stub_handler_spec.rb +14 -12
- data/spec/lib/billy/proxy_request_stub_spec.rb +55 -42
- data/spec/lib/billy/resource_utils_spec.rb +17 -17
- data/spec/lib/proxy_spec.rb +62 -70
- data/spec/spec_helper.rb +3 -3
- data/spec/support/test_server.rb +2 -2
- metadata +6 -6
@@ -6,9 +6,9 @@ module Billy
|
|
6
6
|
def_delegators :stub_handler, :stub
|
7
7
|
|
8
8
|
def handlers
|
9
|
-
@handlers ||= { :
|
10
|
-
:
|
11
|
-
:
|
9
|
+
@handlers ||= { stubs: StubHandler.new,
|
10
|
+
cache: CacheHandler.new,
|
11
|
+
proxy: ProxyHandler.new }
|
12
12
|
end
|
13
13
|
|
14
14
|
def handle_request(method, url, headers, body)
|
@@ -20,7 +20,7 @@ module Billy
|
|
20
20
|
end
|
21
21
|
|
22
22
|
body_msg = method == 'post' ? " with body '#{body}'" : ''
|
23
|
-
{ :
|
23
|
+
{ error: "Connection to #{url}#{body_msg} not cached and new http connections are disabled" }
|
24
24
|
end
|
25
25
|
|
26
26
|
def handles_request?(method, url, headers, body)
|
@@ -32,9 +32,7 @@ module Billy
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def reset
|
35
|
-
handlers.each_value
|
36
|
-
handler.reset
|
37
|
-
end
|
35
|
+
handlers.each_value(&:reset)
|
38
36
|
end
|
39
37
|
|
40
38
|
def reset_stubs
|
@@ -46,7 +44,7 @@ module Billy
|
|
46
44
|
end
|
47
45
|
|
48
46
|
def restore_cache
|
49
|
-
warn
|
47
|
+
warn '[DEPRECATION] `restore_cache` is deprecated as cache files are dynamically checked. Use `reset_cache` if you just want to clear the cache.'
|
50
48
|
reset_cache
|
51
49
|
end
|
52
50
|
|
@@ -8,7 +8,7 @@ module Billy
|
|
8
8
|
def handle_request(method, url, headers, body)
|
9
9
|
if handles_request?(method, url, headers, body)
|
10
10
|
if (stub = find_stub(method, url))
|
11
|
-
query_string = Addressable::URI.parse(url).query ||
|
11
|
+
query_string = Addressable::URI.parse(url).query || ''
|
12
12
|
params = CGI.parse(query_string)
|
13
13
|
stub.call(params, headers, body).tap do |response|
|
14
14
|
Billy.log(:info, "puffing-billy: STUB #{method} for '#{url}'")
|
@@ -20,7 +20,7 @@ module Billy
|
|
20
20
|
nil
|
21
21
|
end
|
22
22
|
|
23
|
-
def handles_request?(method, url,
|
23
|
+
def handles_request?(method, url, _headers, _body)
|
24
24
|
!find_stub(method, url).nil?
|
25
25
|
end
|
26
26
|
|
data/lib/billy/json_utils.rb
CHANGED
@@ -2,7 +2,6 @@ require 'json'
|
|
2
2
|
|
3
3
|
module Billy
|
4
4
|
module JSONUtils
|
5
|
-
|
6
5
|
def self.json?(value)
|
7
6
|
!!JSON.parse(value)
|
8
7
|
rescue JSON::ParserError, TypeError
|
@@ -33,7 +32,7 @@ module Billy
|
|
33
32
|
# Processing JSON in this way enables a consistent SHA to be derived from
|
34
33
|
# JSON payloads which have the same name/value pairs, but different orders.
|
35
34
|
def self.sort_json(json_str)
|
36
|
-
JSONUtils
|
35
|
+
JSONUtils.sort_hash_keys(JSON.parse(json_str, symbolize_names: true)).to_json
|
37
36
|
end
|
38
37
|
end
|
39
38
|
end
|
@@ -37,7 +37,7 @@ module Billy
|
|
37
37
|
else
|
38
38
|
if @ssl
|
39
39
|
uri = Addressable::URI.parse(@parser.request_url)
|
40
|
-
@url = "https://#{@ssl}#{[uri.path,uri.query].compact.join('?')}"
|
40
|
+
@url = "https://#{@ssl}#{[uri.path, uri.query].compact.join('?')}"
|
41
41
|
else
|
42
42
|
@url = @parser.request_url
|
43
43
|
end
|
@@ -52,17 +52,17 @@ module Billy
|
|
52
52
|
@parser = Http::Parser.new(self)
|
53
53
|
send_data("HTTP/1.0 200 Connection established\r\nProxy-agent: Puffing-Billy/0.0.0\r\n\r\n")
|
54
54
|
start_tls(
|
55
|
-
:
|
56
|
-
:
|
55
|
+
private_key_file: File.expand_path('../mitm.key', __FILE__),
|
56
|
+
cert_chain_file: File.expand_path('../mitm.crt', __FILE__)
|
57
57
|
)
|
58
58
|
end
|
59
59
|
|
60
60
|
def handle_request
|
61
61
|
EM.synchrony do
|
62
62
|
handler.handle_request(@parser.http_method, @url, @headers, @body).tap do |response|
|
63
|
-
if response.
|
63
|
+
if response.key?(:error)
|
64
64
|
close_connection
|
65
|
-
|
65
|
+
fail "puffing-billy: #{response[:error]}"
|
66
66
|
else
|
67
67
|
send_response(response)
|
68
68
|
end
|
@@ -3,10 +3,10 @@ require 'multi_json'
|
|
3
3
|
module Billy
|
4
4
|
class ProxyRequestStub
|
5
5
|
def initialize(url, options = {})
|
6
|
-
@options = {:
|
6
|
+
@options = { method: :get }.merge(options)
|
7
7
|
@method = @options[:method].to_s.upcase
|
8
8
|
@url = url
|
9
|
-
@response = {code: 204, headers: {}, text:
|
9
|
+
@response = { code: 204, headers: {}, text: '' }
|
10
10
|
end
|
11
11
|
|
12
12
|
def and_return(response)
|
@@ -27,10 +27,10 @@ module Billy
|
|
27
27
|
headers['Content-Type'] = res[:content_type] if res[:content_type]
|
28
28
|
|
29
29
|
if res[:json]
|
30
|
-
headers = {'Content-Type' => 'application/json'}.merge(headers)
|
30
|
+
headers = { 'Content-Type' => 'application/json' }.merge(headers)
|
31
31
|
body = MultiJson.dump(res[:json])
|
32
32
|
elsif res[:jsonp]
|
33
|
-
headers = {'Content-Type' => 'application/javascript'}.merge(headers)
|
33
|
+
headers = { 'Content-Type' => 'application/javascript' }.merge(headers)
|
34
34
|
if res[:callback]
|
35
35
|
callback = res[:callback]
|
36
36
|
elsif res[:callback_param]
|
@@ -40,11 +40,11 @@ module Billy
|
|
40
40
|
end
|
41
41
|
body = "#{callback}(#{MultiJson.dump(res[:jsonp])})"
|
42
42
|
elsif res[:text]
|
43
|
-
headers = {'Content-Type' => 'text/plain'}.merge(headers)
|
43
|
+
headers = { 'Content-Type' => 'text/plain' }.merge(headers)
|
44
44
|
body = res[:text]
|
45
45
|
elsif res[:redirect_to]
|
46
46
|
code = 302
|
47
|
-
headers = {'Location' => res[:redirect_to]}
|
47
|
+
headers = { 'Location' => res[:redirect_to] }
|
48
48
|
else
|
49
49
|
body = res[:body]
|
50
50
|
end
|
@@ -57,7 +57,7 @@ module Billy
|
|
57
57
|
if @url.is_a?(Regexp)
|
58
58
|
url.match(@url)
|
59
59
|
else
|
60
|
-
url.split('?')[0] == @url
|
60
|
+
Billy.config.strip_query_params ? (url.split('?')[0] == @url) : (url == @url)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
data/lib/billy/version.rb
CHANGED
data/lib/tasks/billy.rake
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'addressable/uri'
|
2
2
|
|
3
3
|
namespace :cache do
|
4
|
-
|
5
4
|
desc 'Print out all cache file information'
|
6
5
|
task :print_all do
|
7
6
|
cache_array = load_cache
|
@@ -12,9 +11,9 @@ namespace :cache do
|
|
12
11
|
end
|
13
12
|
|
14
13
|
desc 'Print out specific cache file information'
|
15
|
-
task :print_details, :sha do |
|
16
|
-
|
17
|
-
cache_array = load_cache(Billy.config.cache_path, '*'+args[:sha]+'*.yml')
|
14
|
+
task :print_details, :sha do |_t, args|
|
15
|
+
fail "Missing sha; usage: rake cache:print_details['<sha>']" unless args[:sha]
|
16
|
+
cache_array = load_cache(Billy.config.cache_path, '*' + args[:sha] + '*.yml')
|
18
17
|
|
19
18
|
sort_cache(cache_array).each do |cache|
|
20
19
|
print_cache_details(cache)
|
@@ -22,10 +21,10 @@ namespace :cache do
|
|
22
21
|
end
|
23
22
|
|
24
23
|
desc 'Find specific cache files by URL'
|
25
|
-
task :find_by_url, :api_path do |
|
26
|
-
|
24
|
+
task :find_by_url, :api_path do |_t, args|
|
25
|
+
fail "Missing api path; usage: rake cache:find_by_url['<api_path>']" unless args[:api_path]
|
27
26
|
cache_array = load_cache
|
28
|
-
filtered_cache_array = cache_array.select {|f| f[:url_path].include?(args[:api_path]) }
|
27
|
+
filtered_cache_array = cache_array.select { |f| f[:url_path].include?(args[:api_path]) }
|
29
28
|
|
30
29
|
sort_cache(filtered_cache_array).each do |cache|
|
31
30
|
print_cache_details(cache)
|
@@ -33,10 +32,10 @@ namespace :cache do
|
|
33
32
|
end
|
34
33
|
|
35
34
|
desc 'Find specific cache files by scope'
|
36
|
-
task :find_by_scope, :scope do |
|
37
|
-
|
35
|
+
task :find_by_scope, :scope do |_t, args|
|
36
|
+
fail "Missing scope; usage: rake cache:find_by_scope['<scope>']" unless args[:scope]
|
38
37
|
cache_array = load_cache
|
39
|
-
filtered_cache_array = cache_array.select {|f| f[:scope] && f[:scope].include?(args[:scope]) }
|
38
|
+
filtered_cache_array = cache_array.select { |f| f[:scope] && f[:scope].include?(args[:scope]) }
|
40
39
|
|
41
40
|
sort_cache(filtered_cache_array).each do |cache|
|
42
41
|
print_cache_details(cache)
|
@@ -46,7 +45,7 @@ namespace :cache do
|
|
46
45
|
desc 'Find cache files with non-successful status codes'
|
47
46
|
task :find_non_successful do
|
48
47
|
cache_array = load_cache
|
49
|
-
filtered_cache_array = cache_array.select {|f| !(200..299).include?(f[:status]) }
|
48
|
+
filtered_cache_array = cache_array.select { |f| !(200..299).include?(f[:status]) }
|
50
49
|
|
51
50
|
sort_cache(filtered_cache_array).each do |cache|
|
52
51
|
print_cache_details(cache)
|
@@ -57,11 +56,11 @@ namespace :cache do
|
|
57
56
|
cache_path = Rails.root.join(cache_directory)
|
58
57
|
cache_array = []
|
59
58
|
|
60
|
-
Dir.glob(cache_path+file_pattern) do |filename|
|
59
|
+
Dir.glob(cache_path + file_pattern) do |filename|
|
61
60
|
data = load_cache_file(filename)
|
62
61
|
url = Addressable::URI.parse(data[:url])
|
63
|
-
data[:url_path] = "#{url.path}#{url.query ? '?'+url.query : ''}#{url.fragment ? '#'+url.fragment : ''}"
|
64
|
-
data[:filename] = filename.gsub(Rails.root.to_s+'/','')
|
62
|
+
data[:url_path] = "#{url.path}#{url.query ? '?' + url.query : ''}#{url.fragment ? '#' + url.fragment : ''}"
|
63
|
+
data[:filename] = filename.gsub(Rails.root.to_s + '/', '')
|
65
64
|
cache_array << data
|
66
65
|
end
|
67
66
|
cache_array
|
@@ -85,5 +84,4 @@ namespace :cache do
|
|
85
84
|
def sort_cache(cache, key = :url_path)
|
86
85
|
cache.sort_by { |hsh| hsh[key] }
|
87
86
|
end
|
88
|
-
|
89
87
|
end
|
data/puffing-billy.gemspec
CHANGED
@@ -2,36 +2,36 @@
|
|
2
2
|
require File.expand_path('../lib/billy/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = [
|
6
|
-
gem.email = [
|
7
|
-
gem.description =
|
8
|
-
gem.summary =
|
9
|
-
gem.homepage =
|
5
|
+
gem.authors = ['Olly Smith']
|
6
|
+
gem.email = ['olly.smith@gmail.com']
|
7
|
+
gem.description = 'A stubbing proxy server for ruby. Connect it to your browser in integration tests to fake interactions with remote HTTP(S) servers.'
|
8
|
+
gem.summary = 'Easy request stubs for browser tests.'
|
9
|
+
gem.homepage = 'https://github.com/oesmith/puffing-billy'
|
10
10
|
|
11
|
-
gem.files = `git ls-files`.split(
|
12
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
11
|
+
gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
13
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
-
gem.name =
|
15
|
-
gem.require_paths = [
|
14
|
+
gem.name = 'puffing-billy'
|
15
|
+
gem.require_paths = ['lib']
|
16
16
|
gem.version = Billy::VERSION
|
17
17
|
|
18
|
-
gem.add_development_dependency
|
19
|
-
gem.add_development_dependency
|
20
|
-
gem.add_development_dependency
|
21
|
-
gem.add_development_dependency
|
22
|
-
gem.add_development_dependency
|
23
|
-
gem.add_development_dependency
|
24
|
-
gem.add_development_dependency
|
25
|
-
gem.add_development_dependency
|
26
|
-
gem.add_development_dependency
|
27
|
-
gem.add_development_dependency
|
28
|
-
gem.add_development_dependency
|
29
|
-
gem.add_development_dependency
|
30
|
-
gem.add_runtime_dependency
|
31
|
-
gem.add_runtime_dependency
|
32
|
-
gem.add_runtime_dependency
|
33
|
-
gem.add_runtime_dependency
|
34
|
-
gem.add_runtime_dependency
|
35
|
-
gem.add_runtime_dependency
|
36
|
-
gem.add_runtime_dependency
|
18
|
+
gem.add_development_dependency 'rspec'
|
19
|
+
gem.add_development_dependency 'thin'
|
20
|
+
gem.add_development_dependency 'faraday'
|
21
|
+
gem.add_development_dependency 'poltergeist'
|
22
|
+
gem.add_development_dependency 'selenium-webdriver'
|
23
|
+
gem.add_development_dependency 'capybara'
|
24
|
+
gem.add_development_dependency 'capybara-webkit', '~> 1.0'
|
25
|
+
gem.add_development_dependency 'rack'
|
26
|
+
gem.add_development_dependency 'guard'
|
27
|
+
gem.add_development_dependency 'rb-inotify'
|
28
|
+
gem.add_development_dependency 'pry'
|
29
|
+
gem.add_development_dependency 'cucumber'
|
30
|
+
gem.add_runtime_dependency 'addressable'
|
31
|
+
gem.add_runtime_dependency 'eventmachine'
|
32
|
+
gem.add_runtime_dependency 'em-synchrony'
|
33
|
+
gem.add_runtime_dependency 'em-http-request', '~> 1.1.0'
|
34
|
+
gem.add_runtime_dependency 'eventmachine_httpserver'
|
35
|
+
gem.add_runtime_dependency 'http_parser.rb', '~> 0.6.0'
|
36
|
+
gem.add_runtime_dependency 'multi_json'
|
37
37
|
end
|
@@ -1,22 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'base64'
|
3
3
|
|
4
|
-
describe 'Facebook API example', :
|
4
|
+
describe 'Facebook API example', type: :feature, js: true do
|
5
5
|
before do
|
6
|
-
proxy.stub('https://www.facebook.com:443/dialog/oauth').and_return(
|
6
|
+
proxy.stub('https://www.facebook.com:443/dialog/oauth').and_return(proc do |params, _, _|
|
7
7
|
# mock a signed request from facebook. the JS api never verifies the
|
8
8
|
# signature, so all it needs is the base64-encoded payload
|
9
9
|
signed_request = "xxxxxxxxxx.#{Base64.encode64('{"user_id":"1234567"}')}"
|
10
10
|
# redirect to the 'redirect_uri', with some extra crap in the query string
|
11
|
-
{:
|
12
|
-
|
11
|
+
{ redirect_to: "#{params['redirect_uri'][0]}&access_token=foobar&expires_in=600&base_domain=localhost&https=1&signed_request=#{signed_request}" }
|
12
|
+
end)
|
13
13
|
|
14
|
-
proxy.stub('https://graph.facebook.com:443/me').and_return(:
|
14
|
+
proxy.stub('https://graph.facebook.com:443/me').and_return(jsonp: { name: 'Tester 1' })
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should show me as logged-in' do
|
18
18
|
visit '/facebook_api.html'
|
19
|
-
click_on
|
20
|
-
expect(page).to have_content
|
19
|
+
click_on 'Login'
|
20
|
+
expect(page).to have_content 'Hi, Tester 1'
|
21
21
|
end
|
22
22
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe 'Tumblr API example', :
|
3
|
+
describe 'Tumblr API example', type: :feature, js: true do
|
4
4
|
before do
|
5
5
|
proxy.stub('http://blog.howmanyleft.co.uk/api/read/json').and_return(
|
6
|
-
:
|
7
|
-
:
|
6
|
+
jsonp: {
|
7
|
+
posts: [
|
8
8
|
{
|
9
9
|
'regular-title' => 'News Item 1',
|
10
10
|
'url-with-slug' => 'http://example.com/news/1',
|
@@ -16,14 +16,14 @@ describe 'Tumblr API example', :type => :feature, :js => true do
|
|
16
16
|
'regular-body' => 'News item 2 content here'
|
17
17
|
}
|
18
18
|
]
|
19
|
-
|
19
|
+
})
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'should show news stories' do
|
23
23
|
visit '/tumblr_api.html'
|
24
|
-
expect(page).to have_link('News Item 1', :
|
24
|
+
expect(page).to have_link('News Item 1', href: 'http://example.com/news/1')
|
25
25
|
expect(page).to have_content('News item 1 content here')
|
26
|
-
expect(page).to have_link('News Item 2', :
|
26
|
+
expect(page).to have_link('News Item 2', href: 'http://example.com/news/2')
|
27
27
|
expect(page).to have_content('News item 2 content here')
|
28
28
|
end
|
29
29
|
end
|
@@ -27,13 +27,13 @@ describe Billy::Cache do
|
|
27
27
|
expect { cache.format_url(pipe_url) }.not_to raise_error
|
28
28
|
end
|
29
29
|
|
30
|
-
context
|
30
|
+
context 'when dynamic_jsonp is true' do
|
31
31
|
it 'omits the callback param by default' do
|
32
32
|
expect(cache.format_url(params_url_with_callback, false, true)).to eq params_url
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'omits the params listed in Billy.config.dynamic_jsonp_keys' do
|
36
|
-
allow(Billy.config).to receive(:dynamic_jsonp_keys) { [
|
36
|
+
allow(Billy.config).to receive(:dynamic_jsonp_keys) { ['foo'] }
|
37
37
|
|
38
38
|
expect(cache.format_url(params_url_with_callback, false, true)).to eq "#{base_url}?callback=quux"
|
39
39
|
end
|
@@ -56,11 +56,10 @@ describe Billy::Cache do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
context
|
60
|
-
|
61
|
-
let(:
|
62
|
-
let(:
|
63
|
-
let(:regular_url) { "http://www.example-analytics.com/user.js" }
|
59
|
+
context 'with merge_cached_responses_whitelist set' do
|
60
|
+
let(:analytics_url1) { 'http://www.example-analytics.com/user/SDF879932/' }
|
61
|
+
let(:analytics_url2) { 'http://www.example-analytics.com/user/OIWEMLW39/' }
|
62
|
+
let(:regular_url) { 'http://www.example-analytics.com/user.js' }
|
64
63
|
|
65
64
|
let(:regex_to_match_analytics_urls_only) do
|
66
65
|
# Note that it matches the forward slash at the end of the URL, which doesn't match regular_url:
|
@@ -74,19 +73,18 @@ describe Billy::Cache do
|
|
74
73
|
end
|
75
74
|
|
76
75
|
it "has one cache key for the two analytics urls that match, and a separate one for the other that doesn't" do
|
77
|
-
expect(cache.key(
|
78
|
-
expect(cache.key(
|
76
|
+
expect(cache.key('post', analytics_url1, 'body')).to eq cache.key('post', analytics_url2, 'body')
|
77
|
+
expect(cache.key('post', analytics_url1, 'body')).not_to eq cache.key('post', regular_url, 'body')
|
79
78
|
end
|
80
79
|
|
81
|
-
it
|
82
|
-
identical_cache_key =
|
83
|
-
distinct_cache_key =
|
80
|
+
it 'More specifically, the cache keys should be identical for the 2 analytics urls' do
|
81
|
+
identical_cache_key = 'post_5fcb7a450e4cd54dcffcb526212757ee0ca9dc17'
|
82
|
+
distinct_cache_key = 'post_www.example-analytics.com_81f097654a523bd7ddb10fd4aee781723e076a1a_02083f4579e08a612425c0c1a17ee47add783b94'
|
84
83
|
|
85
|
-
expect(cache.key(
|
86
|
-
expect(cache.key(
|
87
|
-
expect(cache.key(
|
84
|
+
expect(cache.key('post', analytics_url1, 'body')).to eq identical_cache_key
|
85
|
+
expect(cache.key('post', regular_url, 'body')).to eq distinct_cache_key
|
86
|
+
expect(cache.key('post', analytics_url2, 'body')).to eq identical_cache_key
|
88
87
|
end
|
89
|
-
|
90
88
|
end
|
91
89
|
end
|
92
90
|
end
|
@@ -2,13 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Billy::CacheHandler do
|
4
4
|
let(:handler) { Billy::CacheHandler.new }
|
5
|
-
let(:request)
|
5
|
+
let(:request) do
|
6
|
+
{
|
6
7
|
method: 'post',
|
7
8
|
url: 'http://example.test:8080/index?some=param&callback=dynamicCallback5678',
|
8
|
-
headers: {'Accept-Encoding' => 'gzip',
|
9
|
-
|
9
|
+
headers: { 'Accept-Encoding' => 'gzip',
|
10
|
+
'Cache-Control' => 'no-cache' },
|
10
11
|
body: 'Some body'
|
11
|
-
|
12
|
+
}
|
13
|
+
end
|
12
14
|
|
13
15
|
it 'delegates #reset to the cache' do
|
14
16
|
expect(Billy::Cache.instance).to receive(:reset).at_least(:once)
|
@@ -23,12 +25,12 @@ describe Billy::CacheHandler do
|
|
23
25
|
describe '#handles_request?' do
|
24
26
|
it 'handles the request if it is cached' do
|
25
27
|
expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
|
26
|
-
expect(handler.handles_request?(nil,nil,nil,nil)).to be true
|
28
|
+
expect(handler.handles_request?(nil, nil, nil, nil)).to be true
|
27
29
|
end
|
28
30
|
|
29
31
|
it 'does not handle the request if it is not cached' do
|
30
32
|
expect(Billy::Cache.instance).to receive(:cached?).and_return(false)
|
31
|
-
expect(handler.handles_request?(nil,nil,nil,nil)).to be false
|
33
|
+
expect(handler.handles_request?(nil, nil, nil, nil)).to be false
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -43,11 +45,11 @@ describe Billy::CacheHandler do
|
|
43
45
|
|
44
46
|
it 'returns a cached response if the request can be handled' do
|
45
47
|
expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
|
46
|
-
expect(Billy::Cache.instance).to receive(:fetch).and_return(
|
48
|
+
expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'The response body')
|
47
49
|
expect(handler.handle_request(request[:method],
|
48
50
|
request[:url],
|
49
51
|
request[:headers],
|
50
|
-
request[:body])).to eql(
|
52
|
+
request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'The response body')
|
51
53
|
end
|
52
54
|
|
53
55
|
context 'updating jsonp callback names enabled' do
|
@@ -57,20 +59,20 @@ describe Billy::CacheHandler do
|
|
57
59
|
|
58
60
|
it 'updates the cached response if the callback is dynamic' do
|
59
61
|
expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
|
60
|
-
expect(Billy::Cache.instance).to receive(:fetch).and_return(
|
62
|
+
expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
|
61
63
|
expect(handler.handle_request(request[:method],
|
62
64
|
request[:url],
|
63
65
|
request[:headers],
|
64
|
-
request[:body])).to eql(
|
66
|
+
request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback5678({"yolo":"kitten"})')
|
65
67
|
end
|
66
68
|
|
67
69
|
it 'is flexible about the format of the response body' do
|
68
70
|
expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
|
69
|
-
expect(Billy::Cache.instance).to receive(:fetch).and_return(
|
71
|
+
expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: "/**/ dynamicCallback1234(\n{\"yolo\":\"kitten\"})")
|
70
72
|
expect(handler.handle_request(request[:method],
|
71
73
|
request[:url],
|
72
74
|
request[:headers],
|
73
|
-
request[:body])).to eql(
|
75
|
+
request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: "/**/ dynamicCallback5678(\n{\"yolo\":\"kitten\"})")
|
74
76
|
end
|
75
77
|
|
76
78
|
it 'does not interfere with non-jsonp requests' do
|
@@ -78,22 +80,22 @@ describe Billy::CacheHandler do
|
|
78
80
|
other_request = {
|
79
81
|
method: 'get',
|
80
82
|
url: 'http://example.test:8080/index?hanukkah=latkes',
|
81
|
-
headers: {'Accept-Encoding'=>'gzip', 'Cache-Control'=>'no-cache' },
|
83
|
+
headers: { 'Accept-Encoding' => 'gzip', 'Cache-Control' => 'no-cache' },
|
82
84
|
body: 'no jsonp'
|
83
85
|
}
|
84
86
|
|
85
87
|
allow(Billy::Cache.instance).to receive(:cached?).and_return(true)
|
86
|
-
allow(Billy::Cache.instance).to receive(:fetch).with(jsonp_request[:method], jsonp_request[:url], jsonp_request[:body]).and_return(
|
87
|
-
|
88
|
-
|
89
|
-
allow(Billy::Cache.instance).to receive(:fetch).with(other_request[:method], other_request[:url], other_request[:body]).and_return(
|
90
|
-
|
91
|
-
|
88
|
+
allow(Billy::Cache.instance).to receive(:fetch).with(jsonp_request[:method], jsonp_request[:url], jsonp_request[:body]).and_return(status: 200,
|
89
|
+
headers: { 'Connection' => 'close' },
|
90
|
+
content: 'dynamicCallback1234({"yolo":"kitten"})')
|
91
|
+
allow(Billy::Cache.instance).to receive(:fetch).with(other_request[:method], other_request[:url], other_request[:body]).and_return(status: 200,
|
92
|
+
headers: { 'Connection' => 'close' },
|
93
|
+
content: 'no jsonp but has parentheses()')
|
92
94
|
|
93
95
|
expect(handler.handle_request(other_request[:method],
|
94
|
-
|
95
|
-
|
96
|
-
|
96
|
+
other_request[:url],
|
97
|
+
other_request[:headers],
|
98
|
+
other_request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'no jsonp but has parentheses()')
|
97
99
|
end
|
98
100
|
end
|
99
101
|
|
@@ -104,11 +106,11 @@ describe Billy::CacheHandler do
|
|
104
106
|
|
105
107
|
it 'does not change the response' do
|
106
108
|
expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
|
107
|
-
expect(Billy::Cache.instance).to receive(:fetch).and_return(
|
109
|
+
expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
|
108
110
|
expect(handler.handle_request(request[:method],
|
109
111
|
request[:url],
|
110
112
|
request[:headers],
|
111
|
-
request[:body])).to eql(
|
113
|
+
request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
|
112
114
|
end
|
113
115
|
end
|
114
116
|
|