site-inspector 2.0.0 → 3.0.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/.gitignore +2 -1
- data/.travis.yml +4 -1
- data/README.md +11 -2
- data/lib/site-inspector/checks/accessibility.rb +114 -0
- data/lib/site-inspector/checks/check.rb +4 -0
- data/lib/site-inspector/checks/content.rb +6 -5
- data/lib/site-inspector/checks/cookies.rb +45 -0
- data/lib/site-inspector/checks/headers.rb +0 -16
- data/lib/site-inspector/checks/sniffer.rb +28 -6
- data/lib/site-inspector/disk_cache.rb +3 -1
- data/lib/site-inspector/domain.rb +28 -10
- data/lib/site-inspector/endpoint.rb +5 -8
- data/lib/site-inspector/version.rb +1 -1
- data/lib/site-inspector.rb +5 -1
- data/package.json +23 -0
- data/script/bootstrap +1 -0
- data/script/cibuild +2 -0
- data/site-inspector.gemspec +3 -2
- data/spec/checks/site_inspector_endpoint_accessibility_spec.rb +81 -0
- data/spec/checks/site_inspector_endpoint_check_spec.rb +4 -0
- data/spec/checks/site_inspector_endpoint_content_spec.rb +20 -2
- data/spec/checks/site_inspector_endpoint_cookies_spec.rb +72 -0
- data/spec/checks/site_inspector_endpoint_headers_spec.rb +0 -10
- data/spec/checks/site_inspector_endpoint_sniffer_spec.rb +99 -37
- data/spec/{site_inspector_disc_cache_spec.rb → site_inspector_disk_cache_spec.rb} +13 -7
- data/spec/site_inspector_domain_spec.rb +28 -6
- data/spec/site_inspector_endpoint_spec.rb +32 -11
- data/spec/site_inspector_spec.rb +1 -1
- metadata +27 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b994e74251bb7b1be968d5bbad80273ee3ffea24
|
4
|
+
data.tar.gz: e104a5856e1710233df4da02b234935e56910f3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c68e92c9e4c7b82aa7f19fb56f625f0656104b026ef81ede02b8f9dff90b430fc1af16062bb0fa8d337ad53f410ee563c127de9c594a3b47ce4a93723b668b90
|
7
|
+
data.tar.gz: 2e07f88d11a2c116289bfeb3e9050ad59b7314523aedeb45cf7d4b4042912c31e2ac4e80828ed27a272cec8952726ed02735c2af4022821255d3685c38478c61
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
A Ruby Gem to sniff information about a domain's technology and capabilities.
|
4
4
|
|
5
|
-
[](http://badge.fury.io/rb/site-inspector) [](http://badge.fury.io/rb/site-inspector) [](https://travis-ci.org/benbalter/site-inspector)
|
6
6
|
|
7
7
|
## Demo
|
8
8
|
|
@@ -87,6 +87,15 @@ Options:
|
|
87
87
|
|
88
88
|
Each endpoint also returns the following checks:
|
89
89
|
|
90
|
+
#### Accessibility
|
91
|
+
|
92
|
+
Uses the `pa11y` CLI to run automated accessibility tests. Requires `node`. To install `pally`: `[sudo] npm install -g pa11y`.
|
93
|
+
|
94
|
+
* `section508` - Tests against the Section508 standard
|
95
|
+
* `wcag2a` - Tests against the WCAG2A standard
|
96
|
+
* `wcag2aa` - Tests against the WCAG2AA standard
|
97
|
+
* `wcag2aaa` - Tests against the WCAG2AAA standard
|
98
|
+
|
90
99
|
#### Content
|
91
100
|
|
92
101
|
* `doctype` - The HTML doctype returned
|
@@ -136,7 +145,7 @@ Each endpoint also returns the following checks:
|
|
136
145
|
|
137
146
|
## Adding your own check
|
138
147
|
|
139
|
-
[Checks](https://github.com/benbalter/site-inspector
|
148
|
+
[Checks](https://github.com/benbalter/site-inspector/tree/master/lib/site-inspector/checks) are special classes that are children of [`SiteInspector::Endpoint::Check`](https://github.com/benbalter/site-inspector/blob/master/lib/site-inspector/checks/check.rb). You can implement your own check like this:
|
140
149
|
|
141
150
|
```ruby
|
142
151
|
class SiteInspector
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
class SiteInspector
|
5
|
+
class Endpoint
|
6
|
+
class Accessibility < Check
|
7
|
+
class Pa11yError < RuntimeError; end
|
8
|
+
|
9
|
+
STANDARDS = {
|
10
|
+
section508: 'Section508', # Default standard
|
11
|
+
wcag2a: 'WCAG2A',
|
12
|
+
wcag2aa: 'WCAG2AA',
|
13
|
+
wcag2aaa: 'WCAG2AAA'
|
14
|
+
}
|
15
|
+
|
16
|
+
DEFAULT_LEVEL = :error
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def pa11y_version
|
20
|
+
output, status = Open3.capture2e("pa11y", "--version")
|
21
|
+
output.strip if status == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def pa11y?
|
25
|
+
!!(Cliver.detect('pa11y'))
|
26
|
+
end
|
27
|
+
alias_method :enabled?, :pa11y?
|
28
|
+
end
|
29
|
+
|
30
|
+
def level
|
31
|
+
@level ||= DEFAULT_LEVEL
|
32
|
+
end
|
33
|
+
|
34
|
+
def level=(level)
|
35
|
+
raise ArgumentError, "Invalid level '#{level}'" unless [:error, :warning, :notice].include?(level)
|
36
|
+
@level = level
|
37
|
+
end
|
38
|
+
|
39
|
+
def standard?(standard)
|
40
|
+
STANDARDS.keys.include?(standard)
|
41
|
+
end
|
42
|
+
|
43
|
+
def standard
|
44
|
+
@standard ||= STANDARDS.keys.first
|
45
|
+
end
|
46
|
+
|
47
|
+
def standard=(standard)
|
48
|
+
raise ArgumentError, "Unknown standard '#{standard}'" unless standard?(standard)
|
49
|
+
@standard = standard
|
50
|
+
end
|
51
|
+
|
52
|
+
def valid?
|
53
|
+
check[:valid] if check
|
54
|
+
end
|
55
|
+
|
56
|
+
def errors
|
57
|
+
check[:results].count { |r| r["type"] == "error" } if check
|
58
|
+
end
|
59
|
+
|
60
|
+
def check
|
61
|
+
@check ||= pa11y(standard)
|
62
|
+
rescue Pa11yError
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
alias_method :to_h, :check
|
66
|
+
|
67
|
+
def method_missing(method_sym, *arguments, &block)
|
68
|
+
if standard?(method_sym)
|
69
|
+
pa11y(method_sym)
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def respond_to?(method_sym, include_private = false)
|
76
|
+
if standard?(method_sym)
|
77
|
+
true
|
78
|
+
else
|
79
|
+
super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def pa11y(standard)
|
86
|
+
Cliver.assert('pa11y')
|
87
|
+
raise ArgumentError, "Unknown standard '#{standard}'" unless standard?(standard)
|
88
|
+
|
89
|
+
args = [
|
90
|
+
"--standard", STANDARDS[standard],
|
91
|
+
"--reporter", "json",
|
92
|
+
"--level", level.to_s,
|
93
|
+
endpoint.uri.to_s
|
94
|
+
]
|
95
|
+
output, status = run_command(args)
|
96
|
+
|
97
|
+
# Pa11y exit codes: https://github.com/nature/pa11y#exit-codes
|
98
|
+
# 0: No errors, 1: Technical error within pa11y, 2: accessibility error (configurable via --level)
|
99
|
+
raise Pa11yError if status == 1
|
100
|
+
|
101
|
+
{
|
102
|
+
valid: status == 0,
|
103
|
+
results: JSON.parse(output)
|
104
|
+
}
|
105
|
+
rescue Pa11yError, JSON::ParserError
|
106
|
+
raise Pa11yError, "Command `pa11y #{args.join(" ")}` failed: #{output}"
|
107
|
+
end
|
108
|
+
|
109
|
+
def run_command(args)
|
110
|
+
Open3.capture2e("pa11y", *args)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -3,7 +3,7 @@ class SiteInspector
|
|
3
3
|
class Content < Check
|
4
4
|
# Given a path (e.g, "/data"), check if the given path exists on the canonical endpoint
|
5
5
|
def path_exists?(path)
|
6
|
-
endpoint.request(path: path, followlocation: true).success?
|
6
|
+
endpoint.up? && endpoint.request(path: path, followlocation: true).success?
|
7
7
|
end
|
8
8
|
|
9
9
|
def document
|
@@ -17,22 +17,23 @@ class SiteInspector
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def robots_txt?
|
20
|
-
@bodts_txt ||= path_exists?("robots.txt")
|
20
|
+
@bodts_txt ||= path_exists?("robots.txt") if proper_404s?
|
21
21
|
end
|
22
22
|
|
23
23
|
def sitemap_xml?
|
24
|
-
@sitemap_xml ||= path_exists?("sitemap.xml")
|
24
|
+
@sitemap_xml ||= path_exists?("sitemap.xml") if proper_404s?
|
25
25
|
end
|
26
26
|
|
27
27
|
def humans_txt?
|
28
|
-
@humans_txt ||= path_exists?("humans.txt")
|
28
|
+
@humans_txt ||= path_exists?("humans.txt") if proper_404s?
|
29
29
|
end
|
30
30
|
|
31
31
|
def doctype
|
32
|
-
document.internal_subset.
|
32
|
+
document.internal_subset.external_id
|
33
33
|
end
|
34
34
|
|
35
35
|
def prefetch
|
36
|
+
return unless endpoint.up?
|
36
37
|
options = SiteInspector.typhoeus_defaults.merge(followlocation: true)
|
37
38
|
["robots.txt", "sitemap.xml", "humans.txt", random_path].each do |path|
|
38
39
|
request = Typhoeus::Request.new(URI.join(endpoint.uri, path), options)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class SiteInspector
|
2
|
+
class Endpoint
|
3
|
+
class Cookies < Check
|
4
|
+
|
5
|
+
def any?(&block)
|
6
|
+
if cookie_header.nil? || cookie_header.empty?
|
7
|
+
false
|
8
|
+
elsif block_given?
|
9
|
+
all.any? { |cookie| block.call(cookie) }
|
10
|
+
else
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
alias_method :cookies?, :any?
|
15
|
+
|
16
|
+
def all
|
17
|
+
@cookies ||= cookie_header.map { |c| CGI::Cookie::parse(c) } if cookies?
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](key)
|
21
|
+
all.find { |cookie| cookie.keys.first == key } if cookies?
|
22
|
+
end
|
23
|
+
|
24
|
+
def secure?
|
25
|
+
pairs = cookie_header.join("; ").split("; ") # CGI::Cookies#Parse doesn't seem to like secure headers
|
26
|
+
pairs.any? { |c| c.downcase == "secure" } && pairs.any? { |c| c.downcase == "httponly" }
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_h
|
30
|
+
{
|
31
|
+
:cookie? => any?,
|
32
|
+
:secure? => secure?
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def cookie_header
|
39
|
+
# Cookie header may be an array or string, always return an array
|
40
|
+
[endpoint.headers.all["set-cookie"]].flatten.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -2,12 +2,6 @@ class SiteInspector
|
|
2
2
|
class Endpoint
|
3
3
|
class Headers < Check
|
4
4
|
|
5
|
-
# cookies can have multiple set-cookie headers, so this detects
|
6
|
-
# whether cookies are set, but not all their values.
|
7
|
-
def cookies?
|
8
|
-
!!headers["set-cookie"]
|
9
|
-
end
|
10
|
-
|
11
5
|
# TODO: kill this
|
12
6
|
def strict_transport_security?
|
13
7
|
!!strict_transport_security
|
@@ -49,13 +43,6 @@ class SiteInspector
|
|
49
43
|
xss_protection == "1; mode=block"
|
50
44
|
end
|
51
45
|
|
52
|
-
def secure_cookies?
|
53
|
-
return false if !cookies?
|
54
|
-
cookie = headers["set-cookie"]
|
55
|
-
cookie = cookie.first if cookie.is_a?(Array)
|
56
|
-
!!(cookie =~ /(; secure.*; httponly|; httponly.*; secure)/i)
|
57
|
-
end
|
58
|
-
|
59
46
|
# Returns an array of hashes of downcased key/value header pairs (or an empty hash)
|
60
47
|
def all
|
61
48
|
@all ||= (response && response.headers) ? Hash[response.headers.map{ |k,v| [k.downcase,v] }] : {}
|
@@ -68,14 +55,11 @@ class SiteInspector
|
|
68
55
|
|
69
56
|
def to_h
|
70
57
|
{
|
71
|
-
:cookies => cookies?,
|
72
58
|
:strict_transport_security => strict_transport_security || false,
|
73
59
|
:content_security_policy => content_security_policy || false,
|
74
60
|
:click_jacking_protection => click_jacking_protection || false,
|
75
|
-
:click_jacking_protection => click_jacking_protection || false,
|
76
61
|
:server => server,
|
77
62
|
:xss_protection => xss_protection || false,
|
78
|
-
:secure_cookies => secure_cookies?
|
79
63
|
}
|
80
64
|
end
|
81
65
|
end
|
@@ -2,8 +2,31 @@ class SiteInspector
|
|
2
2
|
class Endpoint
|
3
3
|
class Sniffer < Check
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
OPEN_SOURCE_FRAMEWORKS = [
|
6
|
+
# Sniffles
|
7
|
+
:drupal,
|
8
|
+
:joomla,
|
9
|
+
:movabletype,
|
10
|
+
:phpbb,
|
11
|
+
:wordpress,
|
12
|
+
|
13
|
+
# Internal
|
14
|
+
:php,
|
15
|
+
:expression_engine,
|
16
|
+
:cowboy
|
17
|
+
]
|
18
|
+
|
19
|
+
def framework
|
20
|
+
cms = sniff :cms
|
21
|
+
return cms unless cms.nil?
|
22
|
+
return :expression_engine if endpoint.cookies.any? { |c| c.keys.first =~ /^exp_/ }
|
23
|
+
return :php if endpoint.cookies["PHPSESSID"]
|
24
|
+
return :cowboy if endpoint.headers.server.to_s.downcase == "cowboy"
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def open_source?
|
29
|
+
OPEN_SOURCE_FRAMEWORKS.include?(framework)
|
7
30
|
end
|
8
31
|
|
9
32
|
def analytics
|
@@ -20,7 +43,7 @@ class SiteInspector
|
|
20
43
|
|
21
44
|
def to_h
|
22
45
|
{
|
23
|
-
:
|
46
|
+
:framework => framework,
|
24
47
|
:analytics => analytics,
|
25
48
|
:javascript => javascript,
|
26
49
|
:advertising => advertising
|
@@ -31,9 +54,8 @@ class SiteInspector
|
|
31
54
|
|
32
55
|
def sniff(type)
|
33
56
|
require 'sniffles'
|
34
|
-
results = Sniffles.sniff(endpoint.content.body, type).select { |name, meta| meta[:found]
|
35
|
-
results.
|
36
|
-
results
|
57
|
+
results = Sniffles.sniff(endpoint.content.body, type).select { |name, meta| meta[:found] }
|
58
|
+
results.keys.first if results
|
37
59
|
rescue
|
38
60
|
nil
|
39
61
|
end
|
@@ -31,8 +31,10 @@ class SiteInspector
|
|
31
31
|
|
32
32
|
private
|
33
33
|
|
34
|
+
# The `request` is a Typhoeus::Request, which provides a
|
35
|
+
# unique `cache_key` string for exactly this sort of thing.
|
34
36
|
def path(request)
|
35
|
-
File.join(@dir, request)
|
37
|
+
File.join(@dir, request.cache_key)
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
@@ -32,12 +32,20 @@ class SiteInspector
|
|
32
32
|
Gman.valid? host
|
33
33
|
end
|
34
34
|
|
35
|
-
# Does *any* endpoint return a 200 response code?
|
35
|
+
# Does *any* endpoint return a 200 or 300 response code?
|
36
36
|
def up?
|
37
37
|
endpoints.any? { |e| e.up? }
|
38
38
|
end
|
39
39
|
|
40
|
-
# Does any
|
40
|
+
# Does *any* endpoint respond to HTTP?
|
41
|
+
# TODO: needs to allow an invalid chain.
|
42
|
+
def responds?
|
43
|
+
endpoints.any? { |e| e.responds? }
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# TODO: These weren't present before, and may not be useful.
|
48
|
+
# Can you connect to www?
|
41
49
|
def www?
|
42
50
|
endpoints.any? { |e| e.www? && e.up? }
|
43
51
|
end
|
@@ -51,11 +59,13 @@ class SiteInspector
|
|
51
59
|
#
|
52
60
|
# * Either of the HTTPS endpoints is listening, and doesn't have
|
53
61
|
# an invalid hostname.
|
62
|
+
#
|
63
|
+
# TODO: needs to allow an invalid chain.
|
54
64
|
def https?
|
55
65
|
endpoints.any? { |e| e.https? && e.up? && e.https.valid? }
|
56
66
|
end
|
57
67
|
|
58
|
-
# HTTPS is enforced if one of the HTTPS endpoints is "
|
68
|
+
# HTTPS is enforced if one of the HTTPS endpoints is "up",
|
59
69
|
# and if both *HTTP* endpoints are either:
|
60
70
|
#
|
61
71
|
# * down, or
|
@@ -66,14 +76,19 @@ class SiteInspector
|
|
66
76
|
# * an HTTP redirect can go to HTTPS on another domain, as long
|
67
77
|
# as it's immediate.
|
68
78
|
# * a domain with an invalid cert can still be enforcing HTTPS.
|
79
|
+
#
|
80
|
+
# TODO: need to ensure the redirect *immediately* goes to HTTPS.
|
81
|
+
# TODO: don't need to require that the HTTPS cert is valid for this purpose.
|
69
82
|
def enforces_https?
|
70
83
|
return false unless https?
|
71
|
-
endpoints.select { |e| e.http? }.all? { |e| e.
|
84
|
+
endpoints.select { |e| e.http? }.all? { |e| !e.up? || (e.redirect && e.redirect.https?) }
|
72
85
|
end
|
73
86
|
|
74
87
|
# we can say that a canonical HTTPS site "defaults" to HTTPS,
|
75
88
|
# even if it doesn't *strictly* enforce it (e.g. having a www
|
76
89
|
# subdomain first to go HTTP root before HTTPS root).
|
90
|
+
#
|
91
|
+
# TODO: not implemented.
|
77
92
|
def defaults_https?
|
78
93
|
raise "Not implemented. Halp?"
|
79
94
|
end
|
@@ -82,9 +97,11 @@ class SiteInspector
|
|
82
97
|
#
|
83
98
|
# * HTTPS is supported, and
|
84
99
|
# * The 'canonical' endpoint gets an immediate internal redirect to HTTP.
|
100
|
+
#
|
101
|
+
# TODO: the redirect must be internal.
|
85
102
|
def downgrades_https?
|
86
103
|
return false unless https?
|
87
|
-
canonical_endpoint.redirect && canonical_endpoint.redirect.http?
|
104
|
+
canonical_endpoint.redirect? && canonical_endpoint.redirect.http?
|
88
105
|
end
|
89
106
|
|
90
107
|
# A domain is "canonically" at www if:
|
@@ -108,7 +125,7 @@ class SiteInspector
|
|
108
125
|
return false unless www?
|
109
126
|
|
110
127
|
# Are both root endpoints down?
|
111
|
-
return true if endpoints.select { |e| e.root? }.all? { |e| e.
|
128
|
+
return true if endpoints.select { |e| e.root? }.all? { |e| !e.up? }
|
112
129
|
|
113
130
|
# Does either root endpoint redirect to a www endpoint?
|
114
131
|
endpoints.select { |e| e.root? }.any? { |e| e.redirect && e.redirect.www? }
|
@@ -139,7 +156,7 @@ class SiteInspector
|
|
139
156
|
return false unless https?
|
140
157
|
|
141
158
|
# Both http endpoints are down
|
142
|
-
return true if endpoints.select { |e| e.http? }.all? { |e| e.
|
159
|
+
return true if endpoints.select { |e| e.http? }.all? { |e| !e.up? }
|
143
160
|
|
144
161
|
# at least one http endpoint redirects immediately to https
|
145
162
|
endpoints.select { |e| e.http? }.any? { |e| e.redirect && e.redirect.https? }
|
@@ -150,7 +167,7 @@ class SiteInspector
|
|
150
167
|
# 2. All endpoints are either down or an external redirect
|
151
168
|
def redirect?
|
152
169
|
return false unless redirect
|
153
|
-
endpoints.all? { |e| e.
|
170
|
+
endpoints.all? { |e| !e.up? || e.external_redirect? }
|
154
171
|
end
|
155
172
|
|
156
173
|
# The first endpoint to respond with a redirect
|
@@ -205,10 +222,11 @@ class SiteInspector
|
|
205
222
|
# Returns a complete hash of the domain's information
|
206
223
|
def to_h(options={})
|
207
224
|
prefetch
|
208
|
-
|
225
|
+
|
209
226
|
hash = {
|
210
227
|
host: host,
|
211
228
|
up: up?,
|
229
|
+
responds: responds?,
|
212
230
|
www: www?,
|
213
231
|
root: root?,
|
214
232
|
https: https?,
|
@@ -220,7 +238,7 @@ class SiteInspector
|
|
220
238
|
hsts: hsts?,
|
221
239
|
hsts_subdomains: hsts_subdomains?,
|
222
240
|
hsts_preload_ready: hsts_preload_ready?,
|
223
|
-
|
241
|
+
canonical_endpoint: canonical_endpoint.to_h(options)
|
224
242
|
}
|
225
243
|
|
226
244
|
if options["all"]
|
@@ -56,11 +56,6 @@ class SiteInspector
|
|
56
56
|
@response ||= request
|
57
57
|
end
|
58
58
|
|
59
|
-
# Does the server return any response? (including 50x)
|
60
|
-
def response?
|
61
|
-
response.code != 0 && !timed_out?
|
62
|
-
end
|
63
|
-
|
64
59
|
def response_code
|
65
60
|
response.response_code.to_s if response
|
66
61
|
end
|
@@ -74,8 +69,9 @@ class SiteInspector
|
|
74
69
|
response && response_code.start_with?("2") || response_code.start_with?("3")
|
75
70
|
end
|
76
71
|
|
77
|
-
|
78
|
-
|
72
|
+
# Does the server respond at all?
|
73
|
+
def responds?
|
74
|
+
response.code != 0 && !timed_out?
|
79
75
|
end
|
80
76
|
|
81
77
|
# If the domain is a redirect, what's the first endpoint we're redirected to?
|
@@ -155,6 +151,7 @@ class SiteInspector
|
|
155
151
|
https: https?,
|
156
152
|
scheme: scheme,
|
157
153
|
up: up?,
|
154
|
+
responds: responds?,
|
158
155
|
timed_out: timed_out?,
|
159
156
|
redirect: redirect?,
|
160
157
|
external_redirect: external_redirect?,
|
@@ -172,7 +169,7 @@ class SiteInspector
|
|
172
169
|
end
|
173
170
|
|
174
171
|
def self.checks
|
175
|
-
ObjectSpace.each_object(Class).select { |klass| klass < Check }
|
172
|
+
ObjectSpace.each_object(Class).select { |klass| klass < Check }.select { |check| check.enabled? }
|
176
173
|
end
|
177
174
|
|
178
175
|
def method_missing(method_sym, *arguments, &block)
|
data/lib/site-inspector.rb
CHANGED
@@ -2,18 +2,22 @@ require 'open-uri'
|
|
2
2
|
require 'addressable/uri'
|
3
3
|
require 'public_suffix'
|
4
4
|
require 'typhoeus'
|
5
|
+
require 'cliver'
|
6
|
+
require 'cgi'
|
5
7
|
|
6
8
|
require_relative 'site-inspector/cache'
|
7
9
|
require_relative 'site-inspector/disk_cache'
|
8
10
|
require_relative 'site-inspector/rails_cache'
|
9
11
|
require_relative 'site-inspector/domain'
|
10
12
|
require_relative 'site-inspector/checks/check'
|
13
|
+
require_relative 'site-inspector/checks/accessibility'
|
11
14
|
require_relative 'site-inspector/checks/content'
|
12
15
|
require_relative 'site-inspector/checks/dns'
|
13
16
|
require_relative 'site-inspector/checks/headers'
|
14
17
|
require_relative 'site-inspector/checks/hsts'
|
15
18
|
require_relative 'site-inspector/checks/https'
|
16
19
|
require_relative 'site-inspector/checks/sniffer'
|
20
|
+
require_relative 'site-inspector/checks/cookies'
|
17
21
|
require_relative 'site-inspector/endpoint'
|
18
22
|
require_relative 'site-inspector/version'
|
19
23
|
|
@@ -46,7 +50,7 @@ class SiteInspector
|
|
46
50
|
:timeout => SiteInspector.timeout,
|
47
51
|
:accept_encoding => "gzip",
|
48
52
|
:headers => {
|
49
|
-
"User-Agent" => "Mozilla/5.0 (compatible; SiteInspector/#{SiteInspector::VERSION}; +https://github.com/benbalter/site-inspector
|
53
|
+
"User-Agent" => "Mozilla/5.0 (compatible; SiteInspector/#{SiteInspector::VERSION}; +https://github.com/benbalter/site-inspector)"
|
50
54
|
}
|
51
55
|
}
|
52
56
|
end
|
data/package.json
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"name": "site-inspector",
|
3
|
+
"version": "2.0.0",
|
4
|
+
"description": "Returns information about a domain's technology and capabilities",
|
5
|
+
"main": "site-inspector",
|
6
|
+
"dependencies": {
|
7
|
+
"pa11y": "^2.1.0"
|
8
|
+
},
|
9
|
+
"devDependencies": {},
|
10
|
+
"scripts": {
|
11
|
+
"test": "script/cibuild"
|
12
|
+
},
|
13
|
+
"repository": {
|
14
|
+
"type": "git",
|
15
|
+
"url": "git+https://github.com/benbalter/site-inspector.git"
|
16
|
+
},
|
17
|
+
"author": "",
|
18
|
+
"license": "MIT",
|
19
|
+
"bugs": {
|
20
|
+
"url": "https://github.com/benbalter/site-inspector/issues"
|
21
|
+
},
|
22
|
+
"homepage": "https://github.com/benbalter/site-inspector#readme"
|
23
|
+
}
|
data/script/bootstrap
CHANGED
data/script/cibuild
CHANGED
data/site-inspector.gemspec
CHANGED
@@ -4,11 +4,11 @@ Gem::Specification.new do |s|
|
|
4
4
|
|
5
5
|
s.name = "site-inspector"
|
6
6
|
s.version = SiteInspector::VERSION
|
7
|
-
s.summary = "A Ruby port and v2 of Site Inspector (
|
7
|
+
s.summary = "A Ruby port and v2 of Site Inspector (https://github.com/benbalter/site-inspector)"
|
8
8
|
s.description = "Returns information about a domain's technology and capabilities"
|
9
9
|
s.authors = "Ben Balter"
|
10
10
|
s.email = "ben@balter.com"
|
11
|
-
s.homepage = "https://github.com/benbalter/site-inspector
|
11
|
+
s.homepage = "https://github.com/benbalter/site-inspector"
|
12
12
|
s.license = "MIT"
|
13
13
|
|
14
14
|
s.files = `git ls-files -z`.split("\x0")
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency("oj", "~> 2.11")
|
26
26
|
s.add_dependency("mercenary", "~> 0.3")
|
27
27
|
s.add_dependency("colorator", "~> 0.1")
|
28
|
+
s.add_dependency("cliver", "~> 0.3")
|
28
29
|
s.add_development_dependency("pry", "~> 0.10")
|
29
30
|
s.add_development_dependency( "rake", "~> 10.4" )
|
30
31
|
s.add_development_dependency( "rspec", "~> 3.2")
|