6

If we request a bogus image file, Rails generates an internal 500 server error instead of a 404. See the log below.

Here is the line in routes.rb that catches 404s:

# Catches all 404 errors and redirects
match '*url' => 'default#error_404'

Other unknown URLs are handled correctly with 404s. What is different for image files and URLs with file extensions?

Started GET "/images/doesnotexistyo.png" for 71.198.44.101 at 2013-03-08 07:59:24 +0300
Processing by DefaultController#error_404 as PNG
  Parameters: {"url"=>"images/doesnotexistyo"}
Completed 500 Internal Server Error in 1ms

ActionView::MissingTemplate (Missing template default/error_404, application/error_404 with {:locale=>[:en], :formats=>[:png], :handlers=>[:erb, :builder]}. Searched in:
  * "/home/prod/Prod/app/views"
Crashalot
  • 33,605
  • 61
  • 269
  • 439

3 Answers3

5

The problem is that the error_404 method inside the Default controller can't handle requests in png format. When you ask for say, a JSON response, you could build an URL similar to:

/controller/action.json

And inside the action you would have something like

def action
  respond_to do |format|
    format.html # Renders the default view
    format.json { render :json => @model }
    format.xml { render :xml => @model }
  end
end

As you can see, it's specified how to handle a JSON and an XML request, but since there's no format.png, the action can't handle the .png format. Add this:

format.png # Handle the request here...

Hope it helps :)

Edit

Add this to redirect to your 404 handler:

def error_404
  respond_to do |format|
    format.html
    format.png { redirect_to :controller => 'default', :action => 'error_404' }
  end
end

Cheers :)

Edit2

Use this code to catch all kinds of requests:

def error_404
  respond_to do |format|
    format.html { render :not_found_view }
    format.all { redirect_to controller: 'default', action: 'error_404' }
  end
end

Replace :not_found_view with your 404 page. This will render the 404 page for html requests, and redirect to self (with html format) for any other kind of request.

Hope it helps :)

sergelerator
  • 546
  • 2
  • 7
  • thanks! if it's not a HTML format, can we force it to render the HTML view and show the correct 404 page? – Crashalot Mar 08 '13 at 20:30
  • Edited my answer, hope it helps :D – sergelerator Mar 08 '13 at 22:26
  • How we can set up a catch-all? In other words, if we want to catch any file extension (e.g., .jpg, .gif) without specifying each one individually, how would we approach it? – Crashalot Mar 11 '13 at 03:56
  • format.any doesn't work when we try to render the 404 action. – Crashalot Mar 11 '13 at 04:30
  • Sorry, my bad. `format.any` expects a bunch of formats as params and then a block to handle those formats, you can read about it [here](http://api.rubyonrails.org/classes/ActionController/MimeResponds.html#method-i-respond_to). I'll get back to you as soon as I find a catch-all solution. – sergelerator Mar 11 '13 at 17:04
0

What is DefaultController? That controller is dealing with the 404, instead of Rails default response:

ActionController::RoutingError (No route matches [GET] "/images/doesnotexistyo.png"):

So find out this controller, error_404 is being executed and no template default/error_404 was found, hence the 500 error.

You probably have a code similar to this somewhere in your code:

rescue_from ActiveRecord::RecordNotFound, :with => :error_404
Leonel Galán
  • 6,993
  • 2
  • 41
  • 60
  • we updated the q with a line in routes.rb that catches 404. the question is why does it work for some URLs and not ones with file extensions (images in particular)? – Crashalot Mar 08 '13 at 19:45
  • What's the content of the method error_404? The method is reaching it's end and attempting to render a view with erb or builder, using the provided format: png. Unless you have a error_404.png.erb or error_404.png.builder you will see this error the way the app is setup right now. – Leonel Galán Mar 08 '13 at 19:48
  • ahhh, i see. what's the right way to handle this (and 404s in general) in 3.2.12? to answer your question, error_404 is an empty action that just renders the corresponding .html.erb view. – Crashalot Mar 08 '13 at 19:54
0

Maybe not for you, but since I do some final checks for pages dynamically in my controllers, I just follow all my 404'ing with one to handle non-html files:

format.all { render :status => 404, :nothing => true }
Alien Life Form
  • 581
  • 1
  • 7
  • 15