From cfa5c6a86c6e56fc194e0c36dedc2e6eb78a852d Mon Sep 17 00:00:00 2001 From: zhouyu Date: Mon, 12 Jan 2026 12:58:45 -0800 Subject: [PATCH 01/15] Add http head check etc. --- config/application.rb | 9 ++++ config/initializers/okcomputer.rb | 73 +++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/config/application.rb b/config/application.rb index b3a084e..182d3bc 100644 --- a/config/application.rb +++ b/config/application.rb @@ -20,6 +20,15 @@ class Application < Rails::Application config.action_mailer.default_options = { from: 'fake@berkeley.edu' } config.lit_gtag_id = ENV.fetch('LIT_GTAG_ID', nil) + config.geoserver_url = ENV.fetch('GEOSERVER_URL', 'https://geoserver-public.ucblib.org/geoserver') + config.spatialserver_url = ENV.fetch('SPATIAL_URL', 'https://spatial.ucblib.org') + + config.x.servers ||= {} + + # config.x.servers[:geoserver] = ENV.fetch('GEOSERVER_URL', nil) + # config.x.servers[:secure_geoserver] = ENV.fetch('GEOSERVER_URL', nil) + # config.x.servers[:spatial_server] = ENV.fetch('SPATIAL_URL', nil) + # The Base URL for the generated sitemap config.x.sitemap.base_url = ENV.fetch('GEODATA_BASE_URL', 'http://localhost:3000') # Silenced by default to minimize log noise diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index 2a41f10..a5061bf 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -11,3 +11,76 @@ # Requires the ping handler on the solr core (/admin/ping). core_baseurl = Blacklight.default_index.connection.uri.to_s.chomp('/') OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl) + +def check_geoserver(server_name) + url = host_url(server_name) + # geoserver_url = url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" + geoserver_url = 'https://geoservices.lib.berkeley.edu/geoserver/UCB/wms?service=WMS&version=1.1.0&request=GetMap&layers=UCB%3Af7b68n&bbox=-122.836485%2C37.808713%2C-122.409565%2C38.190532&width=768&height=686&srs=EPSG%3A4326&styles=&format=format=image/png' + OkComputer::Registry.register clr_name(server_name), HttpHeadCheck.new(geoserver_url) +end + +def check_spatial_server(server_name, type) + message = "#{type} #{clr_name(server_name)}" + url = host_url(server_name) + spatial_url = url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" + OkComputer::Registry.register message, HttpHeadCheck.new(spatial_url) +end + +def host_url(server_name) + Rails.configuration.x.servers[server_name.to_sym] +end + +def clr_name(server_name) + server_name.gsub('_', ' ') +end +# geoserver_url = geoserver_capabilty_url(Rails.application.config.geoserver_url) +# OkComputer::Registry.register 'Check public geoserver', HttpHeadCheck.new(geoserver_url) +# pubilc_download_url = spatial_download_url(Rails.application.config.spatialserver_url) +# OkComputer::Registry.register 'Check public download', HttpHeadCheck.new(pubilc_download_url) +# secure_download_url = spatial_download_url(Rails.application.config.spatialserver_url, 'UCB') +# OkComputer::Registry.register 'Check public download', HttpHeadCheck.new(secure_download_url) + +class HttpHeadCheck < OkComputer::Check + ConnectionFailed = Class.new(StandardError) + attr_accessor :url + + def initialize(url) + self.url = url + end + + def check + return skip_check unless url + + response = perform_http_head_request + if response.is_a?(Net::HTTPOK) + mark_message 'Check succeeded.' + else + mark_failure + mark_message "Error: Http head check endpoint responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." + end + rescue StandardError => e + mark_message "Error: '#{e}'" + mark_failure + end + + private + + def perform_http_head_request + uri = URI(url) + Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', verify_mode: OpenSSL::SSL::VERIFY_PEER) do |http| + http.head(uri.request_uri) + end + rescue StandardError => e + raise ConnectionFailed, e + end + + def skip_check + mark_failure + mark_message 'No URL configured; health check was skipped...' + end +end + +check_geoserver 'geoserver' +# check_geoserver 'secure_geoserver' +# check_spatial_server 'spatial_server', 'public' +# check_spatial_server 'spatial_server', 'UCB' From b8fed475d7238ee984c03c41d86391794cc16543 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Wed, 14 Jan 2026 13:37:29 -0800 Subject: [PATCH 02/15] consolidated --- config/application.rb | 6 +++ config/initializers/okcomputer.rb | 81 ++++--------------------------- lib/http_client.rb | 41 ++++++++++++++++ lib/http_head_check.rb | 37 ++++++++++++++ lib/server_check.rb | 24 +++++++++ spec/requests/okcomputer_spec.rb | 4 ++ 6 files changed, 122 insertions(+), 71 deletions(-) create mode 100644 lib/http_client.rb create mode 100644 lib/http_head_check.rb create mode 100644 lib/server_check.rb diff --git a/config/application.rb b/config/application.rb index 182d3bc..7146672 100644 --- a/config/application.rb +++ b/config/application.rb @@ -25,6 +25,12 @@ class Application < Rails::Application config.x.servers ||= {} + # These will be removed before merging code + config.x.servers[:geoserver] = ENV.fetch('GEOSERVER_URL', 'https://geoserver-public.ucblib.org/geoserver') + config.x.servers[:secure_geoserver] = ENV.fetch('GEOSERVER_URL', 'https://geoserver-secure.ucblib.org/geoserver') + config.x.servers[:spatial_server] = ENV.fetch('SPATIAL_URL', 'https://spatial.ucblib.org') + + # These comments will be removed before merging code # config.x.servers[:geoserver] = ENV.fetch('GEOSERVER_URL', nil) # config.x.servers[:secure_geoserver] = ENV.fetch('GEOSERVER_URL', nil) # config.x.servers[:spatial_server] = ENV.fetch('SPATIAL_URL', nil) diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index a5061bf..8b1726b 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -1,5 +1,8 @@ # initializers/okcomputer.rb # Health checks configuration +require_relative '../../lib/http_client' +require_relative '../../lib/http_head_check' +require_relative '../../lib/server_check' OkComputer.logger = Rails.logger OkComputer.check_in_parallel = true @@ -12,75 +15,11 @@ core_baseurl = Blacklight.default_index.connection.uri.to_s.chomp('/') OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl) -def check_geoserver(server_name) - url = host_url(server_name) - # geoserver_url = url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" - geoserver_url = 'https://geoservices.lib.berkeley.edu/geoserver/UCB/wms?service=WMS&version=1.1.0&request=GetMap&layers=UCB%3Af7b68n&bbox=-122.836485%2C37.808713%2C-122.409565%2C38.190532&width=768&height=686&srs=EPSG%3A4326&styles=&format=format=image/png' - OkComputer::Registry.register clr_name(server_name), HttpHeadCheck.new(geoserver_url) -end +SERVER_NAME_GEOSERVER = 'geoserver'.freeze +SERVER_NAME_SECUREGEOSERVER = 'secure_geoserver'.freeze +SERVER_NAME_SPATIAL = 'spatial_server'.freeze -def check_spatial_server(server_name, type) - message = "#{type} #{clr_name(server_name)}" - url = host_url(server_name) - spatial_url = url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" - OkComputer::Registry.register message, HttpHeadCheck.new(spatial_url) -end - -def host_url(server_name) - Rails.configuration.x.servers[server_name.to_sym] -end - -def clr_name(server_name) - server_name.gsub('_', ' ') -end -# geoserver_url = geoserver_capabilty_url(Rails.application.config.geoserver_url) -# OkComputer::Registry.register 'Check public geoserver', HttpHeadCheck.new(geoserver_url) -# pubilc_download_url = spatial_download_url(Rails.application.config.spatialserver_url) -# OkComputer::Registry.register 'Check public download', HttpHeadCheck.new(pubilc_download_url) -# secure_download_url = spatial_download_url(Rails.application.config.spatialserver_url, 'UCB') -# OkComputer::Registry.register 'Check public download', HttpHeadCheck.new(secure_download_url) - -class HttpHeadCheck < OkComputer::Check - ConnectionFailed = Class.new(StandardError) - attr_accessor :url - - def initialize(url) - self.url = url - end - - def check - return skip_check unless url - - response = perform_http_head_request - if response.is_a?(Net::HTTPOK) - mark_message 'Check succeeded.' - else - mark_failure - mark_message "Error: Http head check endpoint responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." - end - rescue StandardError => e - mark_message "Error: '#{e}'" - mark_failure - end - - private - - def perform_http_head_request - uri = URI(url) - Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', verify_mode: OpenSSL::SSL::VERIFY_PEER) do |http| - http.head(uri.request_uri) - end - rescue StandardError => e - raise ConnectionFailed, e - end - - def skip_check - mark_failure - mark_message 'No URL configured; health check was skipped...' - end -end - -check_geoserver 'geoserver' -# check_geoserver 'secure_geoserver' -# check_spatial_server 'spatial_server', 'public' -# check_spatial_server 'spatial_server', 'UCB' +ServerCheck.geoserver SERVER_NAME_GEOSERVER +ServerCheck.geoserver SERVER_NAME_SECUREGEOSERVER +ServerCheck.spatial_server SERVER_NAME_SPATIAL, 'public' +ServerCheck.spatial_server SERVER_NAME_SPATIAL, 'UCB' diff --git a/lib/http_client.rb b/lib/http_client.rb new file mode 100644 index 0000000..e909766 --- /dev/null +++ b/lib/http_client.rb @@ -0,0 +1,41 @@ +require 'net/http' +require 'uri' +require 'openssl' + +module GeoDataHealthCheck + class HttpClient + ConnectionFailed = Class.new(StandardError) + + class << self + def request(method, url, timeout: 5) + uri = URI(url) + + Net::HTTP.start( + uri.host, + uri.port, + use_ssl: uri.scheme == 'https', + verify_mode: OpenSSL::SSL::VERIFY_PEER, + open_timeout: timeout, + read_timeout: timeout # or just skip checking reading timeout? + ) do |http| + req = build_request(method, uri) + http.request(req) + end + rescue Net::OpenTimeout, Net::ReadTimeout => e + msg = "Http #{method} #{url} did not respond within #{request_timeout} seconds: " + raise ConnectionFailed, msg + e.message + rescue StandardError => e + raise ConnectionFailed, e.message + end + + def build_request(method, uri) + req_method = method.downcase.to_sym + raise ConnectionFailed, "Incorrect http request method: #{method}" unless %i[head get].include?(req_method) + + req_klass = method == :head ? Net::HTTP::Head : Net::HTTP::Get + req_klass.new(uri) + end + end + + end +end diff --git a/lib/http_head_check.rb b/lib/http_head_check.rb new file mode 100644 index 0000000..7c30e2e --- /dev/null +++ b/lib/http_head_check.rb @@ -0,0 +1,37 @@ +module GeoDataHealthCheck + class HttpHeadCheck < OkComputer::Check + attr_accessor :url, :request_timeout + + def initialize(url, request_timeout = 5) + self.url = url + self.request_timeout = request_timeout + end + + def check + return skip_check unless url + + response = HttpClient.request( + :head, + url, + timeout: request_timeout + ) + # sleep 14 + if response.is_a?(Net::HTTPOK) || response.is_a?(Net::HTTPRedirection) + mark_message 'Check succeeded.' + else + mark_failure + mark_message "Error: Http head check endpoint responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." + end + rescue StandardError => e + mark_message "Error: '#{e}'" + mark_failure + end + + private + + def skip_check + mark_failure + mark_message 'No URL configured; health check was skipped...' + end + end +end diff --git a/lib/server_check.rb b/lib/server_check.rb new file mode 100644 index 0000000..2b01b9a --- /dev/null +++ b/lib/server_check.rb @@ -0,0 +1,24 @@ +class ServerCheck + class << self + def geoserver(server_name) + url = host_url(server_name) + geoserver_url = url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" + OkComputer::Registry.register clr_msg(server_name), GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url) + end + + def spatial_server(server_name, type) + msg = "#{type} #{server_name}" + url = host_url(server_name) + spatial_url = url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" + OkComputer::Registry.register clr_msg(msg), GeoDataHealthCheck::HttpHeadCheck.new(spatial_url) + end + + def host_url(server_name) + Rails.configuration.x.servers[server_name.to_sym] + end + + def clr_msg(msg) + msg.downcase.strip.gsub(/\s+/, '_') + end + end +end diff --git a/spec/requests/okcomputer_spec.rb b/spec/requests/okcomputer_spec.rb index a04d1c8..039d7cb 100644 --- a/spec/requests/okcomputer_spec.rb +++ b/spec/requests/okcomputer_spec.rb @@ -14,6 +14,10 @@ database database-migrations solr + geoserver + secure_geoserver + public_spatial_server + ucb_spatial_server ] end end From 5c6fbc07b5ced796cf759daf16d663a560f1bf3d Mon Sep 17 00:00:00 2001 From: zhouyu Date: Wed, 14 Jan 2026 14:48:34 -0800 Subject: [PATCH 03/15] uncheck Lint/MissingSuper rule --- lib/http_head_check.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/http_head_check.rb b/lib/http_head_check.rb index 7c30e2e..7a20d2f 100644 --- a/lib/http_head_check.rb +++ b/lib/http_head_check.rb @@ -2,10 +2,12 @@ module GeoDataHealthCheck class HttpHeadCheck < OkComputer::Check attr_accessor :url, :request_timeout + # rubocop:disable Lint/MissingSuper def initialize(url, request_timeout = 5) self.url = url self.request_timeout = request_timeout end + # rubocop:enable Lint/MissingSuper def check return skip_check unless url From abc3ad67c09b28c4b85526436d989a089c7868ae Mon Sep 17 00:00:00 2001 From: zhouyu Date: Wed, 14 Jan 2026 15:46:21 -0800 Subject: [PATCH 04/15] code formating --- config/application.rb | 3 --- config/initializers/okcomputer.rb | 15 ++++++--------- lib/{server_check.rb => check_server.rb} | 21 ++++++++++++++++----- 3 files changed, 22 insertions(+), 17 deletions(-) rename lib/{server_check.rb => check_server.rb} (51%) diff --git a/config/application.rb b/config/application.rb index 7146672..116b8cd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -20,9 +20,6 @@ class Application < Rails::Application config.action_mailer.default_options = { from: 'fake@berkeley.edu' } config.lit_gtag_id = ENV.fetch('LIT_GTAG_ID', nil) - config.geoserver_url = ENV.fetch('GEOSERVER_URL', 'https://geoserver-public.ucblib.org/geoserver') - config.spatialserver_url = ENV.fetch('SPATIAL_URL', 'https://spatial.ucblib.org') - config.x.servers ||= {} # These will be removed before merging code diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index 8b1726b..8a79d60 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -2,7 +2,7 @@ # Health checks configuration require_relative '../../lib/http_client' require_relative '../../lib/http_head_check' -require_relative '../../lib/server_check' +require_relative '../../lib/check_server' OkComputer.logger = Rails.logger OkComputer.check_in_parallel = true @@ -15,11 +15,8 @@ core_baseurl = Blacklight.default_index.connection.uri.to_s.chomp('/') OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl) -SERVER_NAME_GEOSERVER = 'geoserver'.freeze -SERVER_NAME_SECUREGEOSERVER = 'secure_geoserver'.freeze -SERVER_NAME_SPATIAL = 'spatial_server'.freeze - -ServerCheck.geoserver SERVER_NAME_GEOSERVER -ServerCheck.geoserver SERVER_NAME_SECUREGEOSERVER -ServerCheck.spatial_server SERVER_NAME_SPATIAL, 'public' -ServerCheck.spatial_server SERVER_NAME_SPATIAL, 'UCB' +# Check geoservers and spatial servers +CheckServer.geoserver 'public' +CheckServer.geoserver 'UCB' +CheckServer.spatial_server 'public' +CheckServer.spatial_server 'UCB' diff --git a/lib/server_check.rb b/lib/check_server.rb similarity index 51% rename from lib/server_check.rb rename to lib/check_server.rb index 2b01b9a..9479331 100644 --- a/lib/server_check.rb +++ b/lib/check_server.rb @@ -1,14 +1,21 @@ -class ServerCheck +class CheckServer + GEOSERVER_NAME = 'geoserver'.freeze + SECURE_GEOSERVER_NAME = 'secure_geoserver'.freeze + SPATIAL_SERVER_NAME = 'spatial_server'.freeze + class << self - def geoserver(server_name) + def geoserver(type) + check_type(type) + server_name = type == 'public' ? GEOSERVER_NAME : SECURE_GEOSERVER_NAME url = host_url(server_name) geoserver_url = url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" OkComputer::Registry.register clr_msg(server_name), GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url) end - def spatial_server(server_name, type) - msg = "#{type} #{server_name}" - url = host_url(server_name) + def spatial_server(type) + check_type(type) + msg = "#{type} #{SPATIAL_SERVER_NAME}" + url = host_url(SPATIAL_SERVER_NAME) spatial_url = url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" OkComputer::Registry.register clr_msg(msg), GeoDataHealthCheck::HttpHeadCheck.new(spatial_url) end @@ -20,5 +27,9 @@ def host_url(server_name) def clr_msg(msg) msg.downcase.strip.gsub(/\s+/, '_') end + + def check_type(type) + raise StandardError, "Incorrect server type #{type}, expect either 'public' or 'UCB'" unless %w[public UCB].include? type + end end end From b3fb91efec628ce65c2423b0b4177ad00dbc7770 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Wed, 14 Jan 2026 16:16:27 -0800 Subject: [PATCH 05/15] Handling incorrect server type --- lib/check_server.rb | 11 +++++++---- lib/http_head_check.rb | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/check_server.rb b/lib/check_server.rb index 9479331..1aaa634 100644 --- a/lib/check_server.rb +++ b/lib/check_server.rb @@ -5,7 +5,8 @@ class CheckServer class << self def geoserver(type) - check_type(type) + return wrong_type(type) unless %w[public UCB].include? type + server_name = type == 'public' ? GEOSERVER_NAME : SECURE_GEOSERVER_NAME url = host_url(server_name) geoserver_url = url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" @@ -13,7 +14,8 @@ def geoserver(type) end def spatial_server(type) - check_type(type) + return wrong_type(type) unless %w[public UCB].include? type + msg = "#{type} #{SPATIAL_SERVER_NAME}" url = host_url(SPATIAL_SERVER_NAME) spatial_url = url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" @@ -28,8 +30,9 @@ def clr_msg(msg) msg.downcase.strip.gsub(/\s+/, '_') end - def check_type(type) - raise StandardError, "Incorrect server type #{type}, expect either 'public' or 'UCB'" unless %w[public UCB].include? type + def wrong_type(type) + msg = "Incorrect Geoserver or Spatial server type '#{type}', expect either 'public' or 'UCB" + OkComputer::Registry.register msg, GeoDataHealthCheck::HttpHeadCheck.new(' ') end end end diff --git a/lib/http_head_check.rb b/lib/http_head_check.rb index 7a20d2f..c88b18d 100644 --- a/lib/http_head_check.rb +++ b/lib/http_head_check.rb @@ -10,7 +10,7 @@ def initialize(url, request_timeout = 5) # rubocop:enable Lint/MissingSuper def check - return skip_check unless url + return skip_check if url.strip.empty? response = HttpClient.request( :head, From b47424290579036adce061a9335370c5712085a4 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Thu, 15 Jan 2026 07:57:50 -0800 Subject: [PATCH 06/15] change url check --- lib/http_head_check.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http_head_check.rb b/lib/http_head_check.rb index c88b18d..468d99b 100644 --- a/lib/http_head_check.rb +++ b/lib/http_head_check.rb @@ -10,7 +10,7 @@ def initialize(url, request_timeout = 5) # rubocop:enable Lint/MissingSuper def check - return skip_check if url.strip.empty? + return skip_check if url.blank? response = HttpClient.request( :head, From 36a1dfc95b8793f86ede380319b2fce5557bdb86 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Fri, 16 Jan 2026 14:19:18 -0800 Subject: [PATCH 07/15] Refactor to follow the same registry call style in okcomputer.rb --- config/initializers/okcomputer.rb | 24 +++++++++++----- lib/check_server.rb | 38 ------------------------- lib/endpoint_url.rb | 13 +++++++++ lib/http_client.rb | 41 --------------------------- lib/http_head_check.rb | 46 +++++++++++++++++-------------- 5 files changed, 55 insertions(+), 107 deletions(-) delete mode 100644 lib/check_server.rb create mode 100644 lib/endpoint_url.rb delete mode 100644 lib/http_client.rb diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index 8a79d60..7ab660a 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -1,8 +1,8 @@ # initializers/okcomputer.rb # Health checks configuration -require_relative '../../lib/http_client' + require_relative '../../lib/http_head_check' -require_relative '../../lib/check_server' +require_relative '../../lib/endpoint_url' OkComputer.logger = Rails.logger OkComputer.check_in_parallel = true @@ -15,8 +15,18 @@ core_baseurl = Blacklight.default_index.connection.uri.to_s.chomp('/') OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl) -# Check geoservers and spatial servers -CheckServer.geoserver 'public' -CheckServer.geoserver 'UCB' -CheckServer.spatial_server 'public' -CheckServer.spatial_server 'UCB' +# Perform a Head request to check geoserver endpoint +geoserver_url = EndpointUrl.geoserver(:geoserver) +OkComputer::Registry.register 'geoserver', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url) + +# Perform a Head request to check secure_geoserver endpoint +secure_geoserver_url = EndpointUrl.geoserver(:secure_geoserver) +OkComputer::Registry.register 'secure_geoserver', GeoDataHealthCheck::HttpHeadCheck.new(secure_geoserver_url) + +# Perform a Head request to check spatial server endpoint +spatial_server_url = EndpointUrl.spatial_server(:spatial_server, 'public') +OkComputer::Registry.register 'public_spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(spatial_server_url) + +# Perform a Head request to check UCB spatial server endpoint +ucb_spatial_server_url = EndpointUrl.spatial_server(:spatial_server, 'UCB') +OkComputer::Registry.register 'ucb_spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(ucb_spatial_server_url) diff --git a/lib/check_server.rb b/lib/check_server.rb deleted file mode 100644 index 1aaa634..0000000 --- a/lib/check_server.rb +++ /dev/null @@ -1,38 +0,0 @@ -class CheckServer - GEOSERVER_NAME = 'geoserver'.freeze - SECURE_GEOSERVER_NAME = 'secure_geoserver'.freeze - SPATIAL_SERVER_NAME = 'spatial_server'.freeze - - class << self - def geoserver(type) - return wrong_type(type) unless %w[public UCB].include? type - - server_name = type == 'public' ? GEOSERVER_NAME : SECURE_GEOSERVER_NAME - url = host_url(server_name) - geoserver_url = url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" - OkComputer::Registry.register clr_msg(server_name), GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url) - end - - def spatial_server(type) - return wrong_type(type) unless %w[public UCB].include? type - - msg = "#{type} #{SPATIAL_SERVER_NAME}" - url = host_url(SPATIAL_SERVER_NAME) - spatial_url = url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" - OkComputer::Registry.register clr_msg(msg), GeoDataHealthCheck::HttpHeadCheck.new(spatial_url) - end - - def host_url(server_name) - Rails.configuration.x.servers[server_name.to_sym] - end - - def clr_msg(msg) - msg.downcase.strip.gsub(/\s+/, '_') - end - - def wrong_type(type) - msg = "Incorrect Geoserver or Spatial server type '#{type}', expect either 'public' or 'UCB" - OkComputer::Registry.register msg, GeoDataHealthCheck::HttpHeadCheck.new(' ') - end - end -end diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb new file mode 100644 index 0000000..a98dea1 --- /dev/null +++ b/lib/endpoint_url.rb @@ -0,0 +1,13 @@ +class EndpointUrl + class << self + def geoserver(server_name) + url = Rails.configuration.x.servers[server_name] + url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" + end + + def spatial_server(server_name, type) + url = Rails.configuration.x.servers[server_name] + url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" + end + end +end diff --git a/lib/http_client.rb b/lib/http_client.rb deleted file mode 100644 index e909766..0000000 --- a/lib/http_client.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'net/http' -require 'uri' -require 'openssl' - -module GeoDataHealthCheck - class HttpClient - ConnectionFailed = Class.new(StandardError) - - class << self - def request(method, url, timeout: 5) - uri = URI(url) - - Net::HTTP.start( - uri.host, - uri.port, - use_ssl: uri.scheme == 'https', - verify_mode: OpenSSL::SSL::VERIFY_PEER, - open_timeout: timeout, - read_timeout: timeout # or just skip checking reading timeout? - ) do |http| - req = build_request(method, uri) - http.request(req) - end - rescue Net::OpenTimeout, Net::ReadTimeout => e - msg = "Http #{method} #{url} did not respond within #{request_timeout} seconds: " - raise ConnectionFailed, msg + e.message - rescue StandardError => e - raise ConnectionFailed, e.message - end - - def build_request(method, uri) - req_method = method.downcase.to_sym - raise ConnectionFailed, "Incorrect http request method: #{method}" unless %i[head get].include?(req_method) - - req_klass = method == :head ? Net::HTTP::Head : Net::HTTP::Get - req_klass.new(uri) - end - end - - end -end diff --git a/lib/http_head_check.rb b/lib/http_head_check.rb index 468d99b..0f0995a 100644 --- a/lib/http_head_check.rb +++ b/lib/http_head_check.rb @@ -1,39 +1,43 @@ module GeoDataHealthCheck - class HttpHeadCheck < OkComputer::Check - attr_accessor :url, :request_timeout - - # rubocop:disable Lint/MissingSuper - def initialize(url, request_timeout = 5) - self.url = url - self.request_timeout = request_timeout - end - # rubocop:enable Lint/MissingSuper + class HttpHeadCheck < OkComputer::HttpCheck def check - return skip_check if url.blank? + response = perform_request - response = HttpClient.request( - :head, - url, - timeout: request_timeout - ) - # sleep 14 if response.is_a?(Net::HTTPOK) || response.is_a?(Net::HTTPRedirection) - mark_message 'Check succeeded.' + mark_message 'Http head check successful.' else mark_failure - mark_message "Error: Http head check endpoint responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." + mark_message "Error: '#{url.request_uri}' http head check responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." end rescue StandardError => e mark_message "Error: '#{e}'" mark_failure end + def perform_request + head_request + rescue Net::OpenTimeout, Net::ReadTimeout => e + msg = "#{url.request_uri} did not respond within #{request_timeout} seconds: " + raise ConnectionFailed, msg + e.message + rescue StandardError => e + raise ConnectionFailed, e.message + end + private - def skip_check - mark_failure - mark_message 'No URL configured; health check was skipped...' + def head_request + Net::HTTP.start( + url.host, + url.port, + use_ssl: url.scheme == 'https', + verify_mode: OpenSSL::SSL::VERIFY_PEER, + open_timeout: request_timeout, + read_timeout: request_timeout + ) do |http| + http.head(url.request_uri) + end end + end end From bb8d737846b0a47a87ca9576c8ff39db07595275 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Fri, 16 Jan 2026 15:25:13 -0800 Subject: [PATCH 08/15] Remove spatial server ucb endpoint check --- config/initializers/okcomputer.rb | 8 ++------ lib/endpoint_url.rb | 4 ++-- spec/requests/okcomputer_spec.rb | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index 7ab660a..12c3d77 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -24,9 +24,5 @@ OkComputer::Registry.register 'secure_geoserver', GeoDataHealthCheck::HttpHeadCheck.new(secure_geoserver_url) # Perform a Head request to check spatial server endpoint -spatial_server_url = EndpointUrl.spatial_server(:spatial_server, 'public') -OkComputer::Registry.register 'public_spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(spatial_server_url) - -# Perform a Head request to check UCB spatial server endpoint -ucb_spatial_server_url = EndpointUrl.spatial_server(:spatial_server, 'UCB') -OkComputer::Registry.register 'ucb_spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(ucb_spatial_server_url) +spatial_server_url = EndpointUrl.spatial_server(:spatial_server) +OkComputer::Registry.register 'spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(spatial_server_url) diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb index a98dea1..e3771a7 100644 --- a/lib/endpoint_url.rb +++ b/lib/endpoint_url.rb @@ -5,9 +5,9 @@ def geoserver(server_name) url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" end - def spatial_server(server_name, type) + def spatial_server(server_name) url = Rails.configuration.x.servers[server_name] - url && "#{url.chomp('/')}/#{type}/berkeley-status/data.zip" + url && "#{url.chomp('/')}/public/berkeley-status/data.zip" end end end diff --git a/spec/requests/okcomputer_spec.rb b/spec/requests/okcomputer_spec.rb index 039d7cb..0f98aa5 100644 --- a/spec/requests/okcomputer_spec.rb +++ b/spec/requests/okcomputer_spec.rb @@ -16,8 +16,7 @@ solr geoserver secure_geoserver - public_spatial_server - ucb_spatial_server + spatial_server ] end end From c0b86788e0ff09f901bb1c23fde718ad3d92c79e Mon Sep 17 00:00:00 2001 From: zhouyu Date: Tue, 20 Jan 2026 16:45:17 -0800 Subject: [PATCH 09/15] Add rspec tests for endpoint http head checks --- lib/endpoint_url.rb | 4 +- spec/lib/endpoint_url_spec.rb | 53 +++++++++++++++++++++ spec/lib/http_head_check_spec.rb | 81 ++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 spec/lib/endpoint_url_spec.rb create mode 100644 spec/lib/http_head_check_spec.rb diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb index e3771a7..c5980f5 100644 --- a/lib/endpoint_url.rb +++ b/lib/endpoint_url.rb @@ -2,12 +2,12 @@ class EndpointUrl class << self def geoserver(server_name) url = Rails.configuration.x.servers[server_name] - url && "#{url.chomp('/')}/wms?service=WMS&request=GetCapabilities" + url && "#{url.sub(%r{/+\z}, '')}/wms?service=WMS&request=GetCapabilities" end def spatial_server(server_name) url = Rails.configuration.x.servers[server_name] - url && "#{url.chomp('/')}/public/berkeley-status/data.zip" + url && "#{url.sub(%r{/+\z}, '')}/public/berkeley-status/data.zip" end end end diff --git a/spec/lib/endpoint_url_spec.rb b/spec/lib/endpoint_url_spec.rb new file mode 100644 index 0000000..fae834e --- /dev/null +++ b/spec/lib/endpoint_url_spec.rb @@ -0,0 +1,53 @@ +require 'rails_helper' + +describe EndpointUrl do + describe '.geoserver' do + context 'when server is configured' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('https://example.com//') + end + + it 'returns WMS endpoint URL' do + result = EndpointUrl.geoserver('test_server') + expect(result).to eq('https://example.com/wms?service=WMS&request=GetCapabilities') + end + + end + + context 'when server is not configured' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('missing_server').and_return(nil) + end + + it 'returns nil' do + result = EndpointUrl.geoserver('missing_server') + expect(result).to be_nil + end + end + end + + describe '.spatial_server' do + context 'when server is configured' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('https://example.com//') + end + + it 'returns spatial server data zip endpoint URL' do + result = EndpointUrl.spatial_server('test_server') + expect(result).to eq('https://example.com/public/berkeley-status/data.zip') + end + + end + + context 'when server is not configured' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('missing_server').and_return(nil) + end + + it 'returns nil' do + result = EndpointUrl.spatial_server('missing_server') + expect(result).to be_nil + end + end + end +end diff --git a/spec/lib/http_head_check_spec.rb b/spec/lib/http_head_check_spec.rb new file mode 100644 index 0000000..ef10e86 --- /dev/null +++ b/spec/lib/http_head_check_spec.rb @@ -0,0 +1,81 @@ +require 'spec_helper' +require_relative '../../lib/http_head_check' + +RSpec.describe GeoDataHealthCheck::HttpHeadCheck do + let(:test_url) { URI('http://example.com/endpoint') } + let(:check) { described_class.new(test_url) } + + describe '#check' do + it 'succeeds when response is 200 OK' do + response = Net::HTTPOK.new('1.1', '200', 'OK') + allow(check).to receive(:perform_request).and_return(response) + + check.check + + expect(check.message).to include('Http head check successful.') + end + + it 'succeeds when response is a redirect' do + response = Net::HTTPFound.new('1.1', '302', 'Found') + allow(check).to receive(:perform_request).and_return(response) + + check.check + + expect(check.message).to include('Http head check successful.') + end + + it 'fails when response is 404' do + response = Net::HTTPNotFound.new('1.1', '404', 'Not Found') + allow(check).to receive(:perform_request).and_return(response) + + check.check + + expect(check.message).to include('http head check responded, but returned unexpeced HTTP status: 404 Net::HTTPNotFound') + end + + it 'fails when request raises an error' do + error = StandardError.new('Connection error') + allow(check).to receive(:perform_request).and_raise(error) + + check.check + + expect(check.message).to include('Error:') + expect(check.message).to include('Connection error') + end + end + + describe '#perform_request' do + it 'calls head_request' do + response = Net::HTTPOK.new('1.1', '200', 'OK') + allow(check).to receive(:head_request).and_return(response) + + result = check.perform_request + + expect(result).to eq response + end + + it 'raises ConnectionFailed on OpenTimeout' do + allow(check).to receive(:head_request).and_raise(Net::OpenTimeout.new) + + expect do + check.perform_request + end.to raise_error(OkComputer::HttpCheck::ConnectionFailed) + end + + it 'raises ConnectionFailed on ReadTimeout' do + allow(check).to receive(:head_request).and_raise(Net::ReadTimeout.new) + + expect do + check.perform_request + end.to raise_error(OkComputer::HttpCheck::ConnectionFailed) + end + + it 'raises ConnectionFailed on StandardError' do + allow(check).to receive(:head_request).and_raise(StandardError.new) + + expect do + check.perform_request + end.to raise_error(OkComputer::HttpCheck::ConnectionFailed) + end + end +end From 71904bacdbc64f7051f1d31aefa8a52a88d28ac1 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Thu, 22 Jan 2026 17:26:11 -0800 Subject: [PATCH 10/15] HttpHeadCheck with blank url --- config/application.rb | 12 ++--- config/initializers/okcomputer.rb | 20 ++++---- lib/endpoint_url.rb | 27 ++++++++-- lib/http_head_check_new.rb | 60 ++++++++++++++++++++++ spec/lib/endpoint_url_spec.rb | 83 +++++++++++++++++++++++++++++-- spec/requests/okcomputer_spec.rb | 3 -- 6 files changed, 175 insertions(+), 30 deletions(-) create mode 100644 lib/http_head_check_new.rb diff --git a/config/application.rb b/config/application.rb index 116b8cd..bdebd5f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -22,15 +22,9 @@ class Application < Rails::Application config.x.servers ||= {} - # These will be removed before merging code - config.x.servers[:geoserver] = ENV.fetch('GEOSERVER_URL', 'https://geoserver-public.ucblib.org/geoserver') - config.x.servers[:secure_geoserver] = ENV.fetch('GEOSERVER_URL', 'https://geoserver-secure.ucblib.org/geoserver') - config.x.servers[:spatial_server] = ENV.fetch('SPATIAL_URL', 'https://spatial.ucblib.org') - - # These comments will be removed before merging code - # config.x.servers[:geoserver] = ENV.fetch('GEOSERVER_URL', nil) - # config.x.servers[:secure_geoserver] = ENV.fetch('GEOSERVER_URL', nil) - # config.x.servers[:spatial_server] = ENV.fetch('SPATIAL_URL', nil) + config.x.servers[:geoserver] = ENV.fetch('GEOSERVER_URL_FILE', nil) + config.x.servers[:geoserver_secure] = ENV.fetch('GEOSERVER_SECURE_URL_FILE', nil) + config.x.servers[:spatial_server] = ENV.fetch('SPATIAL_URL', nil) # The Base URL for the generated sitemap config.x.sitemap.base_url = ENV.fetch('GEODATA_BASE_URL', 'http://localhost:3000') diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index 12c3d77..7fdf6f0 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -1,7 +1,7 @@ # initializers/okcomputer.rb # Health checks configuration -require_relative '../../lib/http_head_check' +require_relative '../../lib/http_head_check_new' require_relative '../../lib/endpoint_url' OkComputer.logger = Rails.logger @@ -15,14 +15,14 @@ core_baseurl = Blacklight.default_index.connection.uri.to_s.chomp('/') OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl) -# Perform a Head request to check geoserver endpoint -geoserver_url = EndpointUrl.geoserver(:geoserver) -OkComputer::Registry.register 'geoserver', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url) +# # Perform a Head request to check geoserver endpoint +# geoserver_url = EndpointUrl.geoserver(:geoserver) +# OkComputer::Registry.register 'geoserver', GeoDataHealthCheck::HttpHeadCheckNew.new(geoserver_url) -# Perform a Head request to check secure_geoserver endpoint -secure_geoserver_url = EndpointUrl.geoserver(:secure_geoserver) -OkComputer::Registry.register 'secure_geoserver', GeoDataHealthCheck::HttpHeadCheck.new(secure_geoserver_url) +# # Perform a Head request to check secure_geoserver endpoint +# secure_geoserver_url = EndpointUrl.geoserver(:geoserver_secure) +# OkComputer::Registry.register 'geoserver_secure', GeoDataHealthCheck::HttpHeadCheckNew.new(secure_geoserver_url) -# Perform a Head request to check spatial server endpoint -spatial_server_url = EndpointUrl.spatial_server(:spatial_server) -OkComputer::Registry.register 'spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(spatial_server_url) +# # Perform a Head request to check spatial server endpoint +# spatial_server_url = EndpointUrl.spatial_server(:spatial_server) +# OkComputer::Registry.register 'spatial_server', GeoDataHealthCheck::HttpHeadCheckNew.new(spatial_server_url) diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb index c5980f5..12ddfe1 100644 --- a/lib/endpoint_url.rb +++ b/lib/endpoint_url.rb @@ -1,13 +1,34 @@ +require 'uri' class EndpointUrl class << self def geoserver(server_name) - url = Rails.configuration.x.servers[server_name] - url && "#{url.sub(%r{/+\z}, '')}/wms?service=WMS&request=GetCapabilities" + url = get_url(server_name) + url && "#{url}/wms?service=WMS&request=GetCapabilities" end def spatial_server(server_name) url = Rails.configuration.x.servers[server_name] - url && "#{url.sub(%r{/+\z}, '')}/public/berkeley-status/data.zip" + url && "#{url}/public/berkeley-status/data.zip" + end + + def get_url(server_name) + secret_file = Rails.configuration.x.servers[server_name] + return if secret_file.nil? + + url = File.read(secret_file).chomp + safe_url(url) + rescue Errno::ENOENT, Errno::EACCES => e + Rails.logger.error "Failed to read GEOSERVER_URL_FILE from #{secret_file}: #{e.message}" + nil + end + + def safe_url(url) + return if url.nil? + + uri = URI(url) + uri.user = nil + uri.password = nil + uri.to_s.sub(%r{/rest/?$}, '') end end end diff --git a/lib/http_head_check_new.rb b/lib/http_head_check_new.rb new file mode 100644 index 0000000..6277c3e --- /dev/null +++ b/lib/http_head_check_new.rb @@ -0,0 +1,60 @@ +module GeoDataHealthCheck + class HttpHeadCheckNew < OkComputer::Check + ConnectionFailed = Class.new(StandardError) + attr_accessor :url, :request_timeout + + # rubocop:disable Lint/MissingSuper + def initialize(url, request_timeout = 5) + self.url = url + self.request_timeout = request_timeout + end + # rubocop:enable Lint/MissingSuper + + def check + return skip_check if url.blank? + + response = perform_request + + if response.is_a?(Net::HTTPOK) || response.is_a?(Net::HTTPRedirection) + mark_message 'Http head check successful.' + else + mark_failure + mark_message "Error: '#{url}' http head check responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." + end + rescue StandardError => e + mark_message "Error: '#{e}'" + mark_failure + end + + def perform_request + head_request + rescue Net::OpenTimeout, Net::ReadTimeout => e + msg = "#{url} did not respond within #{request_timeout} seconds: " + raise ConnectionFailed, msg + e.message + rescue StandardError => e + raise ConnectionFailed, e.message + end + + private + + def skip_check + mark_failure + mark_message 'No URL configured; health check was skipped...' + end + + def head_request + uri = URI(url) + Net::HTTP.start( + uri.host, + uri.port, + use_ssl: uri.scheme == 'https', + verify_mode: OpenSSL::SSL::VERIFY_PEER, + open_timeout: request_timeout, + read_timeout: request_timeout + ) do |http| + http.head(uri.request_uri) + end + end + + end +end diff --git a/spec/lib/endpoint_url_spec.rb b/spec/lib/endpoint_url_spec.rb index fae834e..63b7089 100644 --- a/spec/lib/endpoint_url_spec.rb +++ b/spec/lib/endpoint_url_spec.rb @@ -2,16 +2,34 @@ describe EndpointUrl do describe '.geoserver' do - context 'when server is configured' do + context 'when server is configured and file exists' do + let(:secret_file) { 'tmp/test_secret.txt' } + before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('https://example.com//') + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return(secret_file) + File.write(secret_file, 'https://user:pass@example.com/rest/') + end + + after do + FileUtils.rm_f(secret_file) end it 'returns WMS endpoint URL' do result = EndpointUrl.geoserver('test_server') expect(result).to eq('https://example.com/wms?service=WMS&request=GetCapabilities') end + end + context 'when file does not exist' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('nonexistent_file.txt') + end + + it 'logs error and returns nil' do + expect(Rails.logger).to receive(:error).with(/Failed to read GEOSERVER_URL_FILE/) + result = EndpointUrl.geoserver('test_server') + expect(result).to be_nil + end end context 'when server is not configured' do @@ -19,7 +37,7 @@ allow(Rails.configuration.x.servers).to receive(:[]).with('missing_server').and_return(nil) end - it 'returns nil' do + it 'returns nil without logging error' do result = EndpointUrl.geoserver('missing_server') expect(result).to be_nil end @@ -29,14 +47,13 @@ describe '.spatial_server' do context 'when server is configured' do before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('https://example.com//') + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('https://example.com') end it 'returns spatial server data zip endpoint URL' do result = EndpointUrl.spatial_server('test_server') expect(result).to eq('https://example.com/public/berkeley-status/data.zip') end - end context 'when server is not configured' do @@ -50,4 +67,60 @@ end end end + + describe '.get_url' do + let(:secret_file) { 'tmp/test_secret.txt' } + + context 'when file exists with valid URL' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return(secret_file) + File.write(secret_file, 'https://user:pass@example.com/rest/') + end + + after do + FileUtils.rm_f(secret_file) + end + + it 'returns cleaned URL without credentials and /rest suffix' do + result = EndpointUrl.get_url('test_server') + expect(result).to eq('https://example.com') + end + end + + context 'when file does not exist' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('nonexistent_file.txt') + end + + it 'logs error and returns nil' do + expect(Rails.logger).to receive(:error).with(/Failed to read GEOSERVER_URL_FILE/) + result = EndpointUrl.get_url('test_server') + expect(result).to be_nil + end + end + + context 'when server config is nil' do + before do + allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return(nil) + end + + it 'returns nil without logging error' do + result = EndpointUrl.get_url('test_server') + expect(result).to be_nil + end + end + end + + describe '.safe_url' do + + it 'removes both credentials and /rest suffix' do + result = EndpointUrl.safe_url('https://user:password@example.com/rest/') + expect(result).to eq('https://example.com') + end + + it 'returns nil when input is nil' do + result = EndpointUrl.safe_url(nil) + expect(result).to be_nil + end + end end diff --git a/spec/requests/okcomputer_spec.rb b/spec/requests/okcomputer_spec.rb index 0f98aa5..a04d1c8 100644 --- a/spec/requests/okcomputer_spec.rb +++ b/spec/requests/okcomputer_spec.rb @@ -14,9 +14,6 @@ database database-migrations solr - geoserver - secure_geoserver - spatial_server ] end end From 9b0d79b24c0344878a090839d2dae5befe599fad Mon Sep 17 00:00:00 2001 From: zhouyu Date: Fri, 23 Jan 2026 15:10:25 -0800 Subject: [PATCH 11/15] Handle special cases --- config/initializers/okcomputer.rb | 20 +++--- lib/endpoint_url.rb | 12 ++-- lib/http_head_check.rb | 29 +++++--- lib/http_head_check_new.rb | 60 ----------------- spec/lib/endpoint_url_spec.rb | 55 --------------- spec/lib/http_head_check_spec.rb | 108 ++++++++++++++++-------------- spec/requests/okcomputer_spec.rb | 5 +- 7 files changed, 99 insertions(+), 190 deletions(-) delete mode 100644 lib/http_head_check_new.rb diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index 7fdf6f0..cffef76 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -1,7 +1,7 @@ # initializers/okcomputer.rb # Health checks configuration -require_relative '../../lib/http_head_check_new' +require_relative '../../lib/http_head_check' require_relative '../../lib/endpoint_url' OkComputer.logger = Rails.logger @@ -15,14 +15,14 @@ core_baseurl = Blacklight.default_index.connection.uri.to_s.chomp('/') OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl) -# # Perform a Head request to check geoserver endpoint -# geoserver_url = EndpointUrl.geoserver(:geoserver) -# OkComputer::Registry.register 'geoserver', GeoDataHealthCheck::HttpHeadCheckNew.new(geoserver_url) +# Perform a Head request to check geoserver endpoint +geoserver_url = EndpointUrl.geoserver(:geoserver) +OkComputer::Registry.register 'geoserver', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url) -# # Perform a Head request to check secure_geoserver endpoint -# secure_geoserver_url = EndpointUrl.geoserver(:geoserver_secure) -# OkComputer::Registry.register 'geoserver_secure', GeoDataHealthCheck::HttpHeadCheckNew.new(secure_geoserver_url) +# Perform a Head request to check secure_geoserver endpoint +geoserver_secure_url = EndpointUrl.geoserver(:geoserver_secure) +OkComputer::Registry.register 'geoserver_secure', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_secure_url) -# # Perform a Head request to check spatial server endpoint -# spatial_server_url = EndpointUrl.spatial_server(:spatial_server) -# OkComputer::Registry.register 'spatial_server', GeoDataHealthCheck::HttpHeadCheckNew.new(spatial_server_url) +# Perform a Head request to check spatial server endpoint +spatial_server_url = EndpointUrl.spatial_server(:spatial_server) +OkComputer::Registry.register 'spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(spatial_server_url) diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb index 12ddfe1..3ac605b 100644 --- a/lib/endpoint_url.rb +++ b/lib/endpoint_url.rb @@ -3,22 +3,24 @@ class EndpointUrl class << self def geoserver(server_name) url = get_url(server_name) - url && "#{url}/wms?service=WMS&request=GetCapabilities" + url && "#{url.sub(%r{/+\z}, '')}/wms?service=WMS&request=GetCapabilities" end def spatial_server(server_name) url = Rails.configuration.x.servers[server_name] - url && "#{url}/public/berkeley-status/data.zip" + url && "#{url.sub(%r{/+\z}, '')}/public/berkeley-status/data.zip" end + private + def get_url(server_name) secret_file = Rails.configuration.x.servers[server_name] - return if secret_file.nil? + raise Errno::ENOENT if secret_file.nil? url = File.read(secret_file).chomp safe_url(url) - rescue Errno::ENOENT, Errno::EACCES => e - Rails.logger.error "Failed to read GEOSERVER_URL_FILE from #{secret_file}: #{e.message}" + rescue Errno::ENOENT, Errno::EACCES + Rails.logger.error 'Failed to read GEOSERVER_URL_FILE' nil end diff --git a/lib/http_head_check.rb b/lib/http_head_check.rb index 0f0995a..c4ef334 100644 --- a/lib/http_head_check.rb +++ b/lib/http_head_check.rb @@ -1,5 +1,14 @@ module GeoDataHealthCheck - class HttpHeadCheck < OkComputer::HttpCheck + class HttpHeadCheck < OkComputer::Check + ConnectionFailed = Class.new(StandardError) + attr_accessor :url, :request_timeout + + # rubocop:disable Lint/MissingSuper + def initialize(url, request_timeout = 5) + self.url = url + self.request_timeout = request_timeout + end + # rubocop:enable Lint/MissingSuper def check response = perform_request @@ -7,19 +16,20 @@ def check if response.is_a?(Net::HTTPOK) || response.is_a?(Net::HTTPRedirection) mark_message 'Http head check successful.' else + mark_message "Error: '#{url}' http head check responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." mark_failure - mark_message "Error: '#{url.request_uri}' http head check responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." end rescue StandardError => e - mark_message "Error: '#{e}'" + mark_message "Error: '#{e.message}'" mark_failure end def perform_request head_request rescue Net::OpenTimeout, Net::ReadTimeout => e - msg = "#{url.request_uri} did not respond within #{request_timeout} seconds: " - raise ConnectionFailed, msg + e.message + raise ConnectionFailed, "#{url} did not respond within #{request_timeout} seconds: #{e.message}" + rescue ArgumentError => e + raise ConnectionFailed, "Invalid URL format for '#{url}', please check log; #{e.class}: #{e.message}" rescue StandardError => e raise ConnectionFailed, e.message end @@ -27,15 +37,16 @@ def perform_request private def head_request + uri = URI(url) Net::HTTP.start( - url.host, - url.port, - use_ssl: url.scheme == 'https', + uri.host, + uri.port, + use_ssl: uri.scheme == 'https', verify_mode: OpenSSL::SSL::VERIFY_PEER, open_timeout: request_timeout, read_timeout: request_timeout ) do |http| - http.head(url.request_uri) + http.head(uri.request_uri) end end diff --git a/lib/http_head_check_new.rb b/lib/http_head_check_new.rb deleted file mode 100644 index 6277c3e..0000000 --- a/lib/http_head_check_new.rb +++ /dev/null @@ -1,60 +0,0 @@ -module GeoDataHealthCheck - class HttpHeadCheckNew < OkComputer::Check - ConnectionFailed = Class.new(StandardError) - attr_accessor :url, :request_timeout - - # rubocop:disable Lint/MissingSuper - def initialize(url, request_timeout = 5) - self.url = url - self.request_timeout = request_timeout - end - # rubocop:enable Lint/MissingSuper - - def check - return skip_check if url.blank? - - response = perform_request - - if response.is_a?(Net::HTTPOK) || response.is_a?(Net::HTTPRedirection) - mark_message 'Http head check successful.' - else - mark_failure - mark_message "Error: '#{url}' http head check responded, but returned unexpeced HTTP status: #{response.code} #{response.class}. Expected 200 Net::HTTPOK." - end - rescue StandardError => e - mark_message "Error: '#{e}'" - mark_failure - end - - def perform_request - head_request - rescue Net::OpenTimeout, Net::ReadTimeout => e - msg = "#{url} did not respond within #{request_timeout} seconds: " - raise ConnectionFailed, msg + e.message - rescue StandardError => e - raise ConnectionFailed, e.message - end - - private - - def skip_check - mark_failure - mark_message 'No URL configured; health check was skipped...' - end - - def head_request - uri = URI(url) - Net::HTTP.start( - uri.host, - uri.port, - use_ssl: uri.scheme == 'https', - verify_mode: OpenSSL::SSL::VERIFY_PEER, - open_timeout: request_timeout, - read_timeout: request_timeout - ) do |http| - http.head(uri.request_uri) - end - end - - end -end diff --git a/spec/lib/endpoint_url_spec.rb b/spec/lib/endpoint_url_spec.rb index 63b7089..ceaacdc 100644 --- a/spec/lib/endpoint_url_spec.rb +++ b/spec/lib/endpoint_url_spec.rb @@ -68,59 +68,4 @@ end end - describe '.get_url' do - let(:secret_file) { 'tmp/test_secret.txt' } - - context 'when file exists with valid URL' do - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return(secret_file) - File.write(secret_file, 'https://user:pass@example.com/rest/') - end - - after do - FileUtils.rm_f(secret_file) - end - - it 'returns cleaned URL without credentials and /rest suffix' do - result = EndpointUrl.get_url('test_server') - expect(result).to eq('https://example.com') - end - end - - context 'when file does not exist' do - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('nonexistent_file.txt') - end - - it 'logs error and returns nil' do - expect(Rails.logger).to receive(:error).with(/Failed to read GEOSERVER_URL_FILE/) - result = EndpointUrl.get_url('test_server') - expect(result).to be_nil - end - end - - context 'when server config is nil' do - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return(nil) - end - - it 'returns nil without logging error' do - result = EndpointUrl.get_url('test_server') - expect(result).to be_nil - end - end - end - - describe '.safe_url' do - - it 'removes both credentials and /rest suffix' do - result = EndpointUrl.safe_url('https://user:password@example.com/rest/') - expect(result).to eq('https://example.com') - end - - it 'returns nil when input is nil' do - result = EndpointUrl.safe_url(nil) - expect(result).to be_nil - end - end end diff --git a/spec/lib/http_head_check_spec.rb b/spec/lib/http_head_check_spec.rb index ef10e86..595a863 100644 --- a/spec/lib/http_head_check_spec.rb +++ b/spec/lib/http_head_check_spec.rb @@ -1,81 +1,89 @@ -require 'spec_helper' +require 'rails_helper' require_relative '../../lib/http_head_check' RSpec.describe GeoDataHealthCheck::HttpHeadCheck do - let(:test_url) { URI('http://example.com/endpoint') } - let(:check) { described_class.new(test_url) } + let(:url) { 'https://example.com/endpoint' } + subject(:check) { described_class.new(url) } - describe '#check' do - it 'succeeds when response is 200 OK' do - response = Net::HTTPOK.new('1.1', '200', 'OK') - allow(check).to receive(:perform_request).and_return(response) - - check.check - - expect(check.message).to include('Http head check successful.') + describe 'initialization' do + it 'sets the URL' do + expect(check.url).to eq url end - it 'succeeds when response is a redirect' do - response = Net::HTTPFound.new('1.1', '302', 'Found') - allow(check).to receive(:perform_request).and_return(response) - - check.check + it 'sets default timeout to 5 seconds' do + expect(check.request_timeout).to eq 5 + end - expect(check.message).to include('Http head check successful.') + it 'allows custom timeout' do + check = described_class.new(url, 10) + expect(check.request_timeout).to eq 10 end + end - it 'fails when response is 404' do - response = Net::HTTPNotFound.new('1.1', '404', 'Not Found') - allow(check).to receive(:perform_request).and_return(response) + describe '#check' do + context 'when request returns 200 OK' do + it 'marks check as successful' do + response = Net::HTTPOK.new('1.1', 200, 'OK') + allow(check).to receive(:perform_request).and_return(response) - check.check + check.check - expect(check.message).to include('http head check responded, but returned unexpeced HTTP status: 404 Net::HTTPNotFound') + expect(check.message).to include('Http head check successful.') + end end - it 'fails when request raises an error' do - error = StandardError.new('Connection error') - allow(check).to receive(:perform_request).and_raise(error) + context 'when request returns 500 error' do + it 'marks check as failed' do + response = Net::HTTPInternalServerError.new('1.1', 500, 'Error') + allow(check).to receive(:perform_request).and_return(response) - check.check + check.check - expect(check.message).to include('Error:') - expect(check.message).to include('Connection error') + expect(check.message).to include('Error') + end end + end describe '#perform_request' do - it 'calls head_request' do - response = Net::HTTPOK.new('1.1', '200', 'OK') - allow(check).to receive(:head_request).and_return(response) - - result = check.perform_request - - expect(result).to eq response + it 'Net::OpenTimeout with ConnectionFailed and formated message' do + check_with_timeout = described_class.new(url, 7) + allow(check_with_timeout).to receive(:head_request).and_raise(Net::OpenTimeout.new('open timeout')) + + expect { check_with_timeout.perform_request }.to raise_error( + GeoDataHealthCheck::HttpHeadCheck::ConnectionFailed, + a_string_including('did not respond within 7 seconds: open timeout') + ) end - it 'raises ConnectionFailed on OpenTimeout' do - allow(check).to receive(:head_request).and_raise(Net::OpenTimeout.new) + it 'Net::ReadTimeout with ConnectionFailed and formated message' do + check_with_timeout = described_class.new(url, 9) + allow(check_with_timeout).to receive(:head_request).and_raise(Net::ReadTimeout.new('read timeout')) - expect do - check.perform_request - end.to raise_error(OkComputer::HttpCheck::ConnectionFailed) + expect { check_with_timeout.perform_request }.to raise_error( + GeoDataHealthCheck::HttpHeadCheck::ConnectionFailed, + a_string_including('did not respond within 9 seconds: Net::ReadTimeout') + ) end - it 'raises ConnectionFailed on ReadTimeout' do - allow(check).to receive(:head_request).and_raise(Net::ReadTimeout.new) + it 'StandardError and passes through the message' do + err_msg = 'generic failure' + allow(check).to receive(:head_request).and_raise(StandardError, err_msg) - expect do - check.perform_request - end.to raise_error(OkComputer::HttpCheck::ConnectionFailed) + expect { check.perform_request }.to raise_error( + GeoDataHealthCheck::HttpHeadCheck::ConnectionFailed, + err_msg + ) end - it 'raises ConnectionFailed on StandardError' do - allow(check).to receive(:head_request).and_raise(StandardError.new) + it 'wraps ArgumentError with ConnectionFailed and includes URL and error class' do + bad_check = described_class.new(url) + allow(bad_check).to receive(:head_request).and_raise(ArgumentError, 'invalid URI') - expect do - check.perform_request - end.to raise_error(OkComputer::HttpCheck::ConnectionFailed) + expect { bad_check.perform_request }.to raise_error( + GeoDataHealthCheck::HttpHeadCheck::ConnectionFailed, + a_string_including("Invalid URL format for '#{url}'", 'ArgumentError', 'invalid URI') + ) end end end diff --git a/spec/requests/okcomputer_spec.rb b/spec/requests/okcomputer_spec.rb index a04d1c8..7801eca 100644 --- a/spec/requests/okcomputer_spec.rb +++ b/spec/requests/okcomputer_spec.rb @@ -8,12 +8,15 @@ it 'returns all checks at /health' do get '/health' - expect(response).to have_http_status :ok + expect(response).to have_http_status :internal_server_error expect(response.parsed_body.keys).to match_array %w[ default database database-migrations solr + geoserver + geoserver_secure + spatial_server ] end end From b460b5bcb48fc9217e9a43f4e68111c9710d27dd Mon Sep 17 00:00:00 2001 From: zhouyu Date: Fri, 23 Jan 2026 18:46:41 -0800 Subject: [PATCH 12/15] Update message --- lib/endpoint_url.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb index 3ac605b..21370af 100644 --- a/lib/endpoint_url.rb +++ b/lib/endpoint_url.rb @@ -19,8 +19,8 @@ def get_url(server_name) url = File.read(secret_file).chomp safe_url(url) - rescue Errno::ENOENT, Errno::EACCES - Rails.logger.error 'Failed to read GEOSERVER_URL_FILE' + rescue StandardError => e + Rails.logger.error "[EndpointUrl] Failed to read #{server_name}'s URL from secrets file.#{e.message}" nil end From 331d7ad03d2db03f87794c1e502a328be93ed0d9 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Fri, 23 Jan 2026 19:02:43 -0800 Subject: [PATCH 13/15] Update a test --- spec/lib/endpoint_url_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/endpoint_url_spec.rb b/spec/lib/endpoint_url_spec.rb index ceaacdc..9c3df10 100644 --- a/spec/lib/endpoint_url_spec.rb +++ b/spec/lib/endpoint_url_spec.rb @@ -26,7 +26,7 @@ end it 'logs error and returns nil' do - expect(Rails.logger).to receive(:error).with(/Failed to read GEOSERVER_URL_FILE/) + expect(Rails.logger).to receive(:error).with("[EndpointUrl] Failed to read test_server's URL from secrets file.No such file or directory @ rb_sysopen - nonexistent_file.txt") result = EndpointUrl.geoserver('test_server') expect(result).to be_nil end From 0c4b921fb826818934c03518ea1cdc01f4707fa8 Mon Sep 17 00:00:00 2001 From: zhouyu Date: Mon, 26 Jan 2026 16:03:58 -0800 Subject: [PATCH 14/15] To store checkpoint urls directly in Environment variables --- config/application.rb | 6 +-- lib/endpoint_url.rb | 21 +--------- lib/http_head_check.rb | 2 +- spec/lib/endpoint_url_spec.rb | 77 +++++++++++------------------------ 4 files changed, 29 insertions(+), 77 deletions(-) diff --git a/config/application.rb b/config/application.rb index bdebd5f..e36274d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -22,9 +22,9 @@ class Application < Rails::Application config.x.servers ||= {} - config.x.servers[:geoserver] = ENV.fetch('GEOSERVER_URL_FILE', nil) - config.x.servers[:geoserver_secure] = ENV.fetch('GEOSERVER_SECURE_URL_FILE', nil) - config.x.servers[:spatial_server] = ENV.fetch('SPATIAL_URL', nil) + config.x.servers[:geoserver] = ENV.fetch('GEODATA_GEOSERVER_PUBLIC_HEALTHCHECK_URL', nil) + config.x.servers[:geoserver_secure] = ENV.fetch('GEODATA_GEOSERVER_SECURE_HEALTHCHECK_URL', nil) + config.x.servers[:spatial_server] = ENV.fetch('GEODATA_SPATIAL_HEALTHCHECK_URL', nil) # The Base URL for the generated sitemap config.x.sitemap.base_url = ENV.fetch('GEODATA_BASE_URL', 'http://localhost:3000') diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb index 21370af..34908a1 100644 --- a/lib/endpoint_url.rb +++ b/lib/endpoint_url.rb @@ -1,4 +1,3 @@ -require 'uri' class EndpointUrl class << self def geoserver(server_name) @@ -7,30 +6,14 @@ def geoserver(server_name) end def spatial_server(server_name) - url = Rails.configuration.x.servers[server_name] + url = get_url(server_name) url && "#{url.sub(%r{/+\z}, '')}/public/berkeley-status/data.zip" end private def get_url(server_name) - secret_file = Rails.configuration.x.servers[server_name] - raise Errno::ENOENT if secret_file.nil? - - url = File.read(secret_file).chomp - safe_url(url) - rescue StandardError => e - Rails.logger.error "[EndpointUrl] Failed to read #{server_name}'s URL from secrets file.#{e.message}" - nil - end - - def safe_url(url) - return if url.nil? - - uri = URI(url) - uri.user = nil - uri.password = nil - uri.to_s.sub(%r{/rest/?$}, '') + Rails.configuration.x.servers[server_name] end end end diff --git a/lib/http_head_check.rb b/lib/http_head_check.rb index c4ef334..1f94efe 100644 --- a/lib/http_head_check.rb +++ b/lib/http_head_check.rb @@ -29,7 +29,7 @@ def perform_request rescue Net::OpenTimeout, Net::ReadTimeout => e raise ConnectionFailed, "#{url} did not respond within #{request_timeout} seconds: #{e.message}" rescue ArgumentError => e - raise ConnectionFailed, "Invalid URL format for '#{url}', please check log; #{e.class}: #{e.message}" + raise ConnectionFailed, "Invalid URL format for '#{url}': #{e.class}: #{e.message}" rescue StandardError => e raise ConnectionFailed, e.message end diff --git a/spec/lib/endpoint_url_spec.rb b/spec/lib/endpoint_url_spec.rb index 9c3df10..a36f288 100644 --- a/spec/lib/endpoint_url_spec.rb +++ b/spec/lib/endpoint_url_spec.rb @@ -1,71 +1,40 @@ require 'rails_helper' +require_relative '../../lib/endpoint_url' + +RSpec.describe EndpointUrl do + around do |example| + original = Rails.configuration.x.servers.dup + Rails.configuration.x.servers.clear + example.run + Rails.configuration.x.servers.clear + Rails.configuration.x.servers.merge!(original) + end -describe EndpointUrl do describe '.geoserver' do - context 'when server is configured and file exists' do - let(:secret_file) { 'tmp/test_secret.txt' } - - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return(secret_file) - File.write(secret_file, 'https://user:pass@example.com/rest/') - end + it 'builds a GetCapabilities URL without duplicate slashes' do + Rails.configuration.x.servers[:geoserver] = 'https://example.com/geoserver//' - after do - FileUtils.rm_f(secret_file) - end + result = described_class.geoserver(:geoserver) - it 'returns WMS endpoint URL' do - result = EndpointUrl.geoserver('test_server') - expect(result).to eq('https://example.com/wms?service=WMS&request=GetCapabilities') - end + expect(result).to eq('https://example.com/geoserver/wms?service=WMS&request=GetCapabilities') end - context 'when file does not exist' do - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('nonexistent_file.txt') - end - - it 'logs error and returns nil' do - expect(Rails.logger).to receive(:error).with("[EndpointUrl] Failed to read test_server's URL from secrets file.No such file or directory @ rb_sysopen - nonexistent_file.txt") - result = EndpointUrl.geoserver('test_server') - expect(result).to be_nil - end - end - - context 'when server is not configured' do - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('missing_server').and_return(nil) - end - - it 'returns nil without logging error' do - result = EndpointUrl.geoserver('missing_server') - expect(result).to be_nil - end + it 'returns nil when server is not configured' do + expect(described_class.geoserver(:unknown)).to be_nil end end describe '.spatial_server' do - context 'when server is configured' do - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('test_server').and_return('https://example.com') - end + it 'builds the status data URL trimming trailing slashes' do + Rails.configuration.x.servers[:spatial_server] = 'https://example.com/status/' - it 'returns spatial server data zip endpoint URL' do - result = EndpointUrl.spatial_server('test_server') - expect(result).to eq('https://example.com/public/berkeley-status/data.zip') - end - end + result = described_class.spatial_server(:spatial_server) - context 'when server is not configured' do - before do - allow(Rails.configuration.x.servers).to receive(:[]).with('missing_server').and_return(nil) - end + expect(result).to eq('https://example.com/status/public/berkeley-status/data.zip') + end - it 'returns nil' do - result = EndpointUrl.spatial_server('missing_server') - expect(result).to be_nil - end + it 'returns nil when server is not configured' do + expect(described_class.spatial_server(:missing)).to be_nil end end - end From a3af94a0720b2792d2e6ffecf2cd02785dbfbe3c Mon Sep 17 00:00:00 2001 From: zhouyu Date: Tue, 27 Jan 2026 09:59:22 -0800 Subject: [PATCH 15/15] Updated to store health check endpoint urls in environment variables --- config/initializers/okcomputer.rb | 7 +++--- lib/endpoint_url.rb | 19 --------------- spec/lib/endpoint_url_spec.rb | 40 ------------------------------- 3 files changed, 3 insertions(+), 63 deletions(-) delete mode 100644 lib/endpoint_url.rb delete mode 100644 spec/lib/endpoint_url_spec.rb diff --git a/config/initializers/okcomputer.rb b/config/initializers/okcomputer.rb index cffef76..b4a35b3 100644 --- a/config/initializers/okcomputer.rb +++ b/config/initializers/okcomputer.rb @@ -2,7 +2,6 @@ # Health checks configuration require_relative '../../lib/http_head_check' -require_relative '../../lib/endpoint_url' OkComputer.logger = Rails.logger OkComputer.check_in_parallel = true @@ -16,13 +15,13 @@ OkComputer::Registry.register 'solr', OkComputer::SolrCheck.new(core_baseurl) # Perform a Head request to check geoserver endpoint -geoserver_url = EndpointUrl.geoserver(:geoserver) +geoserver_url = Rails.configuration.x.servers[:geoserver] OkComputer::Registry.register 'geoserver', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_url) # Perform a Head request to check secure_geoserver endpoint -geoserver_secure_url = EndpointUrl.geoserver(:geoserver_secure) +geoserver_secure_url = Rails.configuration.x.servers[:geoserver_secure] OkComputer::Registry.register 'geoserver_secure', GeoDataHealthCheck::HttpHeadCheck.new(geoserver_secure_url) # Perform a Head request to check spatial server endpoint -spatial_server_url = EndpointUrl.spatial_server(:spatial_server) +spatial_server_url = Rails.configuration.x.servers[:spatial_server] OkComputer::Registry.register 'spatial_server', GeoDataHealthCheck::HttpHeadCheck.new(spatial_server_url) diff --git a/lib/endpoint_url.rb b/lib/endpoint_url.rb deleted file mode 100644 index 34908a1..0000000 --- a/lib/endpoint_url.rb +++ /dev/null @@ -1,19 +0,0 @@ -class EndpointUrl - class << self - def geoserver(server_name) - url = get_url(server_name) - url && "#{url.sub(%r{/+\z}, '')}/wms?service=WMS&request=GetCapabilities" - end - - def spatial_server(server_name) - url = get_url(server_name) - url && "#{url.sub(%r{/+\z}, '')}/public/berkeley-status/data.zip" - end - - private - - def get_url(server_name) - Rails.configuration.x.servers[server_name] - end - end -end diff --git a/spec/lib/endpoint_url_spec.rb b/spec/lib/endpoint_url_spec.rb deleted file mode 100644 index a36f288..0000000 --- a/spec/lib/endpoint_url_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'rails_helper' -require_relative '../../lib/endpoint_url' - -RSpec.describe EndpointUrl do - around do |example| - original = Rails.configuration.x.servers.dup - Rails.configuration.x.servers.clear - example.run - Rails.configuration.x.servers.clear - Rails.configuration.x.servers.merge!(original) - end - - describe '.geoserver' do - it 'builds a GetCapabilities URL without duplicate slashes' do - Rails.configuration.x.servers[:geoserver] = 'https://example.com/geoserver//' - - result = described_class.geoserver(:geoserver) - - expect(result).to eq('https://example.com/geoserver/wms?service=WMS&request=GetCapabilities') - end - - it 'returns nil when server is not configured' do - expect(described_class.geoserver(:unknown)).to be_nil - end - end - - describe '.spatial_server' do - it 'builds the status data URL trimming trailing slashes' do - Rails.configuration.x.servers[:spatial_server] = 'https://example.com/status/' - - result = described_class.spatial_server(:spatial_server) - - expect(result).to eq('https://example.com/status/public/berkeley-status/data.zip') - end - - it 'returns nil when server is not configured' do - expect(described_class.spatial_server(:missing)).to be_nil - end - end -end