Search code examples
ruby-on-railsjsonerror-handlingroutesrails-api

render JSON formatted response when accessing undefined routes in Rails API service


Here is the situation:

If a user try to access my rails-api service with an undefined route, rails would catch an exception and render an html with Routing Error: to the browser.

But what i want my rails-api service to perform is that it can catch any errors like this and return a json-formatted error info to the request source, like below:

# if i visit a route which is undefined in my config/routes.rb like this:

HTTP.get('http://localhost:3000/api/v1/route/of/undefined')

# what i want it to render to the page is:

{status: 404, err_msg: 'route of undefined, please check again.'}

Before i take my action, i find that Rails matches a request with a route happens before it initializes a controller, thus if i add rescue_from to my ApplicationController, ApplicationController has no chance to rescue the exception.

also, i added line below to my project:

# config/application.rb
config.exceptions_app = self.routes

# config/environments/development.rb
config.consider_all_requests_local = false

what next should I do? i searched a lot but could not find an answer to solve this problem. especially in an rails api service.


Solution

  • If you want to render same response for all undefined routes, you can do something like below,

    match '*path', to: "error_controller#handle_root_not_found", via: [:get, :post]
    

    add this line at the end of route.rb. After that generate error_controller and define handle_root_not_found method there which will render your custom response.

    def handle_root_not_found
       render json: { message: "route not found"}, status: 404
    end
    

    So what will happen in this scenario is when you request a particular route, it will scan route file from top to bottom manner. If that route will be found then it will redirect you to that. If route is not found untill match '*path' line then this line will redirect it to handle_root_not_found method which will render our custom response.