diff --git a/lib/mrkt/concerns/connection.rb b/lib/mrkt/concerns/connection.rb index c73380d..c9d23df 100644 --- a/lib/mrkt/concerns/connection.rb +++ b/lib/mrkt/concerns/connection.rb @@ -13,6 +13,7 @@ def init_connection conn.response :logger, @logger, (@log_options || {}) if @debug conn.response :mkto, content_type: /\bjson$/ + conn.response :mkto_exceptional_response conn.options.timeout = @options[:read_timeout] if @options.key?(:read_timeout) conn.options.open_timeout = @options[:open_timeout] if @options.key?(:open_timeout) diff --git a/lib/mrkt/faraday_middleware.rb b/lib/mrkt/faraday_middleware.rb index f87f47d..a841afd 100644 --- a/lib/mrkt/faraday_middleware.rb +++ b/lib/mrkt/faraday_middleware.rb @@ -3,9 +3,11 @@ module Mrkt module FaradayMiddleware autoload :Response, 'mrkt/faraday_middleware/response' + autoload :ExceptionalResponse, 'mrkt/faraday_middleware/exceptional_response' end if Faraday::Middleware.respond_to? :register_middleware Faraday::Response.register_middleware mkto: -> { Mrkt::FaradayMiddleware::Response } + Faraday::Response.register_middleware mkto_exceptional_response: -> { Mrkt::FaradayMiddleware::ExceptionalResponse } end end diff --git a/lib/mrkt/faraday_middleware/exceptional_response.rb b/lib/mrkt/faraday_middleware/exceptional_response.rb new file mode 100644 index 0000000..9f7c621 --- /dev/null +++ b/lib/mrkt/faraday_middleware/exceptional_response.rb @@ -0,0 +1,25 @@ +module Mrkt + module FaradayMiddleware + # A middleware to handle exceptional non-json responses. + # In some cases, for example in trouble of marketo servers, we confirmed + # there is possibility that servers could respond with non json response + # unexpectedly. + class ExceptionalResponse < Faraday::Response::Middleware + ServerErrorStatuses = 400...600 + + def on_complete(env) + # Nothing to do by this handler if response content type is like json + return if env[:response_headers]['Content-Type'] =~ /\bjson$/ + + case env[:status] + when ServerErrorStatuses + raise Mrkt::Errors::Unknown, response_values(env) + end + end + + def response_values(env) + {:status => env.status, :headers => env.response_headers, :body => env.body} + end + end + end +end diff --git a/spec/faraday_middleware/exceptional_response_spec.rb b/spec/faraday_middleware/exceptional_response_spec.rb new file mode 100644 index 0000000..9c89394 --- /dev/null +++ b/spec/faraday_middleware/exceptional_response_spec.rb @@ -0,0 +1,41 @@ +describe Mrkt::FaradayMiddleware::ExceptionalResponse do + before do + response = lambda { |env| + [status, {'Content-Type' => content_type}, body] + } + @conn = Faraday.new do |b| + b.use Mrkt::FaradayMiddleware::ExceptionalResponse + b.adapter :test do |stub| + stub.get('/', &response) + end + end + end + + context 'with application/json and with server error' do + let(:content_type) { 'application/json' } + let(:status) { 500 } + let(:body) { '{}' } + + it 'does nothing' do + expect(@conn.get('/').body).to eq body + end + end + + context 'with non json content-type and with server error' do + let(:content_type) { 'text/plain' } + let(:status) { 500 } + let(:body) { 'something wrong' } + + it { expect { @conn.get('/') }.to raise_error(Mrkt::Errors::Unknown) } + end + + context 'with non json content-type but with successful response' do + let(:content_type) { 'text/html' } + let(:status) { 200 } + let(:body) { 'ok' } + + it 'does nothing' do + expect(@conn.get('/').body).to eq body + end + end +end