puffing-billy 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +65 -0
- data/Gemfile.lock +6 -3
- data/README.md +43 -3
- data/lib/billy.rb +5 -0
- data/lib/billy/cache.rb +21 -5
- data/lib/billy/config.rb +8 -1
- data/lib/billy/handlers/cache_handler.rb +51 -0
- data/lib/billy/handlers/handler.rb +45 -0
- data/lib/billy/handlers/proxy_handler.rb +112 -0
- data/lib/billy/handlers/request_handler.rb +59 -0
- data/lib/billy/handlers/stub_handler.rb +48 -0
- data/lib/billy/proxy.rb +11 -36
- data/lib/billy/proxy_connection.rb +18 -140
- data/lib/billy/version.rb +1 -1
- data/puffing-billy.gemspec +2 -1
- data/spec/features/examples/facebook_api_spec.rb +2 -3
- data/spec/features/examples/tumblr_api_spec.rb +1 -1
- data/spec/lib/billy/cache_spec.rb +18 -1
- data/spec/lib/billy/handlers/cache_handler_spec.rb +124 -0
- data/spec/lib/billy/handlers/handler_spec.rb +16 -0
- data/spec/lib/billy/handlers/proxy_handler_spec.rb +171 -0
- data/spec/lib/billy/handlers/request_handler_spec.rb +144 -0
- data/spec/lib/billy/handlers/stub_handler_spec.rb +71 -0
- data/spec/lib/billy/resource_utils_spec.rb +3 -3
- data/spec/lib/proxy_spec.rb +15 -8
- data/spec/spec_helper.rb +1 -1
- metadata +37 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30ec3de1e00ab91373eb88106e301a8fe9963701
|
4
|
+
data.tar.gz: 7300cdd6f73ae4e5a5a6e6a1dd6108cb9074d272
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e00330461d05f7fa3e3f01cad76e35e152f2ffc44c7b3633d0b780c60e714429185b7200897eaef6c0d96e7067a78cb1cd63e680013601f9f873f3e0f58eeff
|
7
|
+
data.tar.gz: 6d1099b167707b5c41f38444f81ff39c6d6a1753e8072fdbbca85c2e2a605c391591ebf095bff3b6173e4a7060304b0c30c52e1a92723f0c502bb7a4a78bf036
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
v0.3.0, 2014-12-29
|
2
|
+
------------------
|
3
|
+
|
4
|
+
* Fixing a bug where proxy to SSL can duplicate https in the request_url (#36)
|
5
|
+
* Refactor proxy responses (#37)
|
6
|
+
* Update http_parser to 0.6.0 and remove CONNECT request hack (#38)
|
7
|
+
* Allow configurable Billy proxy port (#40)
|
8
|
+
* Refactor handlers (#41)
|
9
|
+
* Mark step definitions as ruby code (#52)
|
10
|
+
* Adds EventMachine timeout configuration (#57)
|
11
|
+
* Support dynamic jsonp with params (#58)
|
12
|
+
* Writing error messages to the logger rather than stdout (#69)
|
13
|
+
* Don't recommend changing javascript_driver config (#70)
|
14
|
+
* README link pointing at wrong target (#73)
|
15
|
+
* Adding example config to README for playing nicely with Webmock, VCR (#74)
|
16
|
+
* Make dynamic_jsonp regex less brittle (#81)
|
17
|
+
|
18
|
+
v0.2.3, 2014-02-07
|
19
|
+
------------------
|
20
|
+
|
21
|
+
* Fixed facebook spec (#24)
|
22
|
+
* Check for existing persistent cache files on demand (#26)
|
23
|
+
* Lazy-loading proxy and other minor fixes (#28)
|
24
|
+
* Support service-oriented architectures, scope cache to scenarios, and sort JSON in POSTs to avoid duplicate cache files (#30)
|
25
|
+
* Set the minimum version of capybara-webkit to 1.0.0 (#31)
|
26
|
+
* Updated gems, cache request headers, handle non-successful responses, ability to stop new connections (#33)
|
27
|
+
* Add requires matching gem name (#34)
|
28
|
+
* Remove duplicated rspec devel dependency (#35)
|
29
|
+
|
30
|
+
v0.2.1, 2013-05-12
|
31
|
+
------------------
|
32
|
+
|
33
|
+
* Add cucumber documentation to readme. (#12)
|
34
|
+
* Use multi_json (#13)
|
35
|
+
* Remove require from Gemfile example (#14)
|
36
|
+
* Add a README example of returning headers (#16)
|
37
|
+
|
38
|
+
v0.2.0, 2013-03-17
|
39
|
+
------------------
|
40
|
+
|
41
|
+
* Update README with HTTPS quirk and trailing slash behaviour. (#3)
|
42
|
+
* Fixes to work with Capybara-Webkit (#6)
|
43
|
+
* VCR-like cache (#7)
|
44
|
+
|
45
|
+
v0.1.3, 2012-11-05
|
46
|
+
------------------
|
47
|
+
|
48
|
+
* Implemented caching
|
49
|
+
|
50
|
+
v0.1.2, 2012-10-12
|
51
|
+
------------------
|
52
|
+
|
53
|
+
* Slightly saner driver setup
|
54
|
+
* Updated README
|
55
|
+
|
56
|
+
v0.1.1, 2012-10-12
|
57
|
+
------------------
|
58
|
+
|
59
|
+
* Content encoding fixes
|
60
|
+
* Updated README
|
61
|
+
|
62
|
+
v0.1.0, 2012-10-11
|
63
|
+
------------------
|
64
|
+
|
65
|
+
* Initial release
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
puffing-billy (0.
|
4
|
+
puffing-billy (0.3.0)
|
5
5
|
capybara
|
6
6
|
em-http-request
|
7
|
+
em-synchrony
|
7
8
|
eventmachine
|
8
9
|
eventmachine_httpserver
|
9
|
-
http_parser.rb
|
10
|
+
http_parser.rb (~> 0.6.0)
|
10
11
|
multi_json
|
11
12
|
|
12
13
|
GEM
|
@@ -29,7 +30,7 @@ GEM
|
|
29
30
|
ffi (~> 1.0, >= 1.0.11)
|
30
31
|
cliver (0.3.2)
|
31
32
|
coderay (1.1.0)
|
32
|
-
cookiejar (0.3.
|
33
|
+
cookiejar (0.3.1)
|
33
34
|
cucumber (1.3.10)
|
34
35
|
builder (>= 2.1.2)
|
35
36
|
diff-lcs (>= 1.1.3)
|
@@ -46,6 +47,8 @@ GEM
|
|
46
47
|
http_parser.rb (>= 0.6.0)
|
47
48
|
em-socksify (0.3.0)
|
48
49
|
eventmachine (>= 1.0.0.beta.4)
|
50
|
+
em-synchrony (1.0.3)
|
51
|
+
eventmachine (>= 1.0.0.beta.1)
|
49
52
|
eventmachine (1.0.3)
|
50
53
|
eventmachine_httpserver (0.2.1)
|
51
54
|
faraday (0.9.0)
|
data/README.md
CHANGED
@@ -120,10 +120,9 @@ Feature: Stubbing via billy
|
|
120
120
|
|
121
121
|
And in steps:
|
122
122
|
|
123
|
-
```
|
123
|
+
```ruby
|
124
124
|
Before('@billy') do
|
125
125
|
Capybara.current_driver = :poltergeist_billy
|
126
|
-
Capybara.javascript_driver = :poltergeist_billy
|
127
126
|
end
|
128
127
|
|
129
128
|
And /^a stub for google$/ do
|
@@ -202,6 +201,18 @@ caching. You should mostly use this for analytics and various social buttons as
|
|
202
201
|
they use cache avoidance techniques, but return practically the same response
|
203
202
|
that most often does not affect your test results.
|
204
203
|
|
204
|
+
`c.dynamic_jsonp` is used to rewrite the body of JSONP responses based on the
|
205
|
+
callback parameter. For example, if a request to `http://example.com/foo?callback=bar`
|
206
|
+
returns `bar({"some": "json"});` and is recorded, then a later request to
|
207
|
+
`http://example.com/foo?callback=baz` will be a cache hit and respond with
|
208
|
+
`baz({"some": "json"});` This is useful because most JSONP implementations
|
209
|
+
base the callback name off of a timestamp or something else dynamic.
|
210
|
+
|
211
|
+
`c.dynamic_jsonp_keys` is used to configure which parameters to ignore when
|
212
|
+
using `c.dynamic_jsonp`. This is helpful when JSONP APIs use cache-busting
|
213
|
+
parameters. For example, if you want `http://example.com/foo?callback=bar&id=1&cache_bust=12345` and `http://example.com/foo?callback=baz&id=1&cache_bust=98765` to be cache hits for each other, you would set `c.dynamic_jsonp_keys = ['callback', 'cache_bust']` to ignore both params. Note
|
214
|
+
that in this example the `id` param would still be considered important.
|
215
|
+
|
205
216
|
`c.path_blacklist = []` is used to always cache specific paths on any hostnames,
|
206
217
|
including whitelisted ones. This is useful if your AUT has routes that get data
|
207
218
|
from external services, such as `/api` where the ajax request is a local URL but
|
@@ -287,13 +298,42 @@ RSpec.configure do |config|
|
|
287
298
|
end
|
288
299
|
```
|
289
300
|
|
301
|
+
## Proxy timeouts
|
302
|
+
|
303
|
+
By default, the Puffing Billy proxy will use the EventMachine:HttpRequest timeouts of 5 seconds
|
304
|
+
for connect and 10 seconds for inactivity when talking to downstream servers.
|
305
|
+
|
306
|
+
These can be configured as follows:
|
307
|
+
|
308
|
+
```ruby
|
309
|
+
Billy.configure do |c|
|
310
|
+
c.proxied_request_connect_timeout = 20
|
311
|
+
c.proxied_request_inactivity_timeout = 20
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
290
315
|
## Customising the javascript driver
|
291
316
|
|
292
317
|
If you use a customised Capybara driver, remember to set the proxy address
|
293
318
|
and tell it to ignore SSL certificate warnings. See
|
294
|
-
[lib/billy
|
319
|
+
[lib/billy.rb](https://github.com/oesmith/puffing-billy/blob/master/lib/billy.rb)
|
295
320
|
to see how Billy's default drivers are configured.
|
296
321
|
|
322
|
+
## Working with VCR and Webmock
|
323
|
+
If you use VCR and Webmock elsewhere in your specs, you will need to disable them
|
324
|
+
for your specs utilizing Puffing Billy. To do so, you can configure your `spec_helper.rb`
|
325
|
+
as shown below:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
RSpec.configure do |config|
|
329
|
+
config.around(:each, type: :feature) do |example|
|
330
|
+
WebMock.allow_net_connect!
|
331
|
+
VCR.turned_off { example.run }
|
332
|
+
WebMock.disable_net_connect!
|
333
|
+
end
|
334
|
+
end
|
335
|
+
```
|
336
|
+
|
297
337
|
## FAQ
|
298
338
|
|
299
339
|
1. Why name it after a train?
|
data/lib/billy.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
require "billy/version"
|
2
2
|
require "billy/config"
|
3
|
+
require "billy/handlers/handler"
|
4
|
+
require "billy/handlers/request_handler"
|
5
|
+
require "billy/handlers/stub_handler"
|
6
|
+
require "billy/handlers/proxy_handler"
|
7
|
+
require "billy/handlers/cache_handler"
|
3
8
|
require "billy/proxy_request_stub"
|
4
9
|
require "billy/cache"
|
5
10
|
require "billy/proxy"
|
data/lib/billy/cache.rb
CHANGED
@@ -2,9 +2,12 @@ require 'resolv'
|
|
2
2
|
require 'uri'
|
3
3
|
require 'yaml'
|
4
4
|
require 'billy/json_utils'
|
5
|
+
require 'singleton'
|
5
6
|
|
6
7
|
module Billy
|
7
8
|
class Cache
|
9
|
+
include Singleton
|
10
|
+
|
8
11
|
attr_reader :scope
|
9
12
|
|
10
13
|
def initialize
|
@@ -30,7 +33,7 @@ module Billy
|
|
30
33
|
begin
|
31
34
|
@cache[key] = YAML.load(File.open(cache_file(key))) if persisted?(key)
|
32
35
|
rescue ArgumentError => e
|
33
|
-
|
36
|
+
Billy.log :error, "Could not parse YAML: #{e.message}"
|
34
37
|
nil
|
35
38
|
end
|
36
39
|
end
|
@@ -83,14 +86,27 @@ module Billy
|
|
83
86
|
key
|
84
87
|
end
|
85
88
|
|
86
|
-
def format_url(url, ignore_params=false)
|
89
|
+
def format_url(url, ignore_params=false, dynamic_jsonp=Billy.config.dynamic_jsonp)
|
87
90
|
url = URI(url)
|
88
91
|
port_to_include = Billy.config.ignore_cache_port ? '' : ":#{url.port}"
|
89
92
|
formatted_url = url.scheme+'://'+url.host+port_to_include+url.path
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
+
|
94
|
+
return formatted_url if ignore_params
|
95
|
+
|
96
|
+
if url.query
|
97
|
+
query_string = if dynamic_jsonp
|
98
|
+
query_hash = Rack::Utils.parse_query(url.query)
|
99
|
+
Billy.config.dynamic_jsonp_keys.each{|k| query_hash.delete(k) }
|
100
|
+
Rack::Utils.build_query(query_hash)
|
101
|
+
else
|
102
|
+
url.query
|
103
|
+
end
|
104
|
+
|
105
|
+
formatted_url += "?#{query_string}"
|
93
106
|
end
|
107
|
+
|
108
|
+
formatted_url += '#'+url.fragment if url.fragment
|
109
|
+
|
94
110
|
formatted_url
|
95
111
|
end
|
96
112
|
|
data/lib/billy/config.rb
CHANGED
@@ -4,10 +4,12 @@ require 'tmpdir'
|
|
4
4
|
module Billy
|
5
5
|
class Config
|
6
6
|
DEFAULT_WHITELIST = ['127.0.0.1', 'localhost']
|
7
|
+
RANDOM_AVAILABLE_PORT = 0 # https://github.com/eventmachine/eventmachine/wiki/FAQ#wiki-can-i-start-a-server-on-a-random-available-port
|
7
8
|
|
8
9
|
attr_accessor :logger, :cache, :cache_request_headers, :whitelist, :path_blacklist, :ignore_params,
|
9
10
|
:persist_cache, :ignore_cache_port, :non_successful_cache_disabled, :non_successful_error_level,
|
10
|
-
:non_whitelisted_requests_disabled, :cache_path
|
11
|
+
:non_whitelisted_requests_disabled, :cache_path, :proxy_port, :proxied_request_inactivity_timeout,
|
12
|
+
:proxied_request_connect_timeout, :dynamic_jsonp, :dynamic_jsonp_keys
|
11
13
|
|
12
14
|
def initialize
|
13
15
|
@logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
|
@@ -21,11 +23,16 @@ module Billy
|
|
21
23
|
@path_blacklist = []
|
22
24
|
@ignore_params = []
|
23
25
|
@persist_cache = false
|
26
|
+
@dynamic_jsonp = false
|
27
|
+
@dynamic_jsonp_keys = ["callback"]
|
24
28
|
@ignore_cache_port = true
|
25
29
|
@non_successful_cache_disabled = false
|
26
30
|
@non_successful_error_level = :warn
|
27
31
|
@non_whitelisted_requests_disabled = false
|
28
32
|
@cache_path = File.join(Dir.tmpdir, 'puffing-billy')
|
33
|
+
@proxy_port = RANDOM_AVAILABLE_PORT
|
34
|
+
@proxied_request_inactivity_timeout = 10 # defaults from https://github.com/igrigorik/em-http-request/wiki/Redirects-and-Timeouts
|
35
|
+
@proxied_request_connect_timeout = 5
|
29
36
|
end
|
30
37
|
end
|
31
38
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'billy/handlers/handler'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module Billy
|
5
|
+
class CacheHandler
|
6
|
+
extend Forwardable
|
7
|
+
include Handler
|
8
|
+
|
9
|
+
def_delegators :cache, :reset, :cached?
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@cache = Billy::Cache.instance
|
13
|
+
end
|
14
|
+
|
15
|
+
def handle_request(method, url, headers, body)
|
16
|
+
method = method.downcase
|
17
|
+
if handles_request?(method, url, headers, body)
|
18
|
+
if (response = cache.fetch(method, url, body))
|
19
|
+
Billy.log(:info, "puffing-billy: CACHE #{method} for '#{url}'")
|
20
|
+
|
21
|
+
if Billy.config.dynamic_jsonp
|
22
|
+
replace_response_callback(response, url)
|
23
|
+
end
|
24
|
+
|
25
|
+
return response
|
26
|
+
end
|
27
|
+
end
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def handles_request?(method, url, headers, body)
|
32
|
+
cached?(method, url, body)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def replace_response_callback(response, url)
|
38
|
+
request_uri = URI::parse(url)
|
39
|
+
if request_uri.query
|
40
|
+
params = CGI::parse(request_uri.query)
|
41
|
+
if params['callback'].any? and response[:content].match(/\w+\(/)
|
42
|
+
response[:content].sub!(/\w+\(/, params['callback'].first + '(')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def cache
|
48
|
+
@cache
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Billy
|
2
|
+
module Handler
|
3
|
+
##
|
4
|
+
#
|
5
|
+
# Handles an incoming HTTP request and returns a response.
|
6
|
+
#
|
7
|
+
# This method accepts HTTP request parameters and must return
|
8
|
+
# a response hash containing the keys :status, :headers,
|
9
|
+
# and :content, or nil if the request cannot be fulfilled.
|
10
|
+
#
|
11
|
+
# @param [String] http_method The HTTP method used, e.g. 'http' or 'https'
|
12
|
+
# @param [String] url The URL requested.
|
13
|
+
# @param [String] headers The headers of the HTTP request.
|
14
|
+
# @param [String] body The body of the HTTP request.
|
15
|
+
# @return [Hash] A hash with the keys [:status, :headers, :content]
|
16
|
+
# Returns {:error => "Some error message"} if a failure occurs.
|
17
|
+
# Returns nil if the request cannot be fulfilled.
|
18
|
+
def handle_request(http_method, url, headers, body)
|
19
|
+
{ error: 'The handler has not overridden the handle_request method!' }
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
#
|
24
|
+
# Checks if the Handler can respond to the given request.
|
25
|
+
#
|
26
|
+
# @param [String] http_method The HTTP method used, e.g. 'http' or 'https'
|
27
|
+
# @param [String] url The URL requested.
|
28
|
+
# @param [String] headers The headers of the HTTP request.
|
29
|
+
# @param [String] body The body of the HTTP request.
|
30
|
+
# @return [Boolean] True if the Handler can respond to the request, else false.
|
31
|
+
#
|
32
|
+
def handles_request?(http_method, url, headers, body)
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
#
|
38
|
+
# Resets the Handler to the default/new state
|
39
|
+
#
|
40
|
+
# This allows the handler to be set back to its default state
|
41
|
+
# at the end of tests or whenever else necessary.
|
42
|
+
#
|
43
|
+
def reset; end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'billy/handlers/handler'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'em-synchrony/em-http'
|
4
|
+
|
5
|
+
module Billy
|
6
|
+
class ProxyHandler
|
7
|
+
include Handler
|
8
|
+
|
9
|
+
def handles_request?(method, url, headers, body)
|
10
|
+
!disabled_request?(url)
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle_request(method, url, headers, body)
|
14
|
+
if handles_request?(method, url, headers, body)
|
15
|
+
req = EventMachine::HttpRequest.new(url, {
|
16
|
+
:inactivity_timeout => Billy.config.proxied_request_inactivity_timeout,
|
17
|
+
:connect_timeout => Billy.config.proxied_request_connect_timeout})
|
18
|
+
|
19
|
+
req = req.send(method.downcase, build_request_options(headers, body))
|
20
|
+
|
21
|
+
if req.error
|
22
|
+
return { :error => "Request to #{url} failed with error: #{req.error}" }
|
23
|
+
end
|
24
|
+
|
25
|
+
if req.response
|
26
|
+
response = process_response(req)
|
27
|
+
|
28
|
+
unless allowed_response_code?(response[:status])
|
29
|
+
if Billy.config.non_successful_error_level == :error
|
30
|
+
return { :error => "Request failed due to response status #{response[:status]} for '#{url}' which was not allowed." }
|
31
|
+
else
|
32
|
+
Billy.log(:warn, "puffing-billy: Received response status code #{response[:status]} for '#{url}'")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
if cacheable?(url, response[:headers], response[:status])
|
37
|
+
Billy::Cache.instance.store(method.downcase, url, headers, body, response[:headers], response[:status], response[:content])
|
38
|
+
end
|
39
|
+
|
40
|
+
Billy.log(:info, "puffing-billy: PROXY #{method} succeeded for '#{url}'")
|
41
|
+
return response
|
42
|
+
end
|
43
|
+
end
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def build_request_options(headers, body)
|
50
|
+
headers = Hash[headers.map { |k,v| [k.downcase, v] }]
|
51
|
+
headers.delete('accept-encoding')
|
52
|
+
|
53
|
+
req_opts = {
|
54
|
+
:redirects => 0,
|
55
|
+
:keepalive => false,
|
56
|
+
:head => headers,
|
57
|
+
:ssl => { :verify => false }
|
58
|
+
}
|
59
|
+
req_opts[:body] = body if body
|
60
|
+
req_opts
|
61
|
+
end
|
62
|
+
|
63
|
+
def process_response(req)
|
64
|
+
response = {
|
65
|
+
:status => req.response_header.status,
|
66
|
+
:headers => req.response_header.raw,
|
67
|
+
:content => req.response.force_encoding('BINARY') }
|
68
|
+
response[:headers].merge!('Connection' => 'close')
|
69
|
+
response[:headers].delete('Transfer-Encoding')
|
70
|
+
response
|
71
|
+
end
|
72
|
+
|
73
|
+
def disabled_request?(url)
|
74
|
+
return false unless Billy.config.non_whitelisted_requests_disabled
|
75
|
+
|
76
|
+
uri = URI(url)
|
77
|
+
# In isolated environments, you may want to stop the request from happening
|
78
|
+
# or else you get "getaddrinfo: Name or service not known" errors
|
79
|
+
blacklisted_path?(uri.path) || !whitelisted_url?(uri)
|
80
|
+
end
|
81
|
+
|
82
|
+
def allowed_response_code?(status)
|
83
|
+
successful_status?(status)
|
84
|
+
end
|
85
|
+
|
86
|
+
def cacheable?(url, headers, status)
|
87
|
+
return false unless Billy.config.cache
|
88
|
+
|
89
|
+
url = URI(url)
|
90
|
+
# Cache the responses if they aren't whitelisted host[:port]s but always cache blacklisted paths on any hosts
|
91
|
+
cacheable_status?(status) && (!whitelisted_url?(url) || blacklisted_path?(url.path))
|
92
|
+
end
|
93
|
+
|
94
|
+
def whitelisted_url?(url)
|
95
|
+
!Billy.config.whitelist.index do |v|
|
96
|
+
v =~ /^#{url.host}(?::#{url.port})?$/
|
97
|
+
end.nil?
|
98
|
+
end
|
99
|
+
|
100
|
+
def blacklisted_path?(path)
|
101
|
+
!Billy.config.path_blacklist.index{|bl| path.include?(bl)}.nil?
|
102
|
+
end
|
103
|
+
|
104
|
+
def successful_status?(status)
|
105
|
+
(200..299).include?(status) || status == 304
|
106
|
+
end
|
107
|
+
|
108
|
+
def cacheable_status?(status)
|
109
|
+
Billy.config.non_successful_cache_disabled ? successful_status?(status) : true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|