Catching invalid JSON parsing errors with Rack middleware

I am using Rails 5 and I am trying to improve error handling for invalid JSON requests for my API.

I tried to process an invalid JSON format by parsing it in the controller, but I realized that the Rails middleware parses my JSON request before it gets to the controller if the user adds a Content Type to his request header.

I followed the guide below: https://robots.thoughtbot.com/catching-json-parse-errors-with-custom-middleware

However, when starting the server, the following error appears:

.rbenv / versions / 2.3.1 / lib / ruby ​​/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/stack.rb: 108: in `assert_index ': no ​​such middleware software for insertion: ActionDispatch :: ParamsParser (RuntimeError)

Now this means that ActionDispatch :: ParamsParser is not running. I believe it is deprecated in Rails 5 to exclude this option.

I also tried using rescue_from in my API controller:

rescue_from JSON::ParserError, with: :json_error

def json_error
  render status: 400, json: {error: "Invalid JSON format in request body"}, status: :unprocessable_entity
end

However, this also did not work. It seems he skipped past him.

Or if I try this:

rescue_from JSON::ParserError, with: json_error

def json_error
  render status: 400, json: {error: "Invalid JSON format in request body"}, status: :unprocessable_entity
end

I get:

undefined local variable or method `json_error' for Api::ApiController:Class
actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb, line 46

``` ruby
   41         private
   42   
   43           def controller(req)
   44             req.controller_class
   45           rescue NameError => e
>  46             raise ActionController::RoutingError, e.message, e.backtrace
   47           end
   48   
   49           def dispatch(controller, action, req, res)
   50             controller.dispatch(action, req, res)
   51           end

Lost, you can use some recommendations

+4
source share
1 answer

, Rails 5. , :

/application.rb

config.middleware.insert_before ActionDispatch::ParamsParser, "CatchJsonParseErrors"

:

require "./lib/middleware/catch_json_parse_errors.rb"
config.middleware.insert_before Rack::Head, CatchJsonParseErrors

, Rack:: Head , ActionDispatch:: ParamsParser . , , , .

, env ['CONTENT_TYPE'] env ['HTTP_ACCEPT']

class CatchJsonParseErrors
  def initialize(app)
    @app = app
  end

  def call(env)
    begin
      @app.call(env)
    rescue ActionDispatch::ParamsParser::ParseError => error
      if env['CONTENT_TYPE'] =~ /application\/json/
        error_output = "There was a problem in the JSON you submitted: #{error.class}"
        return [
          400, { "Content-Type" => "application/json" },
          [ { status: 400, error: error_output }.to_json ]
        ]
      else
        raise error
      end
    end
  end
end
+12

Source: https://habr.com/ru/post/1663992/


All Articles