Search
⌘K
    to navigateEnterto select Escto close

    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
    Previous
    Next