使用机架中间件捕获无效的JSON解析错误 [英] Catching Invalid JSON Parse Errors with Rack Middleware
问题描述
我正在使用Rails 5,并且试图改善对我的API的无效JSON请求的错误处理.
I am using Rails 5 and I am trying to improve error handling for invalid JSON requests to my API.
我尝试通过抢救在控制器中进行解析来处理无效格式的JSON,但意识到Rails中间件在用户向其请求标头添加Content Type时会在我的JSON请求到达控制器之前对其进行解析.
I tried handling invalid format JSON by parsing in the controller with a rescue but realised that Rails middleware is parsing my JSON request before it hits the controller if a user adds Content Type to their request header.
我遵循以下指南: https://robots.thoughtbot.com/catching-json-parse -errors-with-custom-middleware
但是,启动服务器时出现以下错误:
However, I get the following error when starting the server:
.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/stack.rb:108:在'assert_index'中:没有这样的中间件插入之前:ActionDispatch :: ParamsParser(RuntimeError)
.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 to insert before: ActionDispatch::ParamsParser (RuntimeError)
现在,这意味着ActionDispatch :: ParamsParser没有运行.我认为它在Rails 5中已弃用,因此排除了该选项.
Now, what this means is that ActionDispatch::ParamsParser isn't running. I think that it is deprecated in Rails 5 so that rules out that option.
我还尝试在我的API控制器中使用rescue_from:
I also tried to use 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 to skip past it.
或者,如果我尝试这样做:
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
我得到:
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
迷路了,可以使用一些指导
Getting very lost, could use some guidance
推荐答案
上面的指南似乎已与Rails 5一起过时.经过一番调查,似乎不再调用以下中间件:
Seems the guide above is outdated with Rails 5. After some investigation, it seems that the following middleware is no longer called:
config/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没有在中间件堆栈中.另外,不建议将类名"用作字符串,因此您需要先提供文件,然后再传入该类.
This is because Rack::Head is in the middleware stack, but ActionDispatch::ParamsParser is not. Also, the use of Class names as strings is deprecated, so you need to require the file and then pass in the class.
我还修改了以下类,以检查env ['CONTENT_TYPE']而不是env ['HTTP_ACCEPT']
I also modified the below class to check env['CONTENT_TYPE'] instead of 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
这篇关于使用机架中间件捕获无效的JSON解析错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!