Allow rescuing an API 404 #177

Closed
amrnt opened this Issue May 27, 2012 · 14 comments

3 participants

@amrnt

When you access an url that's not defined in the API, you get a 404 default plain text. There should be a way to override it.

@dblock
Ruby Grape member

This is just the default handler for the error in .txt format. You can get JSON format, text format or rescue explicitly. Read "Exception Handling" in the README.

Please do use the google group for further questions.

@dblock dblock closed this May 28, 2012
@amrnt

Okay. Let me state the issue better;

I've already use rescue_from, like so

  error_format :json
  rescue_from :all, backtrace: true
  rescue_from ActiveRecord::RecordNotFound do |e|
    rack_response('{ "status": 404, "message": "Not Found." }', 404)
  end

What my question was about is; When I call a URL that is not defined in the app I got Not Found Error as plain text.

I dont know if It's Grape or Rack case!

@dblock
Ruby Grape member

The first parameter in rack_response should be a hash, not a string?

rack_response({ "status": 404, "message": "Not Found." }, 404)
@amrnt

rack_response first param is a string. When I do what you said I doesn't render a valid JSON. This is the response:

{"status"=>404, "message"=>"Not Found."}

https://github.com/intridea/grape/blob/master/lib/grape/middleware/error.rb#L68

@dblock I'm not talking about this. This issue is when I access an invalid URL in my api application I got a 404 error rendered 'Not Found' with plain/text type (Grape content type default).

For example, in an api I have GET /me/filters when I have a typo like GET /me/filterrsy I got Error 404 as I said before.

@dblock dblock reopened this May 29, 2012
@dblock
Ruby Grape member

Ok. I think I understand now. Grape will return the default 404 in case the API doesn't exist and there's no handler for that that you can override. I reopened this as a feature request. In the meantime, check out my demo app. I added a way to handle the API 404 in a middleware in this commit. Depending on how you setup your app you can do the same or you can just put a middleware in front of grape that looks at the Rack's response[0] and does something else when it's a 404 (eg. serve a static file via Rack::Static like in my demo).

Does this help?

@amrnt

Thank you very much for opening it again, and for ur solution...

@amrnt

I'm not sure if this could solve the problem, to put this piece of code at the very bottom of the api application:

get '/(*:url)', :anchor => false do
  # raise 404 with json response
end

See these cases for more info:

API_SERVER/1/ --> Entity not found: /1
API_SERVER/1/links --> Not defined in the api as endpoint for /links --> Entity not found: /1/links
API_SERVER/2/links/search --> defined in the api --> returns json data as expected
API_SERVER/2/links --> Not defined in the api as endpoint for /links --> returns the response above of 404
API_SERVER/2/linkss --> Not defined in the api --> returns the response above of 404
API_SERVER/2/ --> Entity not found: /2

For my code I almost organize it as u describe here: http://code.dblock.org/modularizing-a-ror-grape-api-multiple-versions

@dblock
Ruby Grape member

I tried to implement something for this today and I am not sure what we want. There's no exception raised, this is just Rack not finding a route. So the call to call in api.rb returns [404, {"Content-Type"=>"text/html", "X-Cascade"=>"pass"}, ["Not Found"]]. We could do something where you can process every single response here, for example:

rescue_from :404 do 
 ...
end

or to be less ambiguous

on_response :404 do
 ...
end

But this is also nicely solved by inserting a middleware after grape that does the same logic.

Open to suggestions.

@dblock
Ruby Grape member

The catch-all path should look like this:

route :any, '*path' do
  error! # or something else
end

Here's a catch-all implementation with spec.

@amrnt

Awesome 👍

@dblock
Ruby Grape member

I also think specifying cascade: false may be another solution. This would tell Rails not to process further. Can you try this? Can I close this?

@amrnt

Actually I'm not using Rails... but I confirm its working as expected!

@amrnt amrnt closed this Apr 18, 2013
@xcambar

Maybe the catch-all example should go into the README for more visibility.

@dblock
Ruby Grape member

@xcambar feel free to PR

@xcambar xcambar added a commit to xcambar/grape that referenced this issue Sep 11, 2013
@xcambar xcambar refs #177 Adds a catch-all example in the README b22754e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment