缺失模板 blogs/index 在 Ruby on Rails 项目中。

15

在我的一个项目中,我时不时地会遇到这个异常:

ActionView::MissingTemplate: 缺少模板 blogs/index,包含 {:handlers=>[:rxml, :erb, :builder, :rjs, :haml, :rhtml], :formats=>["image/jpeg", "image/pjpeg", "image/png", "image/gif"], :locale=>[:en, :en]},视图路径为 "/var/www/keeponposting/releases/20110403083651/app/views"

似乎有人在请求一个不是图片的 URL 上:

HTTP_ACCEPT "image/jpeg, image/pjpeg, image/png, image/gif"

你有什么想法怎样处理它?我是否需要实现对其中一个处理程序并返回 "" 来摆脱这些异常,或者有更好的处理方法?

现在我也收到了这个异常:

ActionView::MissingTemplate: 缺少模板 blogs/index,包含 {:formats=>["text/*"], :handlers=>[:rjs, :haml, :rhtml, :erb, :rxml, :builder], :locale=>[:en, :en]},视图路径为 "/var/www/keeponposting/releases/20110415040109/app/views"

无论请求的格式是什么,是否有一种方法发送 HTML 内容?

6个回答

13

我同意封锁冒犯性的机器人,但如果你真的想强制响应格式,可以添加一个before_filter并设置request.format = :html,像这样:

before_filter :force_request_format_to_html

private

def force_request_format_to_html
  request.format = :html
end

1
当然,这仅适用于您的应用程序不接受其他格式的情况下!不支持常见格式JSON或XML。 - ipd
1
在我的情况下,Googlebot正在访问一个搜索结果页面,这是我们想要的,但格式没有被设置。我们的搜索操作也允许json请求,所以强制 :html 是行不通的。但简单的条件可以解决问题:if request[:format].blank? request.format = :html end - Levi Rosol

8

我使用了这个新的Rails 3.1选项(几分钟前)来解决这个问题,目前看起来一切正常:

config.action_dispatch.ignore_accept_header = true

此Rails问题所述,需在config/application.rb中添加内容。

我在Rspec请求测试中进行了测试(使用Capybara):

it "should not break with HTTP_ACCEPT image/*;w=320;h=420 from iPhone" do
  page.driver.header "Accept", "image/*;w=320;h=420"
  visit "/some/path"
  page.should have_content("Some content")
end

1
很好,但是有没有任何好的浏览器在做这件事情,或者这是一次攻击、黑客尝试、DOS或机器人? - Kazim Zaidi

6

这里是一个更严格的响应,建议来自purp第4127个问题的讨论中。

class FooController
  rescue_from  ActionView::MissingTemplate, :with => :missing_template

  def missing_template
    render :nothing => true, :status => 406
  end
end

5

我建议在你的应用控制器中拯救MissingTemplate,并记录Referrer标头以查看是什么触发了此请求。你永远不知道,可能是你自己应用程序中的某个不常见的部分!

另一方面,如果你确信这是由机器人引起的,请考虑将有问题的URL添加到robots.txt文件中。例如:

User-Agent: YandexImages
Disallow: /your/failed/path

将“your/failed/path”替换为机器人遇到问题的路径。如果机器人在整个站点上都无法正常访问,您可以禁止该特定机器人访问整个站点:

User-Agent: YandexImages
Disallow: /

我认为这种方法比专门实现处理程序来抑制看起来行为不良的机器人的错误更加简洁和轻便。


我考虑过这个问题,但在Hoptoad中报告的异常中,通常会获取referrer,但这次没有,所以我认为没有referrer。用户代理是Mozilla/5.0(兼容;YandexImages/3.0;+http://yandex.com/bots),因此我认为它是一个迷路的小机器人。 - pupeno
也许值得将这些信息(以及实际访问的路径)添加到问题中?我已经编辑了答案,建议使用robots.txt排除机器人访问相关区域。 - Paul Russell
阻止一个迷失的小机器人可能会修补这个小错误。有什么方法可以强制Rails应用程序响应类型? - TelegramSam
我们从移动用户那里获取这些信息,而不仅仅是机器人。使用旧的手机浏览器并发送一个 text/* 的 HTTP_ACCEPT 头的人也会发送这些信息。 - ipd

0
我做了这个: 在我的控制器中,我放置了一个前置过滤器:
def acceptable_mime_type
  unless request.accepts.detect{|a| a == :json || a == :html} || request.accepts.include?(nil)
    if request.accepts.detect{|a| a.to_s().include?("*/*")}
      ActionDispatch::Request.ignore_accept_header = true
    else
      render text: "Unacceptable", status: 406
      false
    end
  end
end

它检查我的支持类型(例如json、html)和nil(nil渲染默认html),然后如果这些mime类型不受支持,它会检查标题中的“/”。如果找到了它,我会强制Rails通过忽略接受标头来呈现默认MIME类型。

为了在rspec中测试这个,我不得不这样做:

describe 'bad header' do
  describe 'accept' do
    let(:mimeTypes) { ["application/text, application/octet-stream"] }

    it 'should return a 406 status code' do
      request.accept = mimeTypes
      get 'index'
      expect(response.response_code).to eq 406
    end

    describe 'with */* included' do
      it 'should return a 200 status code' do
        request.accept = ["*/*"] + mimeTypes
        get 'index'
        expect(response.response_code).to eq 200
      end
    end
  end
end

由于某些原因,我在使用这里描述的方法尝试正确发送接受标头时遇到了问题。但是我发现,如果将request.accept设置为一个数组,那么我的测试都通过了。很奇怪,但现在我要继续解决下一个问题了。

0
formats: [:html]添加到渲染中。
def action
  render formats: [:html]
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接