Module: Oddb2xml::ProxyCheck

Defined in:
lib/oddb2xml/proxy_check.rb

Overview

Preflight connectivity check. Run once at the very start of a CLI run, it probes every outbound host oddb2xml needs (honouring the http(s)_proxy environment) and prints a loud warning if any host is blocked by the proxy (HTTP 407 on an allow-list proxy such as Aspectra’s Skyhigh gateway) or is otherwise unreachable. It never aborts the run – downloads still proceed and fail individually as before; this just surfaces the cause up front instead of leaving the user to decode a later Errno/empty-output symptom. See issue #121.

Constant Summary collapse

BASE_HOSTS =

host => human-readable description of what breaks when it is unreachable. Hosts only needed for certain options are added conditionally (see #hosts_for).

{
  "files.refdata.ch" => "Refdata articles",
  "www.swissmedic.ch" => "Swissmedic registrations",
  "raw.githubusercontent.com" => "ATC codes (cpp2sqlite)"
}.freeze
TIMEOUT =

seconds, per host (open + read); checks run concurrently

6

Class Method Summary collapse

Class Method Details

.check_host(host, proxy) ⇒ Object

Returns :ok, :blocked (proxy 407) or :unreachable for a single host.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/oddb2xml/proxy_check.rb', line 47

def check_host(host, proxy)
  http =
    if proxy
      Net::HTTP.new(host, 443, proxy.host, proxy.port, proxy.user, proxy.password)
    else
      Net::HTTP.new(host, 443)
    end
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  http.open_timeout = TIMEOUT
  http.read_timeout = TIMEOUT
  http.start do |h|
    res = h.head("/")
    return :blocked if res.code.to_s == "407"
    return :ok # any HTTP answer (200/301/403/404/...) means the host is reachable
  end
rescue => error
  msg = error.message.to_s.downcase
  return :blocked if msg.include?("407") || msg.include?("authenticationrequired") || msg.include?("proxy")
  :unreachable
end

.hosts_for(options = {}) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/oddb2xml/proxy_check.rb', line 37

def hosts_for(options = {})
  hosts = BASE_HOSTS.dup
  hosts["epl.bag.admin.ch"] = "BAG FHIR data (--fhir)" if options[:fhir]
  hosts["id.gs1.ch"] = "GS1 NONPHARMA (--firstbase / -b)" if options[:firstbase]
  hosts["www.spezialitaetenliste.ch"] = "BAG Spezialitätenliste" unless options[:fhir]
  hosts["www.medregbm.admin.ch"] = "Medizinalberuferegister (-x address)" if options[:address]
  hosts
end

.proxy_uriObject



28
29
30
31
32
33
34
35
# File 'lib/oddb2xml/proxy_check.rb', line 28

def proxy_uri
  env = ENV["https_proxy"] || ENV["HTTPS_PROXY"] || ENV["http_proxy"] || ENV["HTTP_PROXY"]
  return nil if env.nil? || env.empty?
  env = "http://#{env}" unless env.start_with?("http")
  URI.parse(env)
rescue URI::InvalidURIError
  nil
end

.run(options = {}) ⇒ Object

Probe all relevant hosts concurrently and warn about any that fail.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/oddb2xml/proxy_check.rb', line 70

def run(options = {})
  return if defined?(RSpec) || defined?(VCR) # never touch the network in tests
  return if ENV["ODDB2XML_SKIP_PROXY_CHECK"]

  proxy = proxy_uri
  hosts = hosts_for(options)
  results = hosts.map do |host, desc|
    Thread.new { [host, desc, check_host(host, proxy)] }
  end.map(&:value)

  problems = results.reject { |(_host, _desc, status)| status == :ok }
  return if problems.empty?

  warn_about(problems, proxy)
end

.warn_about(problems, proxy) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/oddb2xml/proxy_check.rb', line 86

def warn_about(problems, proxy)
  line = "=" * 72
  $stderr.puts line
  $stderr.puts " oddb2xml CONNECTIVITY WARNING"
  $stderr.puts " The following hosts could not be reached -- the corresponding"
  $stderr.puts " downloads will FAIL or produce incomplete data:"
  problems.each do |(host, desc, status)|
    tag = (status == :blocked) ? "BLOCKED by proxy (407)" : "UNREACHABLE          "
    $stderr.puts format("   [%s] %-26s %s", tag, host, desc)
  end
  if proxy
    $stderr.puts ""
    $stderr.puts " Proxy in use: #{proxy.host}:#{proxy.port}"
    if problems.any? { |(_h, _d, s)| s == :blocked }
      $stderr.puts " This looks like an allow-list proxy. Ask your admin to allow the"
      $stderr.puts " hosts above (HTTPS/443), or set credentials in http(s)_proxy."
    end
  end
  $stderr.puts " (Set ODDB2XML_SKIP_PROXY_CHECK=1 to silence this check.)"
  $stderr.puts line
end