奇怪的“406不可接受”的错误

时间:2009-09-12 06:17:42

标签: ruby-on-rails

当我尝试通过Javascript点击此操作时,出现406 Not Acceptable错误:

  def show
    @annotation = Annotation.find_by_id(params[:id])

    respond_to do |format|
      format.html {
         if @annotation.blank?
           redirect_to root_path
         else
           redirect_to inline_annotation_path(@annotation)
         end
       }

       format.js {
         if params[:format] == "raw"
           render :text => @annotation.body.to_s
         else
           render :text => @annotation.body.to_html
         end
       }
    end
  end

这是来自jQuery,但我在发送之前做的正确:

  $.ajaxSetup({ 
    beforeSend: function(xhr) {
      xhr.setRequestHeader("Accept", "text/javascript");
    },
    cache: false 
  });

以下是我的请求标题:

Host    localhost:3000
User-Agent  Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3
Accept  text/javascript
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive  300
Connection  keep-alive
X-Requested-With    XMLHttpRequest
Content-Type    application/x-www-form-urlencoded

12 个答案:

答案 0 :(得分:30)

我破案了!

我在我的get请求中发送了一个format参数,以告诉服务器向我发送markdown而不是HTML。这是我的Javascript:

$.get("/annotations/" + annotation_id, {format: 'raw'}, function(data) {
});

然后我在format.js块中寻找这个参数:

   format.js {
     if params[:format] == "raw"
       render :text => @annotation.body.to_s
     else
       render :text => @annotation.body.to_html
     end
   }

但显然format参数会混淆respond_to块。我将其从{format: 'raw'}更改为{markdown: 'true'}并且有效。

我猜这是Rails中的一个错误?

答案 1 :(得分:5)

在您的respond_to块中包含“format.js”

答案 2 :(得分:5)

当使用HTTPRiot从iPhone应用程序连接到JSON呈现Web应用程序时,发生了这种情况。似乎问题是由于Rails期望Accept HTTP标头很好,很舒服。因此,我使用Firefox的LiveHTTPHeaders扩展来查看没有406的标题。无论如何,有效的Accept字符串是:

text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

我要研究的另一个领域是产生JSON的控制器。如果控制器缺少一个format指令来指定它可以返回JSON作为响应,那也可能导致406错误。

答案 3 :(得分:3)

检查您的application.js是否需要jquery_ujs

//= require jquery_ujs

答案 4 :(得分:2)

您可以在不设置Accept Header的情况下尝试吗?即使没有Accept标题,它也应该可以正常工作。

答案 5 :(得分:2)

只需在控制器操作方法格式块中使用此代码:

format.js   { render :nothing => true }  

答案 6 :(得分:0)

这是通过Apache提供的吗?您可能需要查看http://forums.alwayswebhosting.com/showthread.php?p=8381,其中介绍了安全策略干扰请求的情况。

编辑:上面引用的网址主张在整个网站上关闭请求嗅探安全策略,这会使网站容易受到攻击。在.htaccess中将SecFilterEngine选项设置为Off,这是URL中规定的,应该只对问题的来源进行归零。它不应被视为长期解决方案。

答案 7 :(得分:0)

如果您使用的是jRails,这对我来说会造成很多问题,这是我的application.js文件:

$(document).ready(function () {
    $.ajaxSetup({
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Accept", "text/javascript, text/html, application/xml, text/xml, */*");
        }
    });
});

答案 8 :(得分:0)

对我来说,一个简单的before_filter限制了一个呈现js文件的动作,一旦我添加了:except => [:action]到before_filter块就可以了。

答案 9 :(得分:0)

当我忘记将:remote => true添加到我的Ajax表单时,我遇到了这个问题。

答案 10 :(得分:0)

我正在调用js格式的url但是在控制器中有这个:

respond_to do |format|
  format.html 
end

这在Safari中运行良好,但不适用于Firefox。

自然我错过了什么,应该是:

respond_to do |format|
  format.html
  format.js
end

现在两个浏览器都很好。

答案 11 :(得分:0)

另一个阴险的" Gotcha"这里是你用一个form_for调用你的控制器意外地有一个额外的不必要的参数。 Rails可以将附加参数解释为格式请求,并且您将获得406。

示例:

= form_for parking_permit, url: permit_group_parking_permits_path(@permit_group.id, useless_id), method: :get do |f| ...

在上面的例子中,你RAKE ROUTES并确定permit_group_parking_permits_path除了permit_group id之外不需要任何东西......

如果您看到正在调用您的方法,例如 /model/action.1?blahblahblah 那么" .1"是你的小费。

这将返回406.我们不会谈论我花了多少时间在这上面。