【问题标题】:Suppressing ActionView::MissingTemplate exception for Rails 3.x抑制 Rails 3.x 的 ActionView::MissingTemplate 异常
【发布时间】:2012-03-10 02:49:11
【问题描述】:

从 Rails 3.0 开始,我不时收到这样的异常通知:

ActionView::MissingTemplate: Missing template [...] with {:locale=>[:en],
  :formats=>[:text], :handlers=>[:erb, :builder, :haml]}. Searched in: * [...]

例如,像http://example.com/some/path/robots.txt 这样的任意手写 URL 会引发错误。不好玩。

我很久以前就在这个ticket中报告了这个问题,并且一直在使用这里提到的补丁,但问题仍然存在。

https://rails.lighthouseapp.com/projects/8994/tickets/6022-content-negotiation-fails-for-some-headers-regression

在这篇博文中提出了修复建议,

http://trevorturk.wordpress.com/2011/12/09/handling-actionviewmissingtemplate-exceptions/

要使用这个:

respond_to do |format|
  format.js
end

但这对我来说感觉不对,因为我对使用多种格式重载动作不感兴趣。在我的应用中,HTML 和 JSON API 有单独的 URL,所以简单的 render 就足够了。

我应该直接吞下rescue_from ActionView::MissingTemplate 的异常并自己返回 406 吗?

有没有更好的方法来处理这种情况?

或者我可以这样问 - 首先,在生产中提出这种异常是否有任何实际用途?

【问题讨论】:

    标签: ruby-on-rails templates exception


    【解决方案1】:

    如果您不需要格式化路由,您可以在路由规范中使用 :format => false 禁用它们,例如

    get '/products' => 'products#index', :format => false
    

    这将生成一个 RoutingError 并转换为 404 Not Found。或者,您可以将其限制为多种预定义格式:

    get '/products' => 'products#index', :format => /(?:|html|json)/
    

    如果您想要一个格式化的 url,但希望它限制为单一格式,那么您可以这样做:

    get '/products.json' => 'products#index', :format => false, :defaults => { :format => 'json' }
    

    在生产环境中引发此错误的正当理由有很多——例如,部署中的文件丢失,或者您可能想要通知有人试图破解您的应用程序的 url。

    【讨论】:

    • 谢谢。在这一点上,我的结论是大部分问题出在:format 上。有没有办法完全禁用:format?我不想在每个定义中都添加:format => false
    • @kenn 您可以在示例中使用 format: false 。但更好的选择是使用 format: 'html' 如果你想提供 html 文件。 scope format: 'html' do # your routes end
    • @gamecreature 谢谢!令人惊讶的是,这个问题在 6 年后仍然存在。
    【解决方案2】:

    最适合我的是application_controller.rb

    rescue_from ActionView::MissingTemplate, with: :not_found
    

    【讨论】:

    • 这是有风险的,因为如果您输入模板名称,您将不会在生产中看到错误。
    【解决方案3】:

    经过一些来源潜水后,我找到了另一种方法。将其放入初始化程序中。

    ActionDispatch::ExceptionWrapper.rescue_responses.merge! 'ActionView::MissingTemplate' => :not_found
    

    【讨论】:

      【解决方案4】:

      如果您有一个只会以一种格式提供的资源,并且您想忽略任何 Accept 标头并简单地强制它始终输出默认格式,您可以从模板文件名中删除该格式。例如,如果你有:

      app/views/some/path/robots.txt.erb
      

      你可以改成简单的

      app/views/some/path/robots.erb
      

      一些学派会说这是一件坏事,因为您返回的数据格式与请求的格式不同,但实际上存在很多行为不端的用户代理,并非每个网站都会仔细过滤内容类型请求,并且始终返回相同的东西是可预测的行为,所以我认为这是一个合理的方法。

      【讨论】:

        【解决方案5】:

        尝试添加

        render nothing: true
        

        在你的方法结束时。

        【讨论】:

          【解决方案6】:

          如果有特定的路径会定期被调用并产生错误——它们是相同的一组被定期调用的 url(即 robots.txt 或其他)——如果可以的话,最好的办法是从一开始就消除它们访问您的 Rails 服务器。

          如何执行此操作取决于您的服务器堆栈。一种方法是在将 url 传递到 rails 之前直接在 RACK 中阻止它。

          另一种方法可能是在 NGINX 或 Unicorn 中阻止它,具体取决于您为应用使用的 Web 侦听器。

          我建议您对此进行调查,然后返回并在此处发布一个关于“如何使用 Rack 阻止 URL?”的附加问题(或 unicorn 或 nginx 或任何您认为阻止访问有意义的地方。

          【讨论】:

          • 我不认为这是处理这类问题的可持续方式,因为这个问题的本质不是重复的,而是随机的。您会不时看到非常奇怪的 URL 被点击。我确实有一些 Nginx 设置来限制或丢弃不需要的请求,但这张票不是它。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-03
          • 2011-11-10
          • 1970-01-01
          • 2016-08-20
          • 1970-01-01
          相关资源
          最近更新 更多