site-inspector 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b994e74251bb7b1be968d5bbad80273ee3ffea24
4
- data.tar.gz: e104a5856e1710233df4da02b234935e56910f3b
3
+ metadata.gz: 56a9e64300435fa494e8ae17ca710b46238bcffd
4
+ data.tar.gz: 1e552e430d8f1fea10eba7d873e1ae17aab00415
5
5
  SHA512:
6
- metadata.gz: c68e92c9e4c7b82aa7f19fb56f625f0656104b026ef81ede02b8f9dff90b430fc1af16062bb0fa8d337ad53f410ee563c127de9c594a3b47ce4a93723b668b90
7
- data.tar.gz: 2e07f88d11a2c116289bfeb3e9050ad59b7314523aedeb45cf7d4b4042912c31e2ac4e80828ed27a272cec8952726ed02735c2af4022821255d3685c38478c61
6
+ metadata.gz: 96eaaa8846783ef2b9dfe5b76e84ebd3c160139c425c69edc25761828690b2d508770aa842e234cbb63e9f6ecaa8bb7ffc7b2121a9449d934928938a9a9ec637
7
+ data.tar.gz: b3b4d86a6b6ead26b17eb380b27a5da37afd645c582b94b53860eb1948e28c8cf6baec1c088ace2a53ebdb4e755a316bb635236b9b46c36cb60f1012581c5500
@@ -24,7 +24,10 @@ class SiteInspector
24
24
  def pa11y?
25
25
  !!(Cliver.detect('pa11y'))
26
26
  end
27
- alias_method :enabled?, :pa11y?
27
+
28
+ def enabled?
29
+ @@enabled && pa11y?
30
+ end
28
31
  end
29
32
 
30
33
  def level
@@ -33,12 +33,21 @@ class SiteInspector
33
33
  self.class.name
34
34
  end
35
35
 
36
- def self.name
37
- self.to_s.split('::').last.downcase.to_sym
38
- end
36
+ class << self
37
+
38
+ @@enabled = true
39
+
40
+ def name
41
+ self.to_s.split('::').last.downcase.to_sym
42
+ end
43
+
44
+ def enabled?
45
+ !!(@@enabled)
46
+ end
39
47
 
40
- def self.enabled?
41
- true
48
+ def enabled=(value)
49
+ @@enabled = !!(value)
50
+ end
42
51
  end
43
52
  end
44
53
  end
@@ -6,6 +6,12 @@ class SiteInspector
6
6
  endpoint.up? && endpoint.request(path: path, followlocation: true).success?
7
7
  end
8
8
 
9
+ # The default Check#response method is from a HEAD request
10
+ # The content check has a special response which includes the body from a GET request
11
+ def response
12
+ @response ||= endpoint.request(:method => :get)
13
+ end
14
+
9
15
  def document
10
16
  require 'nokogiri'
11
17
  @doc ||= Nokogiri::HTML response.body if response
@@ -1,6 +1,7 @@
1
1
  class SiteInspector
2
2
  class Endpoint
3
3
  class Dns < Check
4
+ class LocalhostError < StandardError; end
4
5
 
5
6
  def self.resolver
6
7
  require "dnsruby"
@@ -55,6 +56,10 @@ class SiteInspector
55
56
  end
56
57
  end
57
58
 
59
+ def localhost?
60
+ ip == '127.0.0.1'
61
+ end
62
+
58
63
  def ip
59
64
  require 'resolv'
60
65
  @ip ||= Resolv.getaddress host
@@ -80,6 +85,7 @@ class SiteInspector
80
85
  end
81
86
 
82
87
  def to_h
88
+ return { :error => LocalhostError } if localhost?
83
89
  {
84
90
  :dnssec => dnssec?,
85
91
  :ipv6 => ipv6?,
@@ -21,6 +21,7 @@ class SiteInspector
21
21
  return cms unless cms.nil?
22
22
  return :expression_engine if endpoint.cookies.any? { |c| c.keys.first =~ /^exp_/ }
23
23
  return :php if endpoint.cookies["PHPSESSID"]
24
+ return :coldfusion if endpoint.cookies["CFID"] && endpoint.cookies["CFTOKEN"]
24
25
  return :cowboy if endpoint.headers.server.to_s.downcase == "cowboy"
25
26
  nil
26
27
  end
@@ -14,16 +14,19 @@ class SiteInspector
14
14
 
15
15
  def endpoints
16
16
  @endpoints ||= [
17
- Endpoint.new("https://#{host}"),
18
- Endpoint.new("https://www.#{host}"),
19
- Endpoint.new("http://#{host}"),
20
- Endpoint.new("http://www.#{host}")
17
+ Endpoint.new("https://#{host}", :domain => self),
18
+ Endpoint.new("https://www.#{host}", :domain => self),
19
+ Endpoint.new("http://#{host}", :domain => self),
20
+ Endpoint.new("http://www.#{host}", :domain => self)
21
21
  ]
22
22
  end
23
23
 
24
24
  def canonical_endpoint
25
- @canonical_endpoint ||= endpoints.find do |e|
26
- e.https? == canonically_https? && e.www? == canonically_www?
25
+ @canonical_endpoint ||= begin
26
+ prefetch
27
+ endpoints.find do |e|
28
+ e.https? == canonically_https? && e.www? == canonically_www?
29
+ end
27
30
  end
28
31
  end
29
32
 
@@ -10,15 +10,21 @@ class SiteInspector
10
10
  # Because each of the four endpoints could potentially respond differently
11
11
  # We must evaluate all four to make certain determination
12
12
  class Endpoint
13
- attr_accessor :host, :uri
13
+ attr_accessor :host, :uri, :domain
14
14
 
15
15
  # Initatiate a new Endpoint object
16
16
  #
17
17
  # endpoint - (string) the endpoint to query (e.g., `https://example.com`)
18
- def initialize(host)
18
+ # options - A hash of options
19
+ # domain - the parent domain object, if passed, facilitates caching of redirects
20
+ def initialize(host, options={})
19
21
  @uri = Addressable::URI.parse(host.downcase)
22
+ # The root URL always has an implict path of "/", even if not requested
23
+ # Make it explicit to facilitate caching and prevent a potential redirect
24
+ @uri.path = "/"
20
25
  @host = uri.host.sub(/^www\./, "")
21
26
  @checks = {}
27
+ @domain = options[:domain]
22
28
  end
23
29
 
24
30
  def www?
@@ -92,7 +98,7 @@ class SiteInspector
92
98
  return if redirect.host == host && redirect.scheme == scheme
93
99
 
94
100
  # Init a new endpoint representing the redirect
95
- Endpoint.new(redirect.to_s)
101
+ find_or_create_by_uri(redirect.to_s)
96
102
  end
97
103
  end
98
104
 
@@ -104,6 +110,11 @@ class SiteInspector
104
110
  # What's the effective URL of a request to this domain?
105
111
  def resolves_to
106
112
  return self unless redirect?
113
+
114
+ # If the redirect doesn't return a 30x response code, return the redirected endpoint
115
+ # Otherwise, we'll need to go down the rabbit hole and see how deep it goes
116
+ return redirect unless redirect.redirect?
117
+
107
118
  @resolves_to ||= begin
108
119
  response = request(:followlocation => true)
109
120
 
@@ -118,7 +129,7 @@ class SiteInspector
118
129
  url = response.effective_url
119
130
  end
120
131
 
121
- Endpoint.new(url)
132
+ find_or_create_by_uri(url)
122
133
  end
123
134
  end
124
135
 
@@ -161,7 +172,7 @@ class SiteInspector
161
172
  checks = SiteInspector::Endpoint.checks.select { |c| options.keys.include?(c.name) }
162
173
  checks = SiteInspector::Endpoint.checks if checks.empty?
163
174
 
164
- checks.each do |check|
175
+ Parallel.each(checks, :in_threads => 4) do |check|
165
176
  hash[check.name] = self.send(check.name).to_h
166
177
  end
167
178
 
@@ -193,5 +204,16 @@ class SiteInspector
193
204
  def hydra
194
205
  SiteInspector.hydra
195
206
  end
207
+
208
+ # In the event that a redirect is to one of the domain's four endpoints,
209
+ # Try to return the existing endpoint, rather than create a new one
210
+ def find_or_create_by_uri(uri)
211
+ uri = Addressable::URI.parse(uri.downcase)
212
+ if domain && cached_endpoint = domain.endpoints.find { |e| e.uri.to_s == uri.to_s }
213
+ cached_endpoint
214
+ else
215
+ Endpoint.new(uri.to_s)
216
+ end
217
+ end
196
218
  end
197
219
  end
@@ -1,3 +1,3 @@
1
1
  class SiteInspector
2
- VERSION = "3.0.0"
2
+ VERSION = "3.1.0"
3
3
  end
@@ -2,6 +2,7 @@ require 'open-uri'
2
2
  require 'addressable/uri'
3
3
  require 'public_suffix'
4
4
  require 'typhoeus'
5
+ require 'parallel'
5
6
  require 'cliver'
6
7
  require 'cgi'
7
8
 
@@ -49,17 +50,25 @@ class SiteInspector
49
50
  :followlocation => false,
50
51
  :timeout => SiteInspector.timeout,
51
52
  :accept_encoding => "gzip",
53
+ :method => :head,
52
54
  :headers => {
53
55
  "User-Agent" => "Mozilla/5.0 (compatible; SiteInspector/#{SiteInspector::VERSION}; +https://github.com/benbalter/site-inspector)"
54
56
  }
55
57
  }
56
58
  end
57
59
 
60
+ # Returns a thread-safe, memoized hydra instance
58
61
  def hydra
59
- @hydra ||= Typhoeus::Hydra.new(max_concurrency: 4)
62
+ Typhoeus::Hydra.hydra
60
63
  end
61
64
  end
62
65
  end
63
66
 
67
+ if ENV["DEBUG"]
68
+ Ethon.logger = Logger.new(STDOUT);
69
+ Ethon.logger.level = Logger::DEBUG
70
+ Typhoeus::Config.verbose = true
71
+ end
72
+
64
73
  Typhoeus::Config.memoize = true
65
74
  Typhoeus::Config.cache = SiteInspector.cache
data/script/console CHANGED
@@ -1 +1,3 @@
1
- bundle exec pry -r ./lib/site-inspector.rb
1
+ #! /bin/sh
2
+
3
+ DEBUG=1 bundle exec pry -r './lib/site-inspector'
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_dependency("mercenary", "~> 0.3")
27
27
  s.add_dependency("colorator", "~> 0.1")
28
28
  s.add_dependency("cliver", "~> 0.3")
29
+ s.add_dependency("parallel", "~> 1.6")
29
30
  s.add_development_dependency("pry", "~> 0.10")
30
31
  s.add_development_dependency( "rake", "~> 10.4" )
31
32
  s.add_development_dependency( "rspec", "~> 3.2")
@@ -44,7 +44,7 @@ describe SiteInspector::Endpoint::Accessibility do
44
44
  context "with pa11y installed" do
45
45
 
46
46
  before do
47
- stub_request(:get, "http://example.com/").to_return(:status => 200 )
47
+ stub_request(:head, "http://example.com/").to_return(:status => 200 )
48
48
  end
49
49
 
50
50
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe SiteInspector::Endpoint::Check do
4
4
 
5
5
  subject do
6
- stub_request(:get, "http://example.com/").to_return(:status => 200)
6
+ stub_request(:head, "http://example.com/").to_return(:status => 200)
7
7
  endpoint = SiteInspector::Endpoint.new("http://example.com")
8
8
  SiteInspector::Endpoint::Check.new(endpoint)
9
9
  end
@@ -32,7 +32,10 @@ describe SiteInspector::Endpoint::Check do
32
32
  expect(SiteInspector::Endpoint::Check.name).to eql(:check)
33
33
  end
34
34
 
35
- it "enables the check" do
35
+ it "enables and disables the check" do
36
36
  expect(SiteInspector::Endpoint::Check.enabled?).to eql(true)
37
+ SiteInspector::Endpoint::Check.enabled = false
38
+ expect(SiteInspector::Endpoint::Check.enabled?).to eql(false)
39
+ SiteInspector::Endpoint::Check.enabled = true
37
40
  end
38
41
  end
@@ -14,6 +14,8 @@ describe SiteInspector::Endpoint::Content do
14
14
 
15
15
  stub_request(:get, "http://example.com/").
16
16
  to_return(:status => 200, :body => body )
17
+ stub_request(:head, "http://example.com/").
18
+ to_return(:status => 200 )
17
19
  endpoint = SiteInspector::Endpoint.new("http://example.com")
18
20
  SiteInspector::Endpoint::Content.new(endpoint)
19
21
  end
@@ -32,62 +34,62 @@ describe SiteInspector::Endpoint::Content do
32
34
  end
33
35
 
34
36
  it "knows when robots.txt exists" do
35
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
37
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
36
38
 
37
- stub_request(:get, "http://example.com/robots.txt").
39
+ stub_request(:head, "http://example.com/robots.txt").
38
40
  to_return(:status => 200)
39
41
  expect(subject.robots_txt?).to eql(true)
40
42
  end
41
43
 
42
44
  it "knows when robots.txt doesn't exist" do
43
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
45
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
44
46
 
45
- stub_request(:get, "http://example.com/robots.txt").
47
+ stub_request(:head, "http://example.com/robots.txt").
46
48
  to_return(:status => 404)
47
49
  expect(subject.robots_txt?).to eql(false)
48
50
  end
49
51
 
50
52
  it "knows when sitemap.xml exists" do
51
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
53
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
52
54
 
53
- stub_request(:get, "http://example.com/sitemap.xml").
55
+ stub_request(:head, "http://example.com/sitemap.xml").
54
56
  to_return(:status => 200)
55
57
  expect(subject.sitemap_xml?).to eql(true)
56
58
  end
57
59
 
58
60
  it "knows when sitemap.xml exists" do
59
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
61
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
60
62
 
61
- stub_request(:get, "http://example.com/sitemap.xml").
63
+ stub_request(:head, "http://example.com/sitemap.xml").
62
64
  to_return(:status => 404)
63
65
  expect(subject.sitemap_xml?).to eql(false)
64
66
  end
65
67
 
66
68
  it "knows when humans.txt exists" do
67
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
69
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
68
70
 
69
- stub_request(:get, "http://example.com/humans.txt").
71
+ stub_request(:head, "http://example.com/humans.txt").
70
72
  to_return(:status => 200)
71
73
  expect(subject.humans_txt?).to eql(true)
72
74
  end
73
75
 
74
76
  it "knows when humans.txt doesn't exist" do
75
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
77
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 404)
76
78
 
77
- stub_request(:get, "http://example.com/humans.txt").
79
+ stub_request(:head, "http://example.com/humans.txt").
78
80
  to_return(:status => 200)
79
81
  expect(subject.humans_txt?).to eql(true)
80
82
  end
81
83
 
82
84
  context "404s" do
83
85
  it "knows when an endpoint returns a proper 404" do
84
- stub_request(:get, /http\:\/\/example.com\/.*/).
86
+ stub_request(:head, /http\:\/\/example.com\/.*/).
85
87
  to_return(:status => 404)
86
88
  expect(subject.proper_404s?).to eql(true)
87
89
  end
88
90
 
89
91
  it "knows when an endpoint doesn't return a proper 404" do
90
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).
92
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).
91
93
  to_return(:status => 200)
92
94
  expect(subject.proper_404s?).to eql(false)
93
95
  end
@@ -99,8 +101,8 @@ describe SiteInspector::Endpoint::Content do
99
101
  end
100
102
 
101
103
  it "doesn't say something exists when there are no 404s" do
102
- stub_request(:get, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 200)
103
- stub_request(:get, "http://example.com/humans.txt").to_return(:status => 200)
104
+ stub_request(:head, /http\:\/\/example.com\/[a-z0-9]{32}/i).to_return(:status => 200)
105
+ stub_request(:head, "http://example.com/humans.txt").to_return(:status => 200)
104
106
  expect(subject.humans_txt?).to eql(nil)
105
107
  end
106
108
  end
@@ -4,7 +4,7 @@ describe SiteInspector::Endpoint::Cookies do
4
4
 
5
5
  context "without cookies" do
6
6
  subject do
7
- stub_request(:get, "http://example.com/").
7
+ stub_request(:head, "http://example.com/").
8
8
  to_return(:status => 200, :body => "" )
9
9
  endpoint = SiteInspector::Endpoint.new("http://example.com")
10
10
  SiteInspector::Endpoint::Cookies.new(endpoint)
@@ -33,7 +33,7 @@ describe SiteInspector::Endpoint::Cookies do
33
33
  )
34
34
  ].map { |c| c.to_s }
35
35
 
36
- stub_request(:get, "http://example.com/").
36
+ stub_request(:head, "http://example.com/").
37
37
  to_return(:status => 200, :body => "", :headers => { "set-cookie" => cookies })
38
38
  endpoint = SiteInspector::Endpoint.new("http://example.com")
39
39
  SiteInspector::Endpoint::Cookies.new(endpoint)
@@ -59,7 +59,7 @@ describe SiteInspector::Endpoint::Cookies do
59
59
  "foo=bar; domain=example.com; path=/; secure; HttpOnly",
60
60
  "foo2=bar2; domain=example.com; path=/"
61
61
  ]
62
- stub_request(:get, "http://example.com/").
62
+ stub_request(:head, "http://example.com/").
63
63
  to_return(:status => 200, :body => "", :headers => { "set-cookie" => cookies })
64
64
  endpoint = SiteInspector::Endpoint.new("http://example.com")
65
65
  SiteInspector::Endpoint::Cookies.new(endpoint)
@@ -4,7 +4,7 @@ require 'dnsruby'
4
4
  describe SiteInspector::Endpoint::Dns do
5
5
 
6
6
  subject do
7
- stub_request(:get, "http://github.com/").to_return(:status => 200)
7
+ stub_request(:head, "http://github.com/").to_return(:status => 200)
8
8
  endpoint = SiteInspector::Endpoint.new("http://github.com")
9
9
  SiteInspector::Endpoint::Dns.new(endpoint)
10
10
  end
@@ -81,6 +81,10 @@ describe SiteInspector::Endpoint::Dns do
81
81
  expect(subject.ipv6?).to eql(true)
82
82
  end
83
83
 
84
+ it "knows it's not a localhost address" do
85
+ expect(subject.localhost?).to eql(false)
86
+ end
87
+
84
88
  context "hostname detection" do
85
89
  it "lists cnames" do
86
90
  records = []
@@ -164,4 +168,20 @@ describe SiteInspector::Endpoint::Dns do
164
168
  end
165
169
  end
166
170
  end
171
+
172
+ context "localhost" do
173
+
174
+ before do
175
+ allow(subject).to receive(:ip) { "127.0.0.1" }
176
+ end
177
+
178
+ it "knows it's a localhost address" do
179
+ expect(subject.localhost?).to eql(true)
180
+ end
181
+
182
+ it "returns a LocalhostError" do
183
+ expect(subject.to_h).to eql({:error => SiteInspector::Endpoint::Dns::LocalhostError})
184
+ end
185
+
186
+ end
167
187
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe SiteInspector::Endpoint::Headers do
4
4
 
5
5
  subject do
6
- stub_request(:get, "http://example.com/").
6
+ stub_request(:head, "http://example.com/").
7
7
  to_return(:status => 200, :headers => { :foo => "bar" } )
8
8
  endpoint = SiteInspector::Endpoint.new("http://example.com")
9
9
  SiteInspector::Endpoint::Headers.new(endpoint)
@@ -4,7 +4,7 @@ describe SiteInspector::Endpoint::Hsts do
4
4
 
5
5
  subject do
6
6
  headers = { "strict-transport-security" => "max-age=31536000; includeSubDomains;" }
7
- stub_request(:get, "http://example.com/").
7
+ stub_request(:head, "http://example.com/").
8
8
  to_return(:status => 200, :headers => headers )
9
9
  endpoint = SiteInspector::Endpoint.new("http://example.com")
10
10
  SiteInspector::Endpoint::Hsts.new(endpoint)
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe SiteInspector::Endpoint::Https do
4
4
 
5
5
  subject do
6
- stub_request(:get, "https://example.com/").
6
+ stub_request(:head, "https://example.com/").
7
7
  to_return(:status => 200 )
8
8
  endpoint = SiteInspector::Endpoint.new("https://example.com")
9
9
  allow(endpoint.response).to receive(:return_code) { :ok }
@@ -23,7 +23,10 @@ describe SiteInspector::Endpoint::Sniffer do
23
23
  ].map { |c| c.to_s }
24
24
 
25
25
  stub_request(:get, "http://example.com/").
26
- to_return(:status => 200, :body => "", :headers => { "set-cookie" => cookies } )
26
+ to_return(:status => 200, :body => "" )
27
+
28
+ stub_request(:head, "http://example.com/").
29
+ to_return(:status => 200, :headers => { "set-cookie" => cookies } )
27
30
  end
28
31
 
29
32
  context "stubbed body" do
@@ -50,6 +53,9 @@ describe SiteInspector::Endpoint::Sniffer do
50
53
 
51
54
  stub_request(:get, "http://example.com/").
52
55
  to_return(:status => 200, :body => body )
56
+
57
+ stub_request(:head, "http://example.com/").
58
+ to_return(:status => 200)
53
59
  endpoint = SiteInspector::Endpoint.new("http://example.com")
54
60
  SiteInspector::Endpoint::Sniffer.new(endpoint)
55
61
  end
@@ -105,10 +111,39 @@ describe SiteInspector::Endpoint::Sniffer do
105
111
 
106
112
  it "detects cowboy" do
107
113
  stub_request(:get, "http://example.com/").
108
- to_return(:status => 200, :body => "", :headers => { "server" => "Cowboy" } )
114
+ to_return(:status => 200, :body => "" )
115
+
116
+ stub_request(:head, "http://example.com/").
117
+ to_return(:status => 200, :headers => { "server" => "Cowboy" } )
109
118
 
110
119
  expect(subject.framework).to eql(:cowboy)
111
120
  expect(subject.open_source?).to eql(true)
112
121
  end
122
+
123
+ it "detects ColdFusion" do
124
+ cookies = [
125
+ CGI::Cookie::new(
126
+ "name" => "CFID",
127
+ "value" => "1234",
128
+ "domain" => "example.com",
129
+ "path" => "/"
130
+ ),
131
+ CGI::Cookie::new(
132
+ "name" => "CFTOKEN",
133
+ "value" => "5678",
134
+ "domain" => "example.com",
135
+ "path" => "/"
136
+ )
137
+ ].map { |c| c.to_s }
138
+
139
+ stub_request(:get, "http://example.com/").
140
+ to_return(:status => 200, :body => "" )
141
+
142
+ stub_request(:head, "http://example.com/").
143
+ to_return(:status => 200, :headers => { "set-cookie" => cookies } )
144
+
145
+ expect(subject.framework).to eql(:coldfusion)
146
+ expect(subject.open_source?).to eql(false)
147
+ end
113
148
  end
114
149
  end
@@ -45,19 +45,19 @@ describe SiteInspector::Domain do
45
45
  it "generates the endpoints" do
46
46
  endpoints = subject.endpoints
47
47
  expect(endpoints.count).to eql(4)
48
- expect(endpoints[0].to_s).to eql("https://example.com")
49
- expect(endpoints[1].to_s).to eql("https://www.example.com")
50
- expect(endpoints[2].to_s).to eql("http://example.com")
51
- expect(endpoints[3].to_s).to eql("http://www.example.com")
48
+ expect(endpoints[0].to_s).to eql("https://example.com/")
49
+ expect(endpoints[1].to_s).to eql("https://www.example.com/")
50
+ expect(endpoints[2].to_s).to eql("http://example.com/")
51
+ expect(endpoints[3].to_s).to eql("http://www.example.com/")
52
52
  end
53
53
  end
54
54
 
55
55
  it "knows the canonical domain" do
56
- stub_request(:get, "https://example.com/").to_return(:status => 500)
57
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
58
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
59
- stub_request(:get, "http://example.com/").to_return(:status => 200)
60
- expect(subject.canonical_endpoint.to_s).to eql("http://example.com")
56
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
57
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
58
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
59
+ stub_request(:head, "http://example.com/").to_return(:status => 200)
60
+ expect(subject.canonical_endpoint.to_s).to eql("http://example.com/")
61
61
  end
62
62
 
63
63
  it "knows if a domain is a government domain" do
@@ -75,7 +75,7 @@ describe SiteInspector::Domain do
75
75
  end
76
76
  end
77
77
 
78
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
78
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
79
79
 
80
80
  expect(subject.up?).to eql(true)
81
81
  end
@@ -91,19 +91,19 @@ describe SiteInspector::Domain do
91
91
 
92
92
  context "up" do
93
93
  it "considers a domain up if at least one endpoint is up" do
94
- stub_request(:get, "https://example.com/").to_return(:status => 500)
95
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
96
- stub_request(:get, "http://example.com/").to_return(:status => 500)
97
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
94
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
95
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
96
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
97
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
98
98
 
99
99
  expect(subject.up?).to eql(true)
100
100
  end
101
101
 
102
102
  it "doesn't consider a domain up if all endpoints are down" do
103
- stub_request(:get, "https://example.com/").to_return(:status => 500)
104
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
105
- stub_request(:get, "http://example.com/").to_return(:status => 500)
106
- stub_request(:get, "http://www.example.com/").to_return(:status => 500)
103
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
104
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
105
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
106
+ stub_request(:head, "http://www.example.com/").to_return(:status => 500)
107
107
 
108
108
  expect(subject.up?).to eql(false)
109
109
  end
@@ -111,19 +111,19 @@ describe SiteInspector::Domain do
111
111
 
112
112
  context "www" do
113
113
  it "considers a site www when at least one endpoint is www" do
114
- stub_request(:get, "https://example.com/").to_return(:status => 200)
115
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
116
- stub_request(:get, "http://example.com/").to_return(:status => 500)
117
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
114
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
115
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
116
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
117
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
118
118
 
119
119
  expect(subject.www?).to eql(true)
120
120
  end
121
121
 
122
122
  it "doesn't consider a site www when no endpoint is www" do
123
- stub_request(:get, "https://example.com/").to_return(:status => 200)
124
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
125
- stub_request(:get, "http://example.com/").to_return(:status => 200)
126
- stub_request(:get, "http://www.example.com/").to_return(:status => 500)
123
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
124
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
125
+ stub_request(:head, "http://example.com/").to_return(:status => 200)
126
+ stub_request(:head, "http://www.example.com/").to_return(:status => 500)
127
127
 
128
128
  expect(subject.www?).to eql(false)
129
129
  end
@@ -131,19 +131,19 @@ describe SiteInspector::Domain do
131
131
 
132
132
  context "root" do
133
133
  it "considers a domain root if you can connect without www" do
134
- stub_request(:get, "https://example.com/").to_return(:status => 200)
135
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
136
- stub_request(:get, "http://example.com/").to_return(:status => 500)
137
- stub_request(:get, "http://www.example.com/").to_return(:status => 500)
134
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
135
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
136
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
137
+ stub_request(:head, "http://www.example.com/").to_return(:status => 500)
138
138
 
139
139
  expect(subject.root?).to eql(true)
140
140
  end
141
141
 
142
142
  it "doesn't call a www-only domain root" do
143
- stub_request(:get, "https://example.com/").to_return(:status => 500)
144
- stub_request(:get, "https://www.example.com/").to_return(:status => 200)
145
- stub_request(:get, "http://example.com/").to_return(:status => 500)
146
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
143
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
144
+ stub_request(:head, "https://www.example.com/").to_return(:status => 200)
145
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
146
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
147
147
 
148
148
  expect(subject.root?).to eql(false)
149
149
  end
@@ -151,38 +151,38 @@ describe SiteInspector::Domain do
151
151
 
152
152
  context "https" do
153
153
  it "knows when a domain supports https" do
154
- stub_request(:get, "https://example.com/").to_return(:status => 200)
155
- stub_request(:get, "https://www.example.com/").to_return(:status => 200)
156
- stub_request(:get, "http://example.com/").to_return(:status => 200)
157
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
154
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
155
+ stub_request(:head, "https://www.example.com/").to_return(:status => 200)
156
+ stub_request(:head, "http://example.com/").to_return(:status => 200)
157
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
158
158
  allow(subject.endpoints.first.https).to receive(:valid?) { true }
159
159
 
160
160
  expect(subject.https?).to eql(true)
161
161
  end
162
162
 
163
163
  it "knows when a domain doesn't support https" do
164
- stub_request(:get, "https://example.com/").to_return(:status => 500)
165
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
166
- stub_request(:get, "http://example.com/").to_return(:status => 200)
167
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
164
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
165
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
166
+ stub_request(:head, "http://example.com/").to_return(:status => 200)
167
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
168
168
 
169
169
  expect(subject.https?).to eql(false)
170
170
  end
171
171
 
172
172
  it "considers HTTPS inforced when no http endpoint responds" do
173
- stub_request(:get, "https://example.com/").to_return(:status => 200)
174
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
175
- stub_request(:get, "http://example.com/").to_return(:status => 500)
176
- stub_request(:get, "http://www.example.com/").to_return(:status => 500)
173
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
174
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
175
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
176
+ stub_request(:head, "http://www.example.com/").to_return(:status => 500)
177
177
 
178
178
  #expect(subject.enforces_https?).to eql(true)
179
179
  end
180
180
 
181
181
  it "doesn't consider HTTPS inforced when an http endpoint responds" do
182
- stub_request(:get, "https://example.com/").to_return(:status => 200)
183
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
184
- stub_request(:get, "http://example.com/").to_return(:status => 500)
185
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
182
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
183
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
184
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
185
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
186
186
 
187
187
  expect(subject.enforces_https?).to eql(false)
188
188
  end
@@ -199,20 +199,20 @@ describe SiteInspector::Domain do
199
199
  context "canonical" do
200
200
  context "www" do
201
201
  it "detects a domain as canonically www when root is down" do
202
- stub_request(:get, "https://example.com/").to_return(:status => 500)
203
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
204
- stub_request(:get, "http://example.com/").to_return(:status => 500)
205
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
202
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
203
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
204
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
205
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
206
206
 
207
207
  expect(subject.canonically_www?).to eql(true)
208
208
  end
209
209
 
210
210
  it "detects a domain as canonically www when root redirects" do
211
- stub_request(:get, "https://example.com/").to_return(:status => 500)
212
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
213
- stub_request(:get, "http://example.com/").
211
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
212
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
213
+ stub_request(:head, "http://example.com/").
214
214
  to_return(:status => 301, :headers => { :location => "http://www.example.com" } )
215
- stub_request(:get, "http://www.example.com/").to_return(:status => 200)
215
+ stub_request(:head, "http://www.example.com/").to_return(:status => 200)
216
216
 
217
217
  expect(subject.canonically_www?).to eql(true)
218
218
  end
@@ -220,21 +220,21 @@ describe SiteInspector::Domain do
220
220
 
221
221
  context "https" do
222
222
  it "detects a domain as canonically https when http is down" do
223
- stub_request(:get, "https://example.com/").to_return(:status => 200)
224
- stub_request(:get, "https://www.example.com/").to_return(:status => 200)
225
- stub_request(:get, "http://example.com/").to_return(:status => 500)
226
- stub_request(:get, "http://www.example.com/").to_return(:status => 500)
223
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
224
+ stub_request(:head, "https://www.example.com/").to_return(:status => 200)
225
+ stub_request(:head, "http://example.com/").to_return(:status => 500)
226
+ stub_request(:head, "http://www.example.com/").to_return(:status => 500)
227
227
  allow(subject.endpoints.first.https).to receive(:valid?) { true }
228
228
 
229
229
  expect(subject.canonically_https?).to eql(true)
230
230
  end
231
231
 
232
232
  it "detects a domain as canonically https when http redirect" do
233
- stub_request(:get, "https://example.com/").to_return(:status => 200)
234
- stub_request(:get, "https://www.example.com/").to_return(:status => 200)
235
- stub_request(:get, "http://example.com/").
233
+ stub_request(:head, "https://example.com/").to_return(:status => 200)
234
+ stub_request(:head, "https://www.example.com/").to_return(:status => 200)
235
+ stub_request(:head, "http://example.com/").
236
236
  to_return(:status => 301, :headers => { :location => "https://example.com" } )
237
- stub_request(:get, "http://www.example.com/").to_return(:status => 500)
237
+ stub_request(:head, "http://www.example.com/").to_return(:status => 500)
238
238
  allow(subject.endpoints.first.https).to receive(:valid?) { true }
239
239
 
240
240
  expect(subject.canonically_https?).to eql(true)
@@ -244,11 +244,12 @@ describe SiteInspector::Domain do
244
244
 
245
245
  context "redirects" do
246
246
  it "knows when a domain redirects" do
247
- stub_request(:get, "https://example.com/").to_return(:status => 500)
248
- stub_request(:get, "https://www.example.com/").to_return(:status => 500)
249
- stub_request(:get, "http://example.com/").
247
+ stub_request(:head, "https://example.com/").to_return(:status => 500)
248
+ stub_request(:head, "https://www.example.com/").to_return(:status => 500)
249
+ stub_request(:head, "http://example.com/").
250
250
  to_return(:status => 301, :headers => { :location => "http://foo.example.com" } )
251
- stub_request(:get, "http://www.example.com/").to_return(:status => 500)
251
+ stub_request(:head, "http://www.example.com/").to_return(:status => 500)
252
+ stub_request(:head, "http://foo.example.com/").to_return(:status => 200)
252
253
 
253
254
  expect(subject.redirect?).to eql(true)
254
255
  end
@@ -15,7 +15,7 @@ describe SiteInspector::Endpoint do
15
15
  end
16
16
 
17
17
  it "returns the uri" do
18
- expect(subject.uri.to_s).to eql("http://example.com")
18
+ expect(subject.uri.to_s).to eql("http://example.com/")
19
19
  end
20
20
 
21
21
  it "knows if an endpoint is www" do
@@ -28,10 +28,10 @@ describe SiteInspector::Endpoint do
28
28
  end
29
29
 
30
30
  it "knows if an endpoint is http" do
31
- stub_request(:get, "http://example.com/").
31
+ stub_request(:head, "http://example.com/").
32
32
  to_return(:status => 200, :body => "content")
33
33
 
34
- stub_request(:get, "https://example.com/").
34
+ stub_request(:head, "https://example.com/").
35
35
  to_return(:status => 500, :body => "content")
36
36
 
37
37
  expect(subject.https?).to eql(false)
@@ -39,10 +39,10 @@ describe SiteInspector::Endpoint do
39
39
  end
40
40
 
41
41
  it "knows if an endpoint is https" do
42
- stub_request(:get, "http://example.com/").
42
+ stub_request(:head, "http://example.com/").
43
43
  to_return(:status => 200, :body => "content")
44
44
 
45
- stub_request(:get, "https://example.com/").
45
+ stub_request(:head, "https://example.com/").
46
46
  to_return(:status => 200, :body => "content")
47
47
 
48
48
  endpoint = SiteInspector::Endpoint.new("https://example.com")
@@ -60,7 +60,7 @@ describe SiteInspector::Endpoint do
60
60
  context "requests" do
61
61
 
62
62
  it "requests a URL" do
63
- stub = stub_request(:get, "http://example.com/").
63
+ stub = stub_request(:head, "http://example.com/").
64
64
  to_return(:status => 200, :body => "content")
65
65
 
66
66
  expect(subject.request.body).to eql("content")
@@ -68,7 +68,7 @@ describe SiteInspector::Endpoint do
68
68
  end
69
69
 
70
70
  it "requests a requested path" do
71
- stub = stub_request(:get, "http://example.com/foo").
71
+ stub = stub_request(:head, "http://example.com/foo").
72
72
  to_return(:status => 200, :body => "content")
73
73
 
74
74
  expect(subject.request(:path => "foo").body).to eql("content")
@@ -76,7 +76,7 @@ describe SiteInspector::Endpoint do
76
76
  end
77
77
 
78
78
  it "requests with typhoeus options" do
79
- stub_request(:get, "http://example.com/").
79
+ stub_request(:head, "http://example.com/").
80
80
  to_return(:status => 301, :headers => { :location => "http://example.com/foo" } )
81
81
 
82
82
  response = subject.request(:followlocation => true)
@@ -84,7 +84,7 @@ describe SiteInspector::Endpoint do
84
84
  end
85
85
 
86
86
  it "returns the response" do
87
- stub = stub_request(:get, "http://example.com/").
87
+ stub = stub_request(:head, "http://example.com/").
88
88
  to_return(:status => 200, :body => "content")
89
89
 
90
90
  expect(subject.response.body).to eql("content")
@@ -93,7 +93,7 @@ describe SiteInspector::Endpoint do
93
93
  end
94
94
 
95
95
  it "knows if there's a response" do
96
- stub_request(:get, "http://example.com/").
96
+ stub_request(:head, "http://example.com/").
97
97
  to_return(:status => 200, :body => "content")
98
98
 
99
99
  expect(subject.responds?).to eql(true)
@@ -108,7 +108,7 @@ describe SiteInspector::Endpoint do
108
108
  end
109
109
 
110
110
  it "knows the response code" do
111
- stub_request(:get, "http://example.com/").
111
+ stub_request(:head, "http://example.com/").
112
112
  to_return(:status => 200)
113
113
 
114
114
  expect(subject.response_code).to eql("200")
@@ -120,7 +120,7 @@ describe SiteInspector::Endpoint do
120
120
  end
121
121
 
122
122
  it "considers a 200 response code to be live and a response" do
123
- stub_request(:get, "http://example.com/").
123
+ stub_request(:head, "http://example.com/").
124
124
  to_return(:status => 200)
125
125
 
126
126
  expect(subject.up?).to eql(true)
@@ -128,7 +128,7 @@ describe SiteInspector::Endpoint do
128
128
  end
129
129
 
130
130
  it "considers a 301 response code to be live and a response" do
131
- stub_request(:get, "http://example.com/").
131
+ stub_request(:head, "http://example.com/").
132
132
  to_return(:status => 301)
133
133
 
134
134
  expect(subject.up?).to eql(true)
@@ -136,7 +136,7 @@ describe SiteInspector::Endpoint do
136
136
  end
137
137
 
138
138
  it "considers a 404 response code to be down but a response" do
139
- stub_request(:get, "http://example.com/").
139
+ stub_request(:head, "http://example.com/").
140
140
  to_return(:status => 404)
141
141
 
142
142
  expect(subject.up?).to eql(false)
@@ -144,7 +144,7 @@ describe SiteInspector::Endpoint do
144
144
  end
145
145
 
146
146
  it "considers a 500 response code to be down but a response" do
147
- stub_request(:get, "http://example.com/").
147
+ stub_request(:head, "http://example.com/").
148
148
  to_return(:status => 500)
149
149
 
150
150
  expect(subject.up?).to eql(false)
@@ -168,59 +168,65 @@ describe SiteInspector::Endpoint do
168
168
 
169
169
  context "redirects" do
170
170
  it "knows when there's a redirect" do
171
- stub_request(:get, "http://example.com/").
171
+ stub_request(:head, "http://example.com/").
172
172
  to_return(:status => 301, :headers => { :location => "http://www.example.com" } )
173
173
 
174
174
  expect(subject.redirect?).to eql(true)
175
175
  end
176
176
 
177
177
  it "returns the redirect" do
178
- stub_request(:get, "http://example.com/").
178
+ stub_request(:head, "http://example.com/").
179
179
  to_return(:status => 301, :headers => { :location => "http://www.example.com" } )
180
180
 
181
- stub_request(:get, "http://www.example.com/").
181
+ stub_request(:head, "http://www.example.com/").
182
182
  to_return(:status => 200)
183
183
 
184
- expect(subject.redirect.uri.to_s).to eql("http://www.example.com")
184
+ expect(subject.redirect.uri.to_s).to eql("http://www.example.com/")
185
185
  end
186
186
 
187
187
  it "handles relative redirects" do
188
- stub_request(:get, "http://example.com/").
188
+ stub_request(:head, "http://example.com/").
189
189
  to_return(:status => 301, :headers => { :location => "/foo" } )
190
190
 
191
191
  expect(subject.redirect?).to eql(false)
192
192
  end
193
193
 
194
194
  it "handles relative redirects without a leading slash" do
195
- stub_request(:get, "http://example.com/").
195
+ stub_request(:head, "http://example.com/").
196
196
  to_return(:status => 301, :headers => { :location => "foo" } )
197
197
 
198
198
  expect(subject.redirect?).to eql(false)
199
199
  end
200
200
 
201
201
  it "knows what it resolves to" do
202
- stub_request(:get, "http://example.com/").
202
+ stub_request(:head, "http://example.com/").
203
203
  to_return(:status => 301, :headers => { :location => "http://www.example.com" } )
204
204
 
205
- stub_request(:get, "http://www.example.com/").
205
+ stub_request(:head, "http://www.example.com/").
206
206
  to_return(:status => 200)
207
207
 
208
208
  expect(subject.redirect?).to eql(true)
209
- expect(subject.resolves_to.uri.to_s).to eql("http://www.example.com")
209
+ expect(subject.resolves_to.uri.to_s).to eql("http://www.example.com/")
210
210
  end
211
211
 
212
212
  it "detects external redirects" do
213
- stub_request(:get, "http://example.com/").
213
+ stub_request(:head, "http://example.com/").
214
214
  to_return(:status => 301, :headers => { :location => "http://www.example.gov" } )
215
215
 
216
+ stub_request(:head, "http://www.example.gov").
217
+ to_return(:status => 200)
218
+
216
219
  expect(subject.redirect?).to eql(true)
217
220
  expect(subject.external_redirect?).to eql(true)
218
221
  end
219
222
 
220
223
  it "knows internal redirects are not external redirects" do
221
- stub_request(:get, "http://example.com/").
224
+ stub_request(:head, "http://example.com/").
222
225
  to_return(:status => 301, :headers => { :location => "https://example.com" } )
223
226
 
227
+ stub_request(:head, "https://example.com/").
228
+ to_return(:status => 200)
229
+
224
230
  expect(subject.external_redirect?).to eql(false)
225
231
  end
226
232
  end
@@ -233,7 +239,7 @@ describe SiteInspector::Endpoint do
233
239
  SiteInspector::Endpoint.checks.each do |check|
234
240
  it "responds to the #{check} check" do
235
241
 
236
- stub_request(:get, "http://example.com/").
242
+ stub_request(:head, "http://example.com/").
237
243
  to_return(:status => 200)
238
244
 
239
245
  expect(subject.send(check.name)).to_not be_nil
@@ -36,6 +36,7 @@ describe SiteInspector do
36
36
  expected = {
37
37
  :accept_encoding => "gzip",
38
38
  :followlocation => false,
39
+ :method => :head,
39
40
  :timeout => 10,
40
41
  :headers => {
41
42
  "User-Agent" => "Mozilla/5.0 (compatible; SiteInspector/#{SiteInspector::VERSION}; +https://github.com/benbalter/site-inspector)"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: site-inspector
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Balter
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0.3'
153
+ - !ruby/object:Gem::Dependency
154
+ name: parallel
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.6'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.6'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: pry
155
169
  requirement: !ruby/object:Gem::Requirement