【问题标题】:Weird "406 not acceptable" error奇怪的“406 不可接受”错误
【发布时间】:2009-09-12 06:17:41
【问题描述】:

当我尝试通过 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,但我在做正确的 beforeSend 东西:

  $.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

【问题讨论】:

标签: ruby-on-rails


【解决方案1】:

我破案了!

我在 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 中的一个错误?

【讨论】:

  • 这不是错误,而是预期行为:Rails 使用 Accept Headers 和 format 参数来确定是否使用 html、javascript、xml、json 或其他内容进行响应。因此,在您的情况下,从未调用 format.js {} 块,因为 Rails 认为您想要格式为“raw”的东西,而不是格式为“js”的东西。
  • 你说得对——我应该注册一个 Markdown mimetype (stackoverflow.com/questions/2456219/…) 并添加一个 format.markdown
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    这发生在我使用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 的控制器。如果控制器缺少格式指令来指定它可以返回 JSON 作为响应,这也可能导致 406 错误。

    【讨论】:

      【解决方案4】:

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

      //= require jquery_ujs
      

      【讨论】:

        【解决方案5】:

        您可以尝试不设置 Accept Header 吗?即使没有 Accept 标头,它也应该可以正常工作。

        【讨论】:

          【解决方案6】:

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

          format.js   { render :nothing => true }  
          

          【讨论】:

            【解决方案7】:

            如果您使用的是 jRails,这会给我带来很多问题,这是我的 application.js 文件:

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

            【讨论】:

            • 我实际上什至没有使用 jRails(只是普通的 jQuery)
            【解决方案8】:

            这是通过 Apache 提供的吗?您可能想看看http://forums.alwayswebhosting.com/showthread.php?p=8381,它描述了安全策略干扰请求的场景。

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

            【讨论】:

            • 作为响应的一部分,您打算发送回客户端的数据是什么样的?是 JSON、HTML、JavaScript?
            • 我只是发回文本(准确地说是降价),尽管即使我注释掉 format.js 块的内容,这在 Javascript 中也不起作用(所以我不认为我发送的是相关的)。此外,这是通过 Mongrel 在我的本地机器上发生的
            • 如果您不发回 javascript,则不需要“text/javascript”请求标头。也许“text/plain”会更适合您的需求。
            【解决方案9】:

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

            【讨论】:

              【解决方案10】:

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

              respond_to do |format|
                format.html 
              end
              

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

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

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

              现在两个浏览器都很好。

              【讨论】:

                【解决方案11】:

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

                【讨论】:

                  【解决方案12】:

                  这里的另一个阴险“陷阱”是如果您使用 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。我们不会谈论我在此上花费了多少时间。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-12-07
                    • 1970-01-01
                    • 2015-03-17
                    • 1970-01-01
                    • 2017-04-08
                    • 2013-12-18
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多