问题
I develop a rest webservice that answers in json. But when some (not all) exceptions are thrown, I am unable to catch them, and rails render an htlm, which is not a valid response for all my clients. The problem comes if an exception is raised in a method called by this catch all:
rescue_from Exception, with: :render_unkown_error
I have to admit, raising an exception in a last chance catch all is very very critical, but I wonder:
Is there a way to totally dismiss all rails response in case of such errors instead of returning an html page containing the stack trace ?
EDIT:
In fact this problems also comes for an undefined property in my controller:
ActionController::RoutingError (undefined local variable or method `truc' for V2::Model3dsController:Class):
app/controllers/v2/model3ds_controller.rb:8:in `<class:Model3dsController>'
app/controllers/v2/model3ds_controller.rb:4:in `<module:V2>'
app/controllers/v2/model3ds_controller.rb:3:in `<top (required)>'
even if I have the following rescue in my base controller:
rescue_from ActionController::RoutingError, with: :render_routing_error
EDIT2:
I have the same kind of problem if the user of my webservice send malformatted parameters to my webservice. Since the execution flow do not pass through my code, the exception is not handled:
Started POST "/users" for XXX.XXX.XXX.XXX at 2013-05-07 11:11:27 +0000
Error occurred while parsing request parameters.
Contents:
MultiJson::LoadError (795: unexpected token at 'url=http%3A%2F%2Ftest.test.com%2Fusers'):
json (1.7.7) lib/json/common.rb:155:in `parse'
json (1.7.7) lib/json/common.rb:155:in `parse'
multi_json (1.7.2) lib/multi_json/adapters/json_common.rb:16:in `load'
multi_json (1.7.2) lib/multi_json/adapter.rb:19:in `load'
multi_json (1.7.2) lib/multi_json.rb:120:in `load'
activesupport (3.2.13) lib/active_support/json/decoding.rb:15:in `decode'
actionpack (3.2.13) lib/action_dispatch/middleware/params_parser.rb:47:in `parse_formatted_parameters'
actionpack (3.2.13) lib/action_dispatch/middleware/params_parser.rb:17:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/flash.rb:242:in `call'
rack (1.4.5) lib/rack/session/abstract/id.rb:210:in `context'
rack (1.4.5) lib/rack/session/abstract/id.rb:205:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/cookies.rb:341:in `call'
activerecord (3.2.13) lib/active_record/query_cache.rb:64:in `call'
activerecord (3.2.13) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (3.2.13) lib/active_support/callbacks.rb:405:in `_run__3866502263790514870__call__1366634820855087578__callbacks'
activesupport (3.2.13) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.13) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
activesupport (3.2.13) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (3.2.13) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/reloader.rb:65:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
railties (3.2.13) lib/rails/rack/logger.rb:32:in `call_app'
railties (3.2.13) lib/rails/rack/logger.rb:16:in `block in call'
activesupport (3.2.13) lib/active_support/tagged_logging.rb:22:in `tagged'
railties (3.2.13) lib/rails/rack/logger.rb:16:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/request_id.rb:22:in `call'
rack (1.4.5) lib/rack/methodoverride.rb:21:in `call'
rack (1.4.5) lib/rack/runtime.rb:17:in `call'
activesupport (3.2.13) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
actionpack (3.2.13) lib/action_dispatch/middleware/static.rb:63:in `call'
railties (3.2.13) lib/rails/engine.rb:479:in `call'
railties (3.2.13) lib/rails/application.rb:223:in `call'
railties (3.2.13) lib/rails/railtie/configurable.rb:30:in `method_missing'
thin (1.5.1) lib/thin/connection.rb:81:in `block in pre_process'
thin (1.5.1) lib/thin/connection.rb:79:in `catch'
thin (1.5.1) lib/thin/connection.rb:79:in `pre_process'
eventmachine (1.0.3) lib/eventmachine.rb:1037:in `call'
eventmachine (1.0.3) lib/eventmachine.rb:1037:in `block in spawn_threadpool'
Rendered /home/ubuntu/.rvm/gems/ruby-2.0.0-p0@websrv2.4.0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.8ms)
Rendered /home/ubuntu/.rvm/gems/ruby-2.0.0-p0@websrv2.4.0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.3ms)
Rendered /home/ubuntu/.rvm/gems/ruby-2.0.0-p0@websrv2.4.0/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (11.7ms)
回答1:
What you want is exceptions_app.
Rails exceptions_app is basically a configuration option for rails which defaults to the middleware PublicExceptions in ActionDispatch.
This is pretty much what exceptions_app defaults to if none provided:
PublicExceptions
This is the public_exceptions middleware that handles displaying the public 500.html and 400.html
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
Show Exceptions
This is part of the middleware that shows exceptions on development/production
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/show_exceptions.rb#L26
Defaults
Here's what it defaults to when you initialize an application
https://github.com/rails/rails/blob/master/railties/lib/rails/application.rb#L391-L393
You can exchange it for an app or route it to your own rails apps like this:
config/application.rb
config.exceptions_app = self.routes
Then in your routes you would match routes like this
routes.rb
match "/500" => "errors#exception"
match "/404" => "errors#not_found"
So you would then have a ErrorsController that would have these actions and handle the response to them.
errors_controller.rb
class ErrorsController < ApiController
def exception
render json: {error: "Internal Error"}, status: 500
end
def not_found
render json: {error: "Not Found"}, status: 404
end
end
来源:https://stackoverflow.com/questions/16108286/disable-all-html-exception-rendering-in-rails