diff --git a/lib/rack/canonical_host.rb b/lib/rack/canonical_host.rb index 5091b09..5e6cfae 100644 --- a/lib/rack/canonical_host.rb +++ b/lib/rack/canonical_host.rb @@ -15,11 +15,13 @@ def call(env) host = evaluate_host(env) redirect = Redirect.new(env, host, options) - if redirect.canonical? - app.call(env) - else - redirect.response + begin + return redirect.response unless redirect.canonical? + rescue Addressable::URI::InvalidURIError + return [400, { Rack::CONTENT_TYPE => "text/plain", Rack::CONTENT_LENGTH => "0" }, []] end + + app.call(env) end protected diff --git a/spec/rack/canonical_host_spec.rb b/spec/rack/canonical_host_spec.rb index dcde709..fcc2e44 100644 --- a/spec/rack/canonical_host_spec.rb +++ b/spec/rack/canonical_host_spec.rb @@ -84,6 +84,20 @@ def call_app end end + + context 'when the app happens to have an invalid uri error' do + before do + allow(inner_app) + .to receive(:call) + .with(env) + .and_raise(Addressable::URI::InvalidURIError) + end + + it 'explodes as expected' do + expect { call_app }.to raise_error(Addressable::URI::InvalidURIError) + end + end + context 'with an X-Forwarded-Host' do let(:url) { 'http://proxy.test/full/path' } @@ -98,6 +112,21 @@ def call_app it_behaves_like 'a non-matching request' end + + context 'which is an invalid uri' do + let(:headers) { { 'HTTP_X_FORWARDED_HOST' => '[${jndi:ldap://172.16.26.190:52314/nessus}]/' } } + + it { should_not be_redirect } + + it { expect(response[0]).to be 400 } + + it 'does not call the inner app' do + expect(inner_app).to_not receive(:call) + call_app + end + + it { expect(response).to_not have_header('cache-control') } + end end context 'without a host' do