require 'spec_helper.rb' describe Stitches::ValidMimeType do let(:app) { double("rack app") } before do allow(app).to receive(:call).with(env) end subject(:middleware) { described_class.new(app, namespace: "/api") } shared_examples "an unacceptable response" do it "returns a 406" do status, _headers, _body = @response expect(status).to eq(406) end it "stops the call chain preventing anything from happening" do expect(app).not_to have_received(:call) end it "sends a reasonable message" do _status, _headers, body = @response expect(body.first).to match(/didn't have the right mime type or version number. We only accept application\/json/) end end describe "#call" do context "not in namespace" do context "not in allowlist" do let(:env) { { "PATH_INFO" => "/index/home", } } before do @response = middleware.call(env) end it_behaves_like "an unacceptable response" end context "allowlisting" do let(:env) { { "PATH_INFO" => "/index/home", } } context "allowlist is explicit in middleware usage" do before do @response = middleware.call(env) end context "passes the allowlist" do subject(:middleware) { described_class.new(app, except: %r{\A/resque\/.*\Z}) } let(:env) { { "PATH_INFO" => "/resque/overview" } } it "calls through to the rest of the chain" do expect(app).to have_received(:call).with(env) end end context "fails the allowlist" do subject(:middleware) { described_class.new(app, except: %r{\A/resque\/.*\Z}) } let(:env) { { "PATH_INFO" => "//resque/overview" # subtle } } it_behaves_like "an unacceptable response" end context "except: is not given a regexp" do let(:env) { { "PATH_INFO" => "//resque/overview" } } it "blows up" do expect { described_class.new(app, except: "/resque") }.to raise_error(/must be a Regexp/i) end end end context "allowlist is implicit from the configuration" do before do Stitches.configuration.allowlist_regexp = %r{\A/resque/.*\Z} @response = middleware.call(env) end context "passes the allowlist" do subject(:middleware) { described_class.new(app) } let(:env) { { "PATH_INFO" => "/resque/overview" } } it "calls through to the rest of the chain" do expect(app).to have_received(:call).with(env) end end context "fails the allowlist" do subject(:middleware) { described_class.new(app) } let(:env) { { "PATH_INFO" => "//resque/overview" # subtle } } it_behaves_like "an unacceptable response" end end end end context "valid header" do let(:env) { { "PATH_INFO" => "/api/ping", "HTTP_ACCEPT" => "application/json; version=99", } } before do @response = middleware.call(env) end it "calls through to the rest of the chain" do expect(app).to have_received(:call).with(env) end end context "unacceptable responses" do before do @response = middleware.call(env) end context "no header" do let(:env) { { "PATH_INFO" => "/api/ping", } } it_behaves_like "an unacceptable response" end context "bad mime type" do let(:env) { { "PATH_INFO" => "/api/ping", "HTTP_ACCEPT" => "application/json; version=bleorgh", } } it_behaves_like "an unacceptable response" end context "bad version" do let(:env) { { "PATH_INFO" => "/api/ping", "HTTP_ACCEPT" => "application/xml; version=1", } } it_behaves_like "an unacceptable response" end end end end