diff --git a/modules/claims_api/lib/bgs_service/local_bgs.rb b/modules/claims_api/lib/bgs_service/local_bgs.rb index fb9443409ba..5b2ac52214a 100644 --- a/modules/claims_api/lib/bgs_service/local_bgs.rb +++ b/modules/claims_api/lib/bgs_service/local_bgs.rb @@ -12,18 +12,26 @@ module ClaimsApi class LocalBGS + Fault = + Data.define( + :code, + :string, + :message + ) + class << self def breakers_service url = URI.parse(Settings.bgs.url) - matcher = proc do |request_env| - request_env.url.host == url.host && - request_env.url.port == url.port && - request_env.url.path =~ /^#{url.path}/ - end + request_matcher = + proc do |request_env| + request_env.url.host == url.host && + request_env.url.port == url.port && + request_env.url.path =~ /^#{url.path}/ + end Breakers::Service.new( name: 'BGS/Claims', - request_matcher: matcher + request_matcher: ) end end @@ -69,11 +77,14 @@ def initialize( # rubocop:disable Metrics/MethodLength end def healthcheck(endpoint) - response = fetch_wsdl(endpoint) - response.status + fetch_wsdl(endpoint).status end - def make_request(endpoint:, action:, body:, key: nil, namespaces: {}, transform_response: true) # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists + def make_request( # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists + endpoint:, action:, body:, key: nil, namespaces: {}, + error_handler: ClaimsApi::SoapErrorHandler, + transform_response: true + ) begin wsdl = log_duration(event: 'connection_wsdl_get', endpoint:) do @@ -97,7 +108,6 @@ def make_request(endpoint:, action:, body:, key: nil, namespaces: {}, transform_ log_duration(event: 'connection_post', endpoint:, action:) do connection.post(endpoint) do |req| req.body = request_body - req.headers.merge!( 'Content-Type' => 'text/xml;charset=UTF-8', 'Host' => "#{@env}.vba.va.gov", @@ -114,7 +124,7 @@ def make_request(endpoint:, action:, body:, key: nil, namespaces: {}, transform_ log_duration(event: 'parsed_response', key:) do response_body = Hash.from_xml(response.body) - soap_error_handler.handle_errors!(response_body) + handle_errors!(response_body, error_handler:) unwrap_response_body( response_body, @@ -188,8 +198,24 @@ def unwrap_response_body(body, action:, key:, transform:) end end - def soap_error_handler - ClaimsApi::SoapErrorHandler.new + def handle_errors!(body, error_handler:) + data = body.dig('Envelope', 'Body', 'Fault').to_h + return if data.blank? + + message = + data.dig('detail', 'MessageException') || + data.dig('detail', 'MessageFaultException') + + fault = + Fault.new( + code: data['faultcode'].to_s.split(':').last, + string: data['faultstring'], + message: + ) + + error_handler.handle_errors!( + fault + ) end def connection diff --git a/modules/claims_api/lib/claims_api/error/soap_error_handler.rb b/modules/claims_api/lib/claims_api/error/soap_error_handler.rb index 736981400af..5c4d900ee10 100644 --- a/modules/claims_api/lib/claims_api/error/soap_error_handler.rb +++ b/modules/claims_api/lib/claims_api/error/soap_error_handler.rb @@ -1,30 +1,24 @@ # frozen_string_literal: true module ClaimsApi + # list of fault codes: https://hub.verj.io/ebase/doc/SOAP_Faults.htm + # + # TODO: Some (or all) of these cases should be handled in consumers and not in + # a central location. class SoapErrorHandler - # list of fault codes: https://hub.verj.io/ebase/doc/SOAP_Faults.htm - - def handle_errors!(body) - @hash = body - - return if @hash&.dig('Envelope', 'Body', 'Fault').blank? - - get_fault_info + class << self + def handle_errors!(fault) + new(fault).handle_errors! + end end - def get_fault_info - fault = @hash&.dig('Envelope', 'Body', 'Fault') - @fault_code = fault&.dig('faultcode')&.split(':')&.dig(1) - @fault_string = fault&.dig('faultstring') - @fault_message = fault&.dig('detail', 'MessageException') || fault&.dig('detail', 'MessageFaultException') - return {} if @fault_string.include?('IntentToFileWebService') && @fault_string.include?('not found') - - get_exception + def initialize(fault) + @fault = fault end - private + def handle_errors! + return if not_error? - def get_exception if not_found? raise ::Common::Exceptions::ResourceNotFound.new(detail: 'Resource not found.') elsif bnft_claim_not_found? @@ -39,16 +33,23 @@ def get_exception end end + private + + def not_error? + @fault.string.include?('IntentToFileWebService') && + @fault.string.include?('not found') + end + def not_found? errors = ['bnftClaimId-->bnftClaimId/text()', 'not found', 'No Person found'] - has_errors = errors.any? { |error| @fault_string.include? error } + has_errors = errors.any? { |error| @fault.string.include? error } soap_logging('404') if has_errors has_errors end def bnft_claim_not_found? errors = ['No BnftClaim found'] - has_errors = errors.any? { |error| @fault_string.include? error } + has_errors = errors.any? { |error| @fault.string.include? error } soap_logging('404') if has_errors has_errors end @@ -57,7 +58,7 @@ def unprocessable? errors = ['java.sql', 'MessageException', 'Validation errors', 'Exception Description', 'does not have necessary info', 'Error committing transaction', 'Transaction Rolledback', 'Unexpected error', 'XML reader error', 'could not be converted'] - has_errors = errors.any? { |error| @fault_string.include? error } + has_errors = errors.any? { |error| @fault.string.include? error } soap_logging('422') if has_errors has_errors end @@ -65,8 +66,8 @@ def unprocessable? def soap_logging(status_code) ClaimsApi::Logger.log('soap_error_handler', detail: "Returning #{status_code} via local_bgs & soap_error_handler, " \ - "fault_string: #{@fault_string}, with message: #{@fault_message}, " \ - "and fault_code: #{@fault_code}.") + "fault_string: #{@fault.string}, with message: #{@fault.message}, " \ + "and fault_code: #{@fault.code}.") end end end