diff --git a/app/controllers/idv/in_person/public/usps_locations_controller.rb b/app/controllers/idv/in_person/public/usps_locations_controller.rb index b8f20a7f96d..9531141600c 100644 --- a/app/controllers/idv/in_person/public/usps_locations_controller.rb +++ b/app/controllers/idv/in_person/public/usps_locations_controller.rb @@ -3,15 +3,34 @@ module Idv module InPerson module Public + class UspsLocationsError < StandardError + def initialize + super('Unsupported characters in address field.') + end + end + class UspsLocationsController < ApplicationController skip_forgery_protection + include IppHelper + + rescue_from Faraday::Error, + StandardError, + UspsLocationsError, + Faraday::BadRequestError, + with: :handle_error + def index candidate = UspsInPersonProofing::Applicant.new( address: search_params['street_address'], city: search_params['city'], state: search_params['state'], zip_code: search_params['zip_code'] ) + + unless candidate.has_valid_address? + raise UspsLocationsError + end + locations = proofer.request_facilities(candidate, false) render json: localized_locations(locations).to_json @@ -34,6 +53,27 @@ def localized_locations(locations) end end + def handle_error(err) + remapped_error = case err + when ActionController::InvalidAuthenticityToken, + Faraday::Error, + UspsLocationsError + :unprocessable_entity + else + :internal_server_error + end + + analytics.idv_in_person_locations_request_failure( + api_status_code: Rack::Utils.status_code(remapped_error), + exception_class: err.class, + exception_message: scrub_message(err.message), + response_body_present: err.respond_to?(:response_body) && err.response_body.present?, + response_body: err.respond_to?(:response_body) && scrub_body(err.response_body), + response_status_code: err.respond_to?(:response_status) && err.response_status, + ) + render json: {}, status: remapped_error + end + def search_params params.require(:address).permit( :street_address, diff --git a/spec/controllers/idv/in_person/public/usps_locations_controller_spec.rb b/spec/controllers/idv/in_person/public/usps_locations_controller_spec.rb index 3559670d7b4..57b97ba4755 100644 --- a/spec/controllers/idv/in_person/public/usps_locations_controller_spec.rb +++ b/spec/controllers/idv/in_person/public/usps_locations_controller_spec.rb @@ -3,6 +3,10 @@ RSpec.describe Idv::InPerson::Public::UspsLocationsController do include Rails.application.routes.url_helpers + before do + stub_analytics + end + describe '#index' do subject(:action) do post :index, @@ -21,5 +25,59 @@ action expect(response).to be_ok end + + context 'with a 500 error from USPS' do + let(:server_error) { Faraday::ServerError.new } + let(:proofer) { double('Proofer') } + + before do + allow(UspsInPersonProofing::EnrollmentHelper).to receive(:usps_proofer).and_return(proofer) + allow(proofer).to receive(:request_facilities).and_raise(server_error) + end + + it 'returns an unprocessible entity client error' do + subject + expect(@analytics).to have_logged_event( + 'Request USPS IPP locations: request failed', + api_status_code: 422, + exception_class: server_error.class, + exception_message: server_error.message, + response_body_present: + server_error.response_body.present?, + ) + + status = response.status + expect(status).to eq 422 + end + end + + context 'address has unsupported characters' do + let(:locale) { nil } + let(:usps_locations_error) { Idv::InPerson::Public::UspsLocationsError.new } + + subject(:response) do + post :index, params: { locale: locale, + address: { street_address: '1600, Pennsylvania Ave', + city: 'Washington', + state: 'DC', + zip_code: '20500' } } + end + + it 'returns unprocessable entity' do + subject + + expect(@analytics).to have_logged_event( + 'Request USPS IPP locations: request failed', + api_status_code: 422, + exception_class: usps_locations_error.class, + exception_message: usps_locations_error.message, + response_body_present: false, + response_body: false, + response_status_code: false, + ) + + expect(response.status).to eq 422 + end + end end end