Reputation: 3343
Starting with Rails 3.0, from time to time, I've been receiving an exception notification like this:
ActionView::MissingTemplate: Missing template [...] with {:locale=>[:en],
:formats=>[:text], :handlers=>[:erb, :builder, :haml]}. Searched in: * [...]
For instance, an arbitrary hand-written URL like http://example.com/some/path/robots.txt raises the error. Not fun.
I reported the problem in this ticket quite a long ago, and been using the patch mentioned here, but the problem persists.
A fix is suggested in this blog post,
http://trevorturk.wordpress.com/2011/12/09/handling-actionviewmissingtemplate-exceptions/
To use this:
respond_to do |format|
format.js
end
But it doesn't feel right to me, as I'm not interested in overloading an action with multiple formats. In my app, there are separate URLs for HTML and JSON API, so simple render
should be sufficient.
Should I just swallow the exception by rescue_from ActionView::MissingTemplate
and return 406 myself?
Is there a better way to handle this situation?
Or I can ask this way - in the first place, is there any real-world usefulness in raising this kind of exception on production?
Upvotes: 13
Views: 5228
Reputation: 475
Best that worked for me is in application_controller.rb
:
rescue_from ActionView::MissingTemplate, with: :not_found
Upvotes: 4
Reputation: 860
After some source diving I found another way. Put this in an initializer.
ActionDispatch::ExceptionWrapper.rescue_responses.merge! 'ActionView::MissingTemplate' => :not_found
Upvotes: 2
Reputation: 17246
If you have a resource that will only ever be served in one format and you want to ignore any Accept header and simply force it to always output the default format you can remove the format from the template filename. So for instance, if you have:
app/views/some/path/robots.txt.erb
You can change it to simply
app/views/some/path/robots.erb
Some schools of thought would say this is a bad thing since you are returning data in a different format from what was requested, however in practice there are a lot of misbehaving user agents, not every site carefully filters content type requests, and consistently returning the same thing is predictable behavior, so I think this is a reasonable way to go.
Upvotes: 1
Reputation: 13404
If there are specific paths that periodically get called that generate errors -- and they are the same set of urls that get called regularly (i.e., robots.txt or whatever) -- the best thing to do if you can is to eliminate them from hitting your rails server to begin with.
How to do this depends on your server stack. One way to do it is to block this in directly in RACK prior to having the url passed into rails.
Another way may be to block it in NGINX or Unicorn, depending on which web listener you're using for your app.
I'd recommend looking into this and then coming back and posting an additional question here on 'How to Block URL's using Rack?" (Or unicorn or nginx or wherever you think it makes sense to block access.
Upvotes: 0
Reputation: 981
If you've no need for formatted routes you can disable them with :format => false in your route specification, e.g.
get '/products' => 'products#index', :format => false
This will generate a RoutingError which gets converted to a 404 Not Found. Alternatively you can restrict it to a number of predefined formats:
get '/products' => 'products#index', :format => /(?:|html|json)/
If you want a formatted url but want it restricted to a single format then you can do this:
get '/products.json' => 'products#index', :format => false, :defaults => { :format => 'json' }
There are a number of valid reasons to raise this error in production - a missing file from a deploy for example or perhaps you'd want notification of someone trying to hack your application's urls.
Upvotes: 6