Conversation With API Builders

Response should be valid JSON even when things go wrong

AU : I sent invalid JSON payload and in return I did not get valid JSON response. My mobile application crashed because I was expecting response to be valid JSON.

AB : Do you know how Rails parses JSON data.

AU : Nope.

AB : The thing is that if the payload is invalid JSON then the request does not even hit the controller.

AB : Rails attempts to parse the payload and since the payload is invalid it blows up up in the middleware stack.

AU : I see.

AU : Well we can write a custom middleware which will catch the exception and will return a valid JSON data.

AB : I have no idea how to do that.

AU : Ok. Here is my attempt to build it.

1# app/middleware/catch_json_parse_errors.rb
2
3class CatchJsonParseErrors
4
5  def initialize app
6    @app = app
7  end
8
9  def call env
10    begin
11      @app.call(env)
12    rescue ActionDispatch::ParamsParser::ParseError => exception
13      content_type_is_json?(env) ? build_response(exception) : raise(exception)
14    end
15  end
16
17  private
18
19  def content_type_is_json? env
20    env['CONTENT_TYPE'] =~ /application\/json/
21  end
22
23  def error_message exception
24    "Payload data is not valid JSON. Error message: #{exception}"
25  end
26
27  def build_response exception
28    [ 400, { "Content-Type" => "application/json" }, [ { error: error_message(exception) }.to_json ] ]
29  end
30
31end

AU : Now we need to use this middleware. Here is how we can ask Rails to use this custom middleware.

1# config/application.rb
2
3require File.expand_path('../boot', __FILE__)
4require 'rails/all'
5Bundler.require(:default, Rails.env)
6
7module Wheel
8  class Application < Rails::Application
9    config.middleware.insert_before ActionDispatch::ParamsParser,
10                                    "CatchJsonParseErrors"
11  end
12end
    ⌘F
      to navigateEnterto select Escto close
      Older
      Newer