Ruby

Rails Web Service Error handling

General Error Handling

Errors in Rails application controllers are handled using ActionController::Rescue methods

As well there is a nice recipe on sending exception to the creator by email in Rails Recipes book, Recipe 47, page 209

Providing a default error handling routine for web services

Problem

Hide a stack trace of the exceptions thrown as well as the reason of error from the user, so that a potential attacker could not learn about the structure of the system and the errors he is causing.

Discussion

With web services it is a bit more difficult that a web application. As the method calls to rails web services are handled by the

 RAILS_ROOT/vendor/rails/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb

which catches all exceptions (before they get to the Rails exception handling mechanism). When an exception is called the log_error method of the controller is called. If one wishes to check what is said above he could either look at the dispatcher code or throw an exception in log_error all the time. In case of the exception the dispatcher cannot cope with it and passes it to the default rails mechanism.But that is not a really nice solution as it involves throwing a lot of exceptions every time some error needs to be logged.Another way is to intercept the error handling routine of the dispatcher. After it has called the logging routine it calls the internal send_web_service_error_response(ws_request, exception) method.Therefore the solution becomes rather trivial, one should just intercept the method call and replace the original exception with the default one

Solution

Insert this code into the constructor of the controller:


  def initialize()
    # other initialisation code
    @ex = StandardError.new("An error occurred while processing your request")
    # This line is mandatory for the ruby client to work as
    # it expects a backtrace
    @ex.set_backtrace([])
  end

Add this method definition to the controller:


  # Overrides ActionWebService::Dispatcher::ActionController::
  # InstanceMethods.send_web_service_error_response
  def send_web_service_error_response(ws_request, exception)
    # Internal logging routine, if any, should go here

    # Swapping the exception, which was thrown for the default exception
    super(ws_request, @ex)
  end
Standard

One thought on “Rails Web Service Error handling

  1. Joe says:

    Very cool. I had a question about the code. If I declare my webservice like so in the controller.

    web_service(:foo) { FooService.new }

    and the service is performing a before_invocation call, is it possible to return the exception thrown by the before_invocation method to the controller? Thanks again!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s