sla 0.3.5 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/sla +2 -5
- data/lib/sla/checker.rb +69 -69
- data/lib/sla/command.rb +38 -28
- data/lib/sla/exceptions.rb +1 -1
- data/lib/sla/formatters/base.rb +5 -5
- data/lib/sla/formatters/simple.rb +6 -5
- data/lib/sla/formatters/tty.rb +9 -9
- data/lib/sla/formatters/verbose.rb +10 -11
- data/lib/sla/page.rb +7 -5
- data/lib/sla/version.rb +2 -2
- data/lib/sla.rb +1 -1
- metadata +23 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3df29353cfd95a9b0b5ae9edfe228aba3d653f0dfa0656c6f7d0aafda9301ebe
|
4
|
+
data.tar.gz: 304f2711c046fc307c939230365d89cd7a3bf832614f9410b4aec62a59dc6dee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c527a92e2e8c28d0e9c5f4bf4aa51c93a44058cd7c00ce2dfd0f8ed6c2176f78b252859b095478174e5a18b384c85f22cf098a7690dbbcd19406d16c95c1607
|
7
|
+
data.tar.gz: d79c49cadf1e3d0919853f4a535f1fca2e4d9a210d89d5fee8a1e095b40b1e6a7fa86552946a996d384bf4389ca7f54ef691dc1c829a1927fc1cb3213112b7c8
|
data/bin/sla
CHANGED
@@ -6,13 +6,10 @@ router = MisterBin::Runner.new handler: SLA::Command
|
|
6
6
|
|
7
7
|
begin
|
8
8
|
exit router.run ARGV
|
9
|
-
|
10
|
-
|
11
|
-
puts "(exit code 1)"
|
9
|
+
rescue SLA::BrokenLinks
|
10
|
+
puts '(exit code 1)'
|
12
11
|
exit 1
|
13
|
-
|
14
12
|
rescue Interrupt
|
15
13
|
puts "\nGoodbye"
|
16
14
|
exit 1
|
17
|
-
|
18
15
|
end
|
data/lib/sla/checker.rb
CHANGED
@@ -1,69 +1,69 @@
|
|
1
|
-
module SLA
|
2
|
-
class Checker
|
3
|
-
attr_reader :max_depth, :ignore, :check_external
|
4
|
-
|
5
|
-
def initialize(max_depth: 5, ignore: nil, check_external: false)
|
6
|
-
@max_depth = max_depth
|
7
|
-
@ignore = ignore
|
8
|
-
@check_external = check_external
|
9
|
-
end
|
10
|
-
|
11
|
-
def check(page, &block)
|
12
|
-
return if skip? page
|
13
|
-
|
14
|
-
yield [:source, page] if
|
15
|
-
|
16
|
-
pages = page_list page
|
17
|
-
|
18
|
-
pages.each do |
|
19
|
-
if checked.has_key?
|
20
|
-
yield [:skip,
|
21
|
-
else
|
22
|
-
checked[
|
23
|
-
yield [:check,
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
pages.each do |
|
28
|
-
next if deeply_checked.has_key?
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
page.pages
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
|
1
|
+
module SLA
|
2
|
+
class Checker
|
3
|
+
attr_reader :max_depth, :ignore, :check_external
|
4
|
+
|
5
|
+
def initialize(max_depth: 5, ignore: nil, check_external: false)
|
6
|
+
@max_depth = max_depth
|
7
|
+
@ignore = ignore
|
8
|
+
@check_external = check_external
|
9
|
+
end
|
10
|
+
|
11
|
+
def check(page, &block)
|
12
|
+
return if skip? page
|
13
|
+
|
14
|
+
yield [:source, page] if block
|
15
|
+
|
16
|
+
pages = page_list page
|
17
|
+
|
18
|
+
pages.each do |next_page|
|
19
|
+
if checked.has_key?(next_page.url) || ignore?(next_page)
|
20
|
+
yield [:skip, next_page] if block
|
21
|
+
else
|
22
|
+
checked[next_page.url] = true
|
23
|
+
yield [:check, next_page] if block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
pages.each do |next_page|
|
28
|
+
next if deeply_checked.has_key? next_page.url
|
29
|
+
|
30
|
+
deeply_checked[next_page.url] = true
|
31
|
+
next if next_page.external?
|
32
|
+
|
33
|
+
check next_page, &block
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def page_list(page)
|
40
|
+
if check_external
|
41
|
+
page.pages
|
42
|
+
else
|
43
|
+
page.pages.reject(&:external?)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def skip?(page)
|
48
|
+
ignore?(page) or page.depth >= max_depth or !page.valid?
|
49
|
+
end
|
50
|
+
|
51
|
+
def ignore?(page)
|
52
|
+
return false unless ignore
|
53
|
+
|
54
|
+
ignore.each do |text|
|
55
|
+
return true if page.url.include? text
|
56
|
+
end
|
57
|
+
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def deeply_checked
|
62
|
+
@deeply_checked ||= {}
|
63
|
+
end
|
64
|
+
|
65
|
+
def checked
|
66
|
+
@checked ||= {}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/sla/command.rb
CHANGED
@@ -2,32 +2,42 @@ module SLA
|
|
2
2
|
class Command < MisterBin::Command
|
3
3
|
include Colsole
|
4
4
|
|
5
|
-
help
|
5
|
+
help 'Site Link Analyzer'
|
6
6
|
|
7
7
|
version VERSION
|
8
8
|
|
9
|
-
usage
|
10
|
-
usage
|
9
|
+
usage 'sla URL [options]'
|
10
|
+
usage 'sla --help | -h | --version'
|
11
11
|
|
12
|
-
param
|
12
|
+
param 'URL', 'URL to scan'
|
13
13
|
|
14
|
-
option
|
15
|
-
option
|
16
|
-
option
|
17
|
-
option
|
18
|
-
option
|
19
|
-
|
20
|
-
|
14
|
+
option '--verbose, -v', 'Show detailed output'
|
15
|
+
option '--simple, -s', 'Show simple output of errors only'
|
16
|
+
option '--depth, -d DEPTH', 'Set crawling depth [default: 5]'
|
17
|
+
option '--external, -x', 'Also check external links'
|
18
|
+
option '--ignore, -i URLS', <<~USAGE
|
19
|
+
Specify a list of space delimited patterns to skip
|
20
|
+
URLs that contain any of the strings in this list will be skipped
|
21
|
+
USAGE
|
22
|
+
option '--cache, -c LIFE', <<~USAGE
|
23
|
+
Set cache life [default: 1d]. LIFE can be in any of the following formats:
|
24
|
+
10 = 10 seconds
|
25
|
+
20s = 20 seconds
|
26
|
+
10m = 10 minutes
|
27
|
+
10h = 10 hours
|
28
|
+
10d = 10 days
|
29
|
+
USAGE
|
30
|
+
option '--cache-dir DIR', 'Set the cache directory'
|
21
31
|
|
22
|
-
example
|
23
|
-
example
|
24
|
-
example
|
25
|
-
example
|
26
|
-
example
|
27
|
-
example
|
28
|
-
example
|
32
|
+
example 'sla example.com'
|
33
|
+
example 'sla example.com -c10m -d10'
|
34
|
+
example 'sla example.com --cache-dir my_cache'
|
35
|
+
example 'sla example.com --depth 10'
|
36
|
+
example 'sla example.com --cache 30d --external'
|
37
|
+
example 'sla example.com --simple > out.log'
|
38
|
+
example 'sla example.com --ignore "/admin /customer/login"'
|
29
39
|
|
30
|
-
environment
|
40
|
+
environment 'SLA_SLEEP', 'Set number of seconds to sleep between calls (for debugging purposes)'
|
31
41
|
|
32
42
|
def run
|
33
43
|
WebCache.life = args['--cache']
|
@@ -36,13 +46,13 @@ module SLA
|
|
36
46
|
max_depth = args['--depth'].to_i
|
37
47
|
url = args['URL']
|
38
48
|
ignore = args['--ignore']
|
39
|
-
ignore = ignore.split
|
49
|
+
ignore = ignore.split if ignore
|
40
50
|
check_external = args['--external']
|
41
51
|
|
42
52
|
checker = Checker.new max_depth: max_depth,
|
43
53
|
ignore: ignore, check_external: check_external
|
44
54
|
|
45
|
-
formatter = if args['--verbose']
|
55
|
+
formatter = if args['--verbose']
|
46
56
|
Formatters::Verbose.new
|
47
57
|
elsif args['--simple']
|
48
58
|
Formatters::Simple.new
|
@@ -54,17 +64,17 @@ module SLA
|
|
54
64
|
end
|
55
65
|
|
56
66
|
def run!(url, checker, formatter)
|
57
|
-
|
58
|
-
checker.check
|
59
|
-
|
67
|
+
initial_page = Page.new url
|
68
|
+
checker.check initial_page do |action, page|
|
69
|
+
formatter.handle action, page
|
60
70
|
sleep ENV['SLA_SLEEP'].to_f if ENV['SLA_SLEEP']
|
61
71
|
end
|
62
72
|
|
63
73
|
formatter.footer
|
64
74
|
|
65
|
-
|
66
|
-
|
67
|
-
|
75
|
+
return if formatter.success? || ENV['SLA_ALLOW_FAILS']
|
76
|
+
|
77
|
+
raise BrokenLinks
|
68
78
|
end
|
69
79
|
end
|
70
|
-
end
|
80
|
+
end
|
data/lib/sla/exceptions.rb
CHANGED
data/lib/sla/formatters/base.rb
CHANGED
@@ -6,11 +6,12 @@ module SLA
|
|
6
6
|
attr_accessor :count, :failed
|
7
7
|
|
8
8
|
def initialize
|
9
|
-
@count
|
9
|
+
@count = 0
|
10
|
+
@failed = 0
|
10
11
|
end
|
11
12
|
|
12
13
|
def success?
|
13
|
-
count
|
14
|
+
count.positive? and failed.zero?
|
14
15
|
end
|
15
16
|
|
16
17
|
def handle(action, page)
|
@@ -24,10 +25,9 @@ module SLA
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def footer
|
27
|
-
color = success? ? '
|
28
|
-
say "#{footer_prefix}#{color}Checked #{count} pages with #{failed} failures"
|
28
|
+
color = success? ? 'g' : 'r'
|
29
|
+
say "#{footer_prefix}#{color}`Checked #{count} pages with #{failed} failures`"
|
29
30
|
end
|
30
|
-
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -7,9 +7,11 @@ module SLA
|
|
7
7
|
@last_source = page.url if action == :source
|
8
8
|
|
9
9
|
return unless action == :check
|
10
|
+
|
10
11
|
@count += 1
|
11
12
|
|
12
13
|
return if page.valid?
|
14
|
+
|
13
15
|
@failed += 1
|
14
16
|
|
15
17
|
show_status page
|
@@ -19,14 +21,13 @@ module SLA
|
|
19
21
|
|
20
22
|
def show_status(page)
|
21
23
|
if last_source
|
22
|
-
say "
|
24
|
+
say "m`SOURCE #{last_source}`"
|
23
25
|
@last_source = nil
|
24
26
|
end
|
25
27
|
|
26
|
-
say "
|
27
|
-
say "
|
28
|
+
say " r`FAIL` #{page.depth} #{page.url}"
|
29
|
+
say " r`#{page.code}` #{page.error}" unless page.code == 404
|
28
30
|
end
|
29
|
-
|
30
31
|
end
|
31
32
|
end
|
32
|
-
end
|
33
|
+
end
|
data/lib/sla/formatters/tty.rb
CHANGED
@@ -8,6 +8,7 @@ module SLA
|
|
8
8
|
@last_source = page.url if action == :source
|
9
9
|
|
10
10
|
return unless action == :check
|
11
|
+
|
11
12
|
@count += 1
|
12
13
|
|
13
14
|
show_status page
|
@@ -21,28 +22,27 @@ module SLA
|
|
21
22
|
|
22
23
|
def show_status(page)
|
23
24
|
if page.valid?
|
24
|
-
status =
|
25
|
-
color =
|
25
|
+
status = 'PASS'
|
26
|
+
color = 'g'
|
26
27
|
else
|
27
28
|
@failed += 1
|
28
|
-
status =
|
29
|
-
color =
|
29
|
+
status = 'FAIL'
|
30
|
+
color = 'r'
|
30
31
|
|
31
32
|
if last_source
|
32
|
-
|
33
|
+
say "m`SOURCE #{last_source}`", replace: true
|
33
34
|
@last_source = nil
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
|
37
|
+
say " r`FAIL` #{page.depth} #{page.url}", replace: true
|
38
|
+
say " r`#{page.code}` #{page.error}", replace: true unless page.code == 404
|
38
39
|
end
|
39
40
|
|
40
41
|
message = "[#{failed}/#{count} @ #{page.depth}] #{status}"
|
41
42
|
remaining_width = screen_width - message.size - 4
|
42
43
|
url = page.url[0..remaining_width]
|
43
|
-
|
44
|
+
say "[#{failed}/#{count} @ #{page.depth}] #{color}`#{status}` #{url} ", replace: true
|
44
45
|
end
|
45
|
-
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -4,13 +4,13 @@ module SLA
|
|
4
4
|
def handle(action, page)
|
5
5
|
case action
|
6
6
|
when :source
|
7
|
-
say "\
|
8
|
-
|
7
|
+
say "\nm`SOURCE #{page.url}`"
|
8
|
+
|
9
9
|
when :check
|
10
10
|
show_check_status page
|
11
11
|
|
12
12
|
when :skip
|
13
|
-
say "
|
13
|
+
say " b`SKIP` #{page.depth} #{page.url}"
|
14
14
|
|
15
15
|
end
|
16
16
|
end
|
@@ -23,19 +23,18 @@ module SLA
|
|
23
23
|
show_error = false
|
24
24
|
|
25
25
|
if page.valid?
|
26
|
-
status =
|
27
|
-
color =
|
26
|
+
status = 'PASS'
|
27
|
+
color = 'g'
|
28
28
|
else
|
29
29
|
@failed += 1
|
30
|
-
status =
|
31
|
-
color =
|
30
|
+
status = 'FAIL'
|
31
|
+
color = 'r'
|
32
32
|
show_error = page.code != 404
|
33
33
|
end
|
34
34
|
|
35
|
-
say " #{color}
|
36
|
-
say "
|
35
|
+
say " #{color}`#{status}` #{page.depth} #{page.url}"
|
36
|
+
say " r`#{page.code}` #{page.error}" if show_error
|
37
37
|
end
|
38
|
-
|
39
38
|
end
|
40
39
|
end
|
41
|
-
end
|
40
|
+
end
|
data/lib/sla/page.rb
CHANGED
@@ -9,7 +9,9 @@ module SLA
|
|
9
9
|
uri.fragment = false
|
10
10
|
end
|
11
11
|
|
12
|
-
@uri
|
12
|
+
@uri = uri
|
13
|
+
@parent = parent
|
14
|
+
@depth = depth
|
13
15
|
end
|
14
16
|
|
15
17
|
def error
|
@@ -60,7 +62,7 @@ module SLA
|
|
60
62
|
|
61
63
|
result = new_url.absolute? ? new_url : URI.join(url, new_url)
|
62
64
|
|
63
|
-
result.scheme
|
65
|
+
/^http/.match?(result.scheme) ? result.to_s : nil
|
64
66
|
end
|
65
67
|
|
66
68
|
def pages!
|
@@ -68,7 +70,8 @@ module SLA
|
|
68
70
|
anchors.each do |a|
|
69
71
|
url = normalize_url a['href']
|
70
72
|
next unless url
|
71
|
-
|
73
|
+
|
74
|
+
page = Page.new url, parent: self, depth: depth + 1
|
72
75
|
result[url] = page
|
73
76
|
end
|
74
77
|
result.values
|
@@ -83,6 +86,5 @@ module SLA
|
|
83
86
|
@uri = response.base_uri
|
84
87
|
response
|
85
88
|
end
|
86
|
-
|
87
89
|
end
|
88
|
-
end
|
90
|
+
end
|
data/lib/sla/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module SLA
|
2
|
-
VERSION =
|
3
|
-
end
|
2
|
+
VERSION = '0.3.7'
|
3
|
+
end
|
data/lib/sla.rb
CHANGED
metadata
CHANGED
@@ -1,71 +1,77 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sla
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Ben Shitrit
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01
|
11
|
+
date: 2023-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colsole
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.1
|
20
|
+
- - "<"
|
18
21
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
22
|
+
version: '2'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
29
|
+
version: 0.8.1
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: mister_bin
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
37
|
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.7
|
39
|
+
version: '0.7'
|
34
40
|
type: :runtime
|
35
41
|
prerelease: false
|
36
42
|
version_requirements: !ruby/object:Gem::Requirement
|
37
43
|
requirements:
|
38
44
|
- - "~>"
|
39
45
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.7
|
46
|
+
version: '0.7'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
48
|
+
name: nokogiri
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - "~>"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
53
|
+
version: '1.10'
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
58
|
- - "~>"
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
60
|
+
version: '1.10'
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
62
|
+
name: webcache
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
58
64
|
requirements:
|
59
65
|
- - "~>"
|
60
66
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
67
|
+
version: '0.8'
|
62
68
|
type: :runtime
|
63
69
|
prerelease: false
|
64
70
|
version_requirements: !ruby/object:Gem::Requirement
|
65
71
|
requirements:
|
66
72
|
- - "~>"
|
67
73
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
74
|
+
version: '0.8'
|
69
75
|
description: Check for broken links on a website
|
70
76
|
email: db@dannyben.com
|
71
77
|
executables:
|
@@ -88,7 +94,8 @@ files:
|
|
88
94
|
homepage: https://github.com/DannyBen/sla
|
89
95
|
licenses:
|
90
96
|
- MIT
|
91
|
-
metadata:
|
97
|
+
metadata:
|
98
|
+
rubygems_mfa_required: 'true'
|
92
99
|
post_install_message:
|
93
100
|
rdoc_options: []
|
94
101
|
require_paths:
|
@@ -104,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
111
|
- !ruby/object:Gem::Version
|
105
112
|
version: '0'
|
106
113
|
requirements: []
|
107
|
-
rubygems_version: 3.4.
|
114
|
+
rubygems_version: 3.4.5
|
108
115
|
signing_key:
|
109
116
|
specification_version: 4
|
110
117
|
summary: Command Line Site Link Analyzer
|