Class: GitHubPages::HealthCheck::Domain
- Defined in:
- lib/github-pages-health-check/domain.rb
Constant Summary collapse
- LEGACY_IP_ADDRESSES =
%w[ 207.97.227.245 204.232.175.78 199.27.73.133 ].freeze
- CURRENT_IP_ADDRESSES =
%w[ 192.30.252.153 192.30.252.154 ].freeze
- HASH_METHODS =
[ :host, :uri, :dns_resolves?, :proxied?, :cloudflare_ip?, :old_ip_address?, :a_record?, :cname_record?, :valid_domain?, :apex_domain?, :should_be_a_record?, :cname_to_github_user_domain?, :cname_to_pages_dot_github_dot_com?, :cname_to_fastly?, :pointed_to_github_pages_ip?, :pages_domain?, :served_by_pages?, :valid_domain? ].freeze
Instance Attribute Summary collapse
-
#host ⇒ Object
readonly
Returns the value of attribute host.
Instance Method Summary collapse
-
#a_record? ⇒ Boolean
Is this domain’s first response an A record?.
-
#apex_domain? ⇒ Boolean
Is this domain an apex domain, meaning a CNAME would be innapropriate.
-
#check! ⇒ Object
Runs all checks, raises an error if invalid.
-
#cloudflare_ip? ⇒ Boolean
Does the domain resolve to a CloudFlare-owned IP.
-
#cname ⇒ Object
The domain to which this domain’s CNAME resolves Returns nil if the domain is not a CNAME.
-
#cname_record? ⇒ Boolean
(also: #cname?)
Is this domain’s first response a CNAME record?.
-
#cname_to_fastly? ⇒ Boolean
Is the given domain CNAME’d directly to our Fastly account?.
-
#cname_to_github_user_domain? ⇒ Boolean
Is the domain’s first response a CNAME to a pages domain?.
-
#cname_to_pages_dot_github_dot_com? ⇒ Boolean
Is the given domain a CNAME to pages.github.(io|com) instead of being CNAME’d to the user’s subdomain?.
- #deprecated_ip? ⇒ Boolean
-
#dns ⇒ Object
Returns an array of DNS answers.
-
#dns? ⇒ Boolean
(also: #dns_resolves?)
Are we even able to get the DNS record?.
-
#fastly? ⇒ Boolean
Is the host our Fastly CNAME?.
-
#github_domain? ⇒ Boolean
Is this domain owned by GitHub?.
-
#initialize(host) ⇒ Domain
constructor
A new instance of Domain.
- #invalid_a_record? ⇒ Boolean
- #invalid_cname? ⇒ Boolean
-
#old_ip_address? ⇒ Boolean
Does this domain have any A record that points to the legacy IPs?.
-
#pages_domain? ⇒ Boolean
Is the host a *.github.io domain?.
-
#pages_dot_github_dot_com? ⇒ Boolean
Is the host pages.github.com or pages.github.io?.
-
#pointed_to_github_pages_ip? ⇒ Boolean
Is the domain’s first response an A record to a valid GitHub Pages IP?.
-
#proxied? ⇒ Boolean
Does this non-GitHub-pages domain proxy a GitHub Pages site?.
- #served_by_pages? ⇒ Boolean
-
#should_be_a_record? ⇒ Boolean
Should the domain be an apex record?.
- #uri ⇒ Object
-
#valid_domain? ⇒ Boolean
Is this a valid domain that PublicSuffix recognizes? Used as an escape hatch to prevent false positives on DNS checkes.
Methods inherited from Checkable
#reason, #to_hash, #to_json, #to_s, #to_s_pretty, #valid?
Constructor Details
#initialize(host) ⇒ Domain
Returns a new instance of Domain.
27 28 29 30 31 32 33 |
# File 'lib/github-pages-health-check/domain.rb', line 27 def initialize(host) unless host.is_a? String raise ArgumentError, "Expected string, got #{host.class}" end @host = host_from_uri(host) end |
Instance Attribute Details
#host ⇒ Object (readonly)
Returns the value of attribute host.
5 6 7 |
# File 'lib/github-pages-health-check/domain.rb', line 5 def host @host end |
Instance Method Details
#a_record? ⇒ Boolean
Is this domain’s first response an A record?
180 181 182 183 |
# File 'lib/github-pages-health-check/domain.rb', line 180 def a_record? return unless dns? dns.first.class == Net::DNS::RR::A end |
#apex_domain? ⇒ Boolean
Is this domain an apex domain, meaning a CNAME would be innapropriate
74 75 76 77 78 79 80 81 82 |
# File 'lib/github-pages-health-check/domain.rb', line 74 def apex_domain? return @apex_domain if defined?(@apex_domain) answers = Resolv::DNS.open { |dns| dns.getresources(absolute_domain, Resolv::DNS::Resource::IN::NS) } @apex_domain = answers.any? end |
#check! ⇒ Object
Runs all checks, raises an error if invalid
36 37 38 39 40 41 42 43 44 |
# File 'lib/github-pages-health-check/domain.rb', line 36 def check! raise Errors::InvalidDNSError unless dns_resolves? return true if proxied? raise Errors::DeprecatedIPError if deprecated_ip? raise Errors::InvalidARecordError if invalid_a_record? raise Errors::InvalidCNAMEError if invalid_cname? raise Errors::NotServedByPagesError unless served_by_pages? true end |
#cloudflare_ip? ⇒ Boolean
Does the domain resolve to a CloudFlare-owned IP
133 134 135 136 137 138 |
# File 'lib/github-pages-health-check/domain.rb', line 133 def cloudflare_ip? return unless dns? dns.all? do |answer| answer.class == Net::DNS::RR::A && CloudFlare.controls_ip?(answer.address) end end |
#cname ⇒ Object
The domain to which this domain’s CNAME resolves Returns nil if the domain is not a CNAME
194 195 196 197 |
# File 'lib/github-pages-health-check/domain.rb', line 194 def cname return unless cname? @cname ||= Domain.new(dns.first.cname.to_s) end |
#cname_record? ⇒ Boolean Also known as: cname?
Is this domain’s first response a CNAME record?
186 187 188 189 |
# File 'lib/github-pages-health-check/domain.rb', line 186 def cname_record? return unless dns? dns.first.class == Net::DNS::RR::CNAME end |
#cname_to_fastly? ⇒ Boolean
Is the given domain CNAME’d directly to our Fastly account?
108 109 110 |
# File 'lib/github-pages-health-check/domain.rb', line 108 def cname_to_fastly? cname? && !pages_domain? && cname.fastly? end |
#cname_to_github_user_domain? ⇒ Boolean
Is the domain’s first response a CNAME to a pages domain?
95 96 97 |
# File 'lib/github-pages-health-check/domain.rb', line 95 def cname_to_github_user_domain? cname? && !cname_to_pages_dot_github_dot_com? && cname.pages_domain? end |
#cname_to_pages_dot_github_dot_com? ⇒ Boolean
Is the given domain a CNAME to pages.github.(io|com) instead of being CNAME’d to the user’s subdomain?
domain - the domain to check, generaly the target of a cname
103 104 105 |
# File 'lib/github-pages-health-check/domain.rb', line 103 def cname_to_pages_dot_github_dot_com? cname? && cname.pages_dot_github_dot_com? end |
#deprecated_ip? ⇒ Boolean
46 47 48 49 |
# File 'lib/github-pages-health-check/domain.rb', line 46 def deprecated_ip? return @deprecated_ip if defined? @deprecated_ip @deprecated_ip = (a_record? && old_ip_address?) end |
#dns ⇒ Object
Returns an array of DNS answers
155 156 157 158 159 160 161 162 163 164 |
# File 'lib/github-pages-health-check/domain.rb', line 155 def dns return @dns if defined? @dns @dns = Timeout.timeout(TIMEOUT) do GitHubPages::HealthCheck.without_warnings do Net::DNS::Resolver.start(absolute_domain).answer unless host.nil? end end rescue StandardError @dns = nil end |
#dns? ⇒ Boolean Also known as: dns_resolves?
Are we even able to get the DNS record?
167 168 169 |
# File 'lib/github-pages-health-check/domain.rb', line 167 def dns? !(dns.nil? || dns.empty?) end |
#fastly? ⇒ Boolean
Is the host our Fastly CNAME?
128 129 130 |
# File 'lib/github-pages-health-check/domain.rb', line 128 def fastly? !!host.match(/\Agithub\.map\.fastly\.net\.?\z/i) end |
#github_domain? ⇒ Boolean
Is this domain owned by GitHub?
123 124 125 |
# File 'lib/github-pages-health-check/domain.rb', line 123 def github_domain? !!host.match(/\.github\.com\z/) end |
#invalid_a_record? ⇒ Boolean
51 52 53 54 |
# File 'lib/github-pages-health-check/domain.rb', line 51 def invalid_a_record? return @invalid_a_record if defined? @invalid_a_record @invalid_a_record = (valid_domain? && a_record? && !should_be_a_record?) end |
#invalid_cname? ⇒ Boolean
56 57 58 59 60 61 62 63 64 |
# File 'lib/github-pages-health-check/domain.rb', line 56 def invalid_cname? return @invalid_cname if defined? @invalid_cname @invalid_cname = begin return false unless valid_domain? return false if github_domain? || apex_domain? return true if cname_to_pages_dot_github_dot_com? || cname_to_fastly? !cname_to_github_user_domain? end end |
#old_ip_address? ⇒ Boolean
Does this domain have any A record that points to the legacy IPs?
173 174 175 176 177 |
# File 'lib/github-pages-health-check/domain.rb', line 173 def old_ip_address? dns.any? do |answer| answer.class == Net::DNS::RR::A && LEGACY_IP_ADDRESSES.include?(answer.address.to_s) end if dns? end |
#pages_domain? ⇒ Boolean
Is the host a *.github.io domain?
113 114 115 |
# File 'lib/github-pages-health-check/domain.rb', line 113 def pages_domain? !!host.match(/\A[\w-]+\.github\.(io|com)\.?\z/i) end |
#pages_dot_github_dot_com? ⇒ Boolean
Is the host pages.github.com or pages.github.io?
118 119 120 |
# File 'lib/github-pages-health-check/domain.rb', line 118 def pages_dot_github_dot_com? !!host.match(/\Apages\.github\.(io|com)\.?\z/i) end |
#pointed_to_github_pages_ip? ⇒ Boolean
Is the domain’s first response an A record to a valid GitHub Pages IP?
90 91 92 |
# File 'lib/github-pages-health-check/domain.rb', line 90 def pointed_to_github_pages_ip? a_record? && CURRENT_IP_ADDRESSES.include?(dns.first.value) end |
#proxied? ⇒ Boolean
Does this non-GitHub-pages domain proxy a GitHub Pages site?
This can be:
1. A Cloudflare-owned IP address
2. A site that returns GitHub.com server headers, but isn't CNAME'd to a GitHub domain
3. A site that returns GitHub.com server headers, but isn't CNAME'd to a GitHub IP
146 147 148 149 150 151 152 |
# File 'lib/github-pages-health-check/domain.rb', line 146 def proxied? return unless dns? return true if cloudflare_ip? return false if pointed_to_github_pages_ip? || cname_to_github_user_domain? return false if cname_to_pages_dot_github_dot_com? || cname_to_fastly? served_by_pages? end |
#served_by_pages? ⇒ Boolean
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/github-pages-health-check/domain.rb', line 199 def served_by_pages? return @served_by_pages if defined? @served_by_pages @served_by_pages = begin response = Typhoeus.head(uri, TYPHOEUS_OPTIONS) # Workaround for webmock not playing nicely with Typhoeus redirects # See https://github.com/bblimke/webmock/issues/237 if response.mock? && response.headers["Location"] response = Typhoeus.head(response.headers["Location"], TYPHOEUS_OPTIONS) end return false unless response.mock? || response.return_code == :ok return true if response.headers["Server"] == "GitHub.com" # Typhoeus mangles the case of the header, compare insensitively response.headers.any? { |k,v| k =~ /X-GitHub-Request-Id/i } end end |
#should_be_a_record? ⇒ Boolean
Should the domain be an apex record?
85 86 87 |
# File 'lib/github-pages-health-check/domain.rb', line 85 def should_be_a_record? !pages_domain? && apex_domain? end |
#uri ⇒ Object
219 220 221 222 223 224 |
# File 'lib/github-pages-health-check/domain.rb', line 219 def uri @uri ||= begin = { :host => host, :scheme => scheme, :path => "/" } Addressable::URI.new().normalize.to_s end end |
#valid_domain? ⇒ Boolean
Is this a valid domain that PublicSuffix recognizes? Used as an escape hatch to prevent false positives on DNS checkes
68 69 70 71 |
# File 'lib/github-pages-health-check/domain.rb', line 68 def valid_domain? return @valid if defined? @valid @valid = PublicSuffix.valid?(host) end |