Grapes: rescue from invalid JSON

At first:

I use grapes to create my API (Rails 4). When someone sends an invalid JSON body (for example, they forgot the last one } ), the following error occurs:

 ActionDispatch::ParamsParser::ParseError (795: unexpected token at '{"foobar": 1234 ') 

I tried it with the grape option rescue_from :all , but this does not work. Inside the stacktrace, I do not see how the grape pearl is involved. This error seems to be selected from actionpack:

  .gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:53:in `rescue in parse_formatted_parameters' .gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:32:in `parse_formatted_parameters' .gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:23:in `call' 

But what is the best way to catch these errors, return the 400: Bad Request errors, and include the unexpected token at '{"foobar": 1234 message in the json response?

The second:

I tried to verify this with RSpec, but was not lucky enough to send a raw request with invalid JSON. I tried this with

 post "/my_route", '{some invalid json' 

but this does not cause an error from above. I thought that since Rails 4, the second parameter passed as a string, is treated as a raw body?

+5
source share
1 answer

Unfortunately, ActionDispatch works much earlier than it ever gets to the controller, so you cannot do this with Grape (AFAIK).

We ran into this problem and found a great article from the Thoughtbot guys on this.

Use the curb gem to make trembling calls:

 require 'curb' it 'sends poorly formatted json' do broken_json = %Q|{"notice":{"title":"A sweet title"#{invalid_tokens}}}| resp = Curl.post("http://#{host}:#{port}#{path}", broken_json) expect(resp.response_code).to eq 500 end 

Thoughtbot recommends writing a middleware class to collect future JSON parsing errors as follows:

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

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


All Articles