sla 0.3.6 → 0.3.7
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/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 +17 -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,35 +1,35 @@
|
|
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
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.8'
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: 0.8.1
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0.8'
|
30
27
|
- - ">="
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: 0.8.1
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: mister_bin
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,33 +45,33 @@ dependencies:
|
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0.7'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
48
|
+
name: nokogiri
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '1.10'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
60
|
+
version: '1.10'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: webcache
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
67
|
+
version: '0.8'
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '0.8'
|
75
75
|
description: Check for broken links on a website
|
76
76
|
email: db@dannyben.com
|
77
77
|
executables:
|
@@ -94,7 +94,8 @@ files:
|
|
94
94
|
homepage: https://github.com/DannyBen/sla
|
95
95
|
licenses:
|
96
96
|
- MIT
|
97
|
-
metadata:
|
97
|
+
metadata:
|
98
|
+
rubygems_mfa_required: 'true'
|
98
99
|
post_install_message:
|
99
100
|
rdoc_options: []
|
100
101
|
require_paths:
|
@@ -110,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
111
|
- !ruby/object:Gem::Version
|
111
112
|
version: '0'
|
112
113
|
requirements: []
|
113
|
-
rubygems_version: 3.4.
|
114
|
+
rubygems_version: 3.4.5
|
114
115
|
signing_key:
|
115
116
|
specification_version: 4
|
116
117
|
summary: Command Line Site Link Analyzer
|