Skip to content

Commit faa4ccd

Browse files
authored
Merge pull request #96 from github/customizable-nameservers
Allow Domain to specify what kind of nameservers it wants to use
2 parents a3209d6 + 255d4c8 commit faa4ccd

File tree

13 files changed

+161
-83
lines changed

13 files changed

+161
-83
lines changed

lib/github-pages-health-check.rb

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,19 @@
1919

2020
module GitHubPages
2121
module HealthCheck
22-
autoload :CDN, "github-pages-health-check/cdn"
23-
autoload :CloudFlare, "github-pages-health-check/cdns/cloudflare"
24-
autoload :Fastly, "github-pages-health-check/cdns/fastly"
25-
autoload :Error, "github-pages-health-check/error"
26-
autoload :Errors, "github-pages-health-check/errors"
27-
autoload :CAA, "github-pages-health-check/caa"
28-
autoload :Checkable, "github-pages-health-check/checkable"
29-
autoload :Domain, "github-pages-health-check/domain"
30-
autoload :Repository, "github-pages-health-check/repository"
31-
autoload :Resolver, "github-pages-health-check/resolver"
32-
autoload :Site, "github-pages-health-check/site"
33-
autoload :Printer, "github-pages-health-check/printer"
22+
autoload :CDN, "github-pages-health-check/cdn"
23+
autoload :CloudFlare, "github-pages-health-check/cdns/cloudflare"
24+
autoload :Fastly, "github-pages-health-check/cdns/fastly"
25+
autoload :Error, "github-pages-health-check/error"
26+
autoload :Errors, "github-pages-health-check/errors"
27+
autoload :CAA, "github-pages-health-check/caa"
28+
autoload :Checkable, "github-pages-health-check/checkable"
29+
autoload :Domain, "github-pages-health-check/domain"
30+
autoload :RedundantCheck, "github-pages-health-check/redundant_check"
31+
autoload :Repository, "github-pages-health-check/repository"
32+
autoload :Resolver, "github-pages-health-check/resolver"
33+
autoload :Site, "github-pages-health-check/site"
34+
autoload :Printer, "github-pages-health-check/printer"
3435

3536
# DNS and HTTP timeout, in seconds
3637
TIMEOUT = 7

lib/github-pages-health-check/caa.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22

33
require "dnsruby"
44
require "public_suffix"
5+
require "github-pages-health-check/resolver"
56

67
module GitHubPages
78
module HealthCheck
89
class CAA
9-
attr_reader :host
10-
attr_reader :error
10+
attr_reader :host, :error, :nameservers
1111

12-
def initialize(host)
12+
def initialize(host, nameservers: nil)
1313
raise ArgumentError, "host cannot be nil" if host.nil?
1414

1515
@host = host
16+
@nameservers = nameservers
1617
end
1718

1819
def errored?
@@ -47,11 +48,15 @@ def issue_caa_record?(record)
4748
end
4849

4950
def query(domain)
50-
GitHubPages::HealthCheck::Resolver.new(domain).query(Dnsruby::Types::CAA)
51+
resolver(domain).query(Dnsruby::Types::CAA)
5152
rescue Dnsruby::ResolvError, Dnsruby::ResolvTimeout => e
5253
@error = e
5354
[]
5455
end
56+
57+
def resolver(domain)
58+
GitHubPages::HealthCheck::Resolver.new(domain, :nameservers => nameservers)
59+
end
5560
end
5661
end
5762
end

lib/github-pages-health-check/domain.rb

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module GitHubPages
44
module HealthCheck
55
class Domain < Checkable
6-
attr_reader :host
6+
attr_reader :host, :resolver, :nameservers
77

88
LEGACY_IP_ADDRESSES = [
99
# Legacy GitHub Datacenter
@@ -89,12 +89,19 @@ class Domain < Checkable
8989
https? enforces_https? https_error https_eligible? caa_error
9090
].freeze
9191

92-
def initialize(host)
92+
def self.redundant(host)
93+
GitHubPages::HealthCheck::RedundantCheck.new(host).check
94+
end
95+
96+
def initialize(host, nameservers: :default)
9397
unless host.is_a? String
9498
raise ArgumentError, "Expected string, got #{host.class}"
9599
end
96100

97101
@host = normalize_host(host)
102+
@nameservers = nameservers
103+
@resolver = GitHubPages::HealthCheck::Resolver.new(host,
104+
:nameservers => nameservers)
98105
end
99106

100107
# Runs all checks, raises an error if invalid
@@ -269,10 +276,6 @@ def dns
269276
@dns = nil
270277
end
271278

272-
def resolver
273-
@resolver ||= GitHubPages::HealthCheck::Resolver.new(absolute_domain)
274-
end
275-
276279
# Are we even able to get the DNS record?
277280
def dns?
278281
!(dns.nil? || dns.empty?)
@@ -371,7 +374,7 @@ def caa_error
371374
private
372375

373376
def caa
374-
@caa ||= GitHubPages::HealthCheck::CAA.new(host)
377+
@caa ||= GitHubPages::HealthCheck::CAA.new(host, :nameservers => nameservers)
375378
end
376379

377380
# The domain's response to HTTP(S) requests, following redirects
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# frozen_string_literal: true
2+
3+
module GitHubPages
4+
module HealthCheck
5+
class RedundantCheck
6+
extend Forwardable
7+
8+
TIMEOUT = 5 # seconds
9+
10+
attr_reader :domain
11+
12+
def initialize(domain)
13+
@domain = domain
14+
end
15+
16+
def check
17+
@check ||= (checks.find(&:valid?) || check_with_default_nameservers)
18+
end
19+
20+
def_delegator :check, :reason, :reason
21+
def_delegator :check, :valid?, :valid?
22+
23+
def https_eligible?
24+
checks.any?(&:https_eligible?)
25+
end
26+
27+
private
28+
29+
def checks
30+
@checks ||= %i[default authoritative].map do |ns|
31+
GitHubPages::HealthCheck::Domain.new(domain, :nameservers => ns)
32+
end
33+
end
34+
35+
def check_with_default_nameservers
36+
@check_with_default_nameservers ||= checks.find { |c| c.nameservers == :default }
37+
end
38+
end
39+
end
40+
end

lib/github-pages-health-check/repository.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def last_built
5454

5555
def domain
5656
return if cname.nil?
57-
@domain ||= GitHubPages::HealthCheck::Domain.new(cname)
57+
@domain ||= GitHubPages::HealthCheck::Domain.redundant(cname)
5858
end
5959

6060
private

lib/github-pages-health-check/resolver.rb

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,53 @@ module GitHubPages
44
module HealthCheck
55
class Resolver
66
DEFAULT_RESOLVER_OPTIONS = {
7-
:retry_times => 2,
7+
:retry_times => 2,
88
:query_timeout => 5,
9-
:dnssec => false
9+
:dnssec => false
1010
}.freeze
1111

12-
PREFERS_AUTHORITATIVE_ANSWER = [
13-
Dnsruby::Types::A,
14-
Dnsruby::Types::CAA,
15-
Dnsruby::Types::MX
16-
].freeze
17-
1812
class << self
1913
def default_resolver
2014
@default_resolver ||= Dnsruby::Resolver.new(DEFAULT_RESOLVER_OPTIONS)
2115
end
2216
end
2317

24-
attr_reader :domain
18+
attr_reader :domain, :nameservers
2519

26-
def initialize(domain)
20+
# Create a new resolver.
21+
#
22+
# domain - the domain we're getting answers for
23+
# nameserver - (optional) a case
24+
def initialize(domain, nameservers: :default)
2725
@domain = domain
26+
@nameservers = nameservers
2827
end
2928

3029
def query(type)
31-
if PREFERS_AUTHORITATIVE_ANSWER.include?(type)
32-
answer = authoritative_resolver.query(domain, type).answer
33-
return answer unless answer.empty?
34-
end
35-
36-
self.class.default_resolver.query(domain, type).answer
37-
rescue Dnsruby::ResolvTimeout, Dnsruby::ResolvError
38-
self.class.default_resolver.query(domain, type).answer
30+
resolver.query(domain, type).answer
3931
end
4032

4133
private
4234

43-
def authoritative_resolver
44-
return self.class.default_resolver if nameservers.nil? || nameservers.empty?
45-
46-
Dnsruby::Resolver.new(DEFAULT_RESOLVER_OPTIONS.merge(:nameservers => nameservers))
35+
def resolver
36+
@resolver ||= case nameservers
37+
when :default
38+
self.class.default_resolver
39+
when :authoritative
40+
Dnsruby::Resolver.new(DEFAULT_RESOLVER_OPTIONS.merge(
41+
:nameservers => authoritative_nameservers
42+
))
43+
when Array
44+
Dnsruby::Resolver.new(DEFAULT_RESOLVER_OPTIONS.merge(
45+
:nameservers => nameservers
46+
))
47+
else
48+
raise "Invalid nameserver type: #{nameservers.inspect}"
49+
end
4750
end
4851

49-
def nameservers
50-
@nameservers ||= begin
52+
def authoritative_nameservers
53+
@authoritative_nameservers ||= begin
5154
self.class.default_resolver.query(domain, Dnsruby::Types::NS).answer.map do |rr|
5255
next rr.nsdname.to_s if rr.type == Dnsruby::Types::NS
5356
end.compact

lib/github-pages-health-check/site.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def initialize(repository_or_domain, access_token: nil)
1010
@domain = @repository.domain
1111
rescue GitHubPages::HealthCheck::Errors::InvalidRepositoryError
1212
@repository = nil
13-
@domain = Domain.new(repository_or_domain)
13+
@domain = Domain.redundant(repository_or_domain)
1414
end
1515

1616
def check!

script/cibuild

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ script/bootstrap
66

77
script/test
88
script/check-cdn-ips
9+
bundle exec script/check www.parkermoore.de | grep 'valid?: true'
10+
bundle exec script/check ben.balter.com | grep 'valid?: true'
911
bundle exec gem build github-pages-health-check.gemspec

spec/github_pages_health_check/domain_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@
462462
let(:headers) { {} }
463463

464464
before do
465+
allow(subject).to receive(:dns) { [a_packet] }
465466
stub_request(:head, domain)
466467
.to_return(:status => status, :headers => headers)
467468
end
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require "spec_helper"
2+
3+
RSpec.describe(GitHubPages::HealthCheck::RedundantCheck) do
4+
let(:domain) { "www.parkermoore.de" }
5+
subject { described_class.new(domain) }
6+
before(:each) do
7+
stub_request(:head, "http://#{domain}/")
8+
.to_return(:status => 200, :body => "", :headers => { "Server" => "GitHub.com" })
9+
end
10+
11+
it { is_expected.to be_valid }
12+
it { is_expected.to be_https_eligible }
13+
14+
it "has a link to the check which was most valid" do
15+
expect(subject.check).not_to be_nil
16+
expect(subject.check).to be_valid
17+
end
18+
end

0 commit comments

Comments
 (0)