Jquery 丢架EOFError(不良内容体)

Jquery 丢架EOFError(不良内容体),jquery,ruby-on-rails,ruby,rack,Jquery,Ruby On Rails,Ruby,Rack,我们在jQuery1.11中使用Ruby2.1.2、Rails3.2.19,没有使用资产管道(因此不使用jQueryUJS,而是显式使用相关的Rails.js)。对于大多数用户来说,JQuery和其他相关的通用插件都是从GoogleCDN(包括JQuery.Form3.50)中提取出来的。受影响的web服务器是Ubuntu 14.04、Nginx 1.6和Passenger 4.x 对于生产服务器上大约10%的用户(负载似乎无关紧要),我们得到了如下堆栈转储,主要针对一个URL,但还有其他URL

我们在jQuery1.11中使用Ruby2.1.2、Rails3.2.19,没有使用资产管道(因此不使用jQueryUJS,而是显式使用相关的Rails.js)。对于大多数用户来说,JQuery和其他相关的通用插件都是从GoogleCDN(包括JQuery.Form3.50)中提取出来的。受影响的web服务器是Ubuntu 14.04、Nginx 1.6和Passenger 4.x

对于生产服务器上大约10%的用户(负载似乎无关紧要),我们得到了如下堆栈转储,主要针对一个URL,但还有其他URL:

/gems/rack-1.4.5/lib/rack/multipart/parser.rb:74 in "block in fast_forward_to_first_boundary"
/gems/rack-1.4.5/lib/rack/multipart/parser.rb:72 in "loop"
/gems/rack-1.4.5/lib/rack/multipart/parser.rb:72 in "fast_forward_to_first_boundary"
/gems/rack-1.4.5/lib/rack/multipart/parser.rb:15 in "parse"
/gems/rack-1.4.5/lib/rack/multipart.rb:25 in "parse_multipart"
/gems/rack-1.4.5/lib/rack/request.rb:336 in "parse_multipart"
/gems/rack-1.4.5/lib/rack/request.rb:201 in "POST"
/gems/actionpack-3.2.19/lib/action_dispatch/http/request.rb:237 in "POST"
/gems/actionpack-3.2.19/lib/action_dispatch/http/parameters.rb:10 in "parameters"
/gems/actionpack-3.2.19/lib/action_dispatch/http/filter_parameters.rb:31 in "filtered_parameters"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/rails3/action_controller.rb:31 in "process_action"
/gems/actionpack-3.2.19/lib/abstract_controller/base.rb:121 in "process"
/gems/actionpack-3.2.19/lib/abstract_controller/rendering.rb:45 in "process"
/gems/actionpack-3.2.19/lib/action_controller/metal.rb:203 in "dispatch"
/gems/actionpack-3.2.19/lib/action_controller/metal/rack_delegation.rb:14 in "dispatch"
/gems/actionpack-3.2.19/lib/action_controller/metal.rb:246 in "block in action"
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:73 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:73 in "dispatch"
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:36 in "call"
/gems/journey-1.0.4/lib/journey/router.rb:68 in "block in call"
/gems/journey-1.0.4/lib/journey/router.rb:56 in "each"
/gems/journey-1.0.4/lib/journey/router.rb:56 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:608 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/rack/error_collector.rb:50 in "traced_call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:55 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/rack/agent_hooks.rb:26 in "traced_call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:55 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/rack/browser_monitoring.rb:23 in "traced_call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:55 in "call"
/gems/oink-0.10.1/lib/oink/middleware.rb:17 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/warden-1.2.3/lib/warden/manager.rb:35 in "block in call"
/gems/warden-1.2.3/lib/warden/manager.rb:34 in "catch"
/gems/warden-1.2.3/lib/warden/manager.rb:34 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/best_standards_support.rb:17 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-1.4.5/lib/rack/etag.rb:23 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-1.4.5/lib/rack/conditionalget.rb:25 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/head.rb:14 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/params_parser.rb:21 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/flash.rb:242 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:210 in "context"
/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:205 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/cookies.rb:341 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/activerecord-3.2.19/lib/active_record/query_cache.rb:64 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/activerecord-3.2.19/lib/active_record/connection_adapters/abstract/connection_pool.rb:479 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/callbacks.rb:28 in "block in call"
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:405 in "_run__3807242266783802268__call__1942732928323145202__callbacks"
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:405 in "__run_callback"
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:385 in "_run_call_callbacks"
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:81 in "run_callbacks"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/callbacks.rb:27 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-1.4.5/lib/rack/sendfile.rb:102 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/remote_ip.rb:31 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/debug_exceptions.rb:16 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/show_exceptions.rb:56 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/railties-3.2.19/lib/rails/rack/logger.rb:32 in "call_app"
/gems/railties-3.2.19/lib/rails/rack/logger.rb:18 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/request_id.rb:22 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-1.4.5/lib/rack/methodoverride.rb:21 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-1.4.5/lib/rack/runtime.rb:17 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/activesupport-3.2.19/lib/active_support/cache/strategy/local_cache.rb:72 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-1.4.5/lib/rack/lock.rb:15 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/rack-cache-1.2/lib/rack/cache/context.rb:136 in "forward"
/gems/rack-cache-1.2/lib/rack/cache/context.rb:245 in "fetch"
/gems/rack-cache-1.2/lib/rack/cache/context.rb:185 in "lookup"
/gems/rack-cache-1.2/lib/rack/cache/context.rb:66 in "call!"
/gems/rack-cache-1.2/lib/rack/cache/context.rb:51 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/railties-3.2.19/lib/rails/engine.rb:484 in "call"
/gems/railties-3.2.19/lib/rails/application.rb:231 in "call"
/gems/railties-3.2.19/lib/rails/railtie/configurable.rb:30 in "method_missing"
/gems/rack-1.4.5/lib/rack/urlmap.rb:64 in "block in call"
/gems/rack-1.4.5/lib/rack/urlmap.rb:49 in "each"
/gems/rack-1.4.5/lib/rack/urlmap.rb:49 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/gems/sass-3.2.19/lib/sass/plugin/rack.rb:54 in "call"
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call"
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/rack/thread_handler_extension.rb:74 in "process_request"
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/request_handler/thread_handler.rb:141 in "accept_and_process_next_request"
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/request_handler/thread_handler.rb:109 in "main_loop"
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/request_handler.rb:448 in "block (3 levels) in start_threads"
在从1.5(!)升级到jQuery1.11之前,这个错误没有发生(或者如果发生了,那是非常罕见的)。到目前为止,我们无法在登台服务器或开发环境中重现此错误。一位技术支持人员在生产环境中看到过一次(我已经尝试过好几次),但无法在登台时进行复制(登台与生产环境相同,但资源较少)。jQueryMigrate在运行时没有显示任何问题,正如我所说的,它似乎对大多数用户都有效;在调试会话期间,似乎没有任何问题。操作系统/平台或浏览器没有明显的模式(尝试在多个日志上复制,虽然很难筛选到足以确定的模式,但日志并不表示模式)。涉及的主要URL用于表单控制器上的#新操作。我们在平台中还有其他几种形式,它们没有显示任何问题

因为我无法复制它,所以不可能给出代码片段——我不知道应该指出什么

到目前为止,我对错误的解释(基于堆栈转储中的第一行)是以下三种情况之一:

  • 内容在其他方面是正确的,但在某种程度上不是完全形成的
  • 内容的格式很差,这表明存在Ruby bug(不过 (也许是JS)
  • 糟糕的编码(我在Ruby中使用form_,甚至 将“multipart:true”作为显式输入)
  • 我看到Rack已经在4.x中处理了一个相关的多部分EOFError问题,但是我们运行的是Rails 3.2.19,它将我们锁定在一个较旧的版本上,升级到Rails 4.x在目前是不现实的。作为测试,我尝试将JQuery恢复到1.7,但似乎没有改变行为(任何旧版本,我必须删除JQuery 1.8+所需的代码更新)

    由于JQuery代码需要对我们的JS进行更改,我怀疑我错过了一些必要的JS更改,但似乎没有任何问题。附近也有一些CSS更改,但我看不出这会对事情产生什么影响(因为在我们的各种测试环境中,一切都通过了,其他更改也包括在部署中)

    我一直主要怀疑JS问题,但一些有限的生产测试(我必须在live server上小心,以免过于激进)没有显示任何线索或抛出任何似乎相关的错误

    作为背景,我在Ruby和JS方面有大约一年的经验(尽管在其他编程平台上有很多年的经验),所以这完全可能是我不熟悉的基础知识

    我很难集中精力解决这个问题。有什么诊断或解决的建议吗


    更新(10/11/14)I monkey patched
    Rack::Multipart::Parser.fast\u forward\u to\u first\u boundary
    (谢谢,Isaac Betesh!)添加日志跟踪,并确认传递给解析器的内容在到达该函数(即
    @env['Rack.input'引用的StringIO)时为空
    在多部分解析期间,不返回任何数据)。我现在的理论是,当没有多部分数据时,它错误地期望多部分数据。同样,这只会间歇性地发生,并且对于同一页面的许多其他调用都可以很好地解析。由于我们使用的是Passenger 4.x和Nginx,我没有排除缓冲问题。

    这最终解决了,我将公布发生的情况,以防对其他人有所帮助

    摘要原始代码在JS中包含一个ajaxSubmit(通过jquery.form插件),它提交了一个带有多部分/表单数据编码的表单(作为帖子)(目前为止还不错)。处理提交的rails控制器正常处理数据,然后重定向到第二个href(作为GET)。浏览器(在返回到它的
    success
    callback处理程序之前,可能仍在通过jquery.form插件进行处理)收到重定向并保留多部分/表单数据编码类型。当rack接收到仍然指定了多部分编码的GET时,它会停止,因为没有要解析的多部分数据

    很抱歉,我的作品中没有很多这方面的内容。我也不清楚为什么在较旧版本的JQuery和JQuery.form插件下可以这样做,或者为什么有时候在新的JQuery/JQuery.form下可以成功

    解决方案重构控制器,使其不再重定向,而是返回原始ajaxSubmit的
    成功
    回调处理程序的URL(作为文本呈现)。
    success
    处理程序现在对返回的URL执行AJAX GET,从而使工作流保持不变,但避免对GET请求进行任何多部分编码

    tl;博士

    在更改代码之前,我们有一个涉及Jquery.form的路径,它是这样的(代码示例并不意味着是可执行的,只是作为一个示例):

    Ruby视图(在HAML中表示提交的表单):

    Ruby控制器:


    这被重构如下(同样,只是一个示例):

    Ruby视图(在HAML中表示提交的表单):未更改

    Ruby控制器:



    这个解决方案是在当地开发人员的帮助下找到的(谢谢,Dan Axtman!),而且在monkey patched Loggin in Rack(谢谢,Isaac Betesh!)中花了不少时间。至少在这个过程中我学到了一些关于机架和猴子的补丁

    如果您无法升级Rack,因为Rails 3正在锁定版本,请尝试在to处对文件中的单个类进行monkey修补
    = form_for @someObject, html: {:multipart => true, :class => "someformclass"} do |f|
      = f.error_messages
      = hidden_field_tag :submitted, true
      =# some more fields
      %p.submits
        = f.submit "Submit", class: "submit"
    
    class OurController < ApplicationController
      layout false
      before_filter :authenticate_user!
    
      # some other actions
    
      def create
        # some processing
    
        someObject.save
        redirect_to new_feedback_path, :method => :get, :notice => "notice text", status: 303
      end
    
      # some other actions
    end
    
    $(document).on('click', '.someformclass .submit', function() {
      ...
      $(this).parents('form').ajaxSubmit({     // uses jquery.form
        ...
        beforeSubmit: function(someargs) {
          ... blah blah
        },
        success: function(responseText) {
          // ... code to display flash message
          if (typeof(window.history.pushState) == 'function') {
            window.history.pushState('html', 'sometext', $.cookie('current_url'));
            matchFiltersClass(window.location.pathname);
          } else {
            window.location.hash = '#!' + $.cookie('current_path');
            matchFiltersClass($.cookie('current_path'));
          }
          $('#main_content').html(responseText);
        }
      });
      return false;
    });
    
    class OurController < ApplicationController
      layout false
      before_filter :authenticate_user!
    
      # some other actions
    
      def create
        # some processing
    
        someObject.save
        flash[:notice] = 'notice text'    # NEW LINE
        render text: new_feedback path, status: accepted  #CHANGED LINE
      end
    
      # some other actions
    end
    
    $(document).on('click', '.someformclass .submit', function() {
      ...
      $(this).parents('form').ajaxSubmit({     // uses jquery.form
        ...
        beforeSubmit: function(someargs) {
          ... blah blah
        },
        success: function(responseText) {
          // ... code to display flash message
          $.get(responseText, function(data) {       // NEW LINE
            if (typeof(window.history.pushState) == 'function') {
              window.history.pushState('html', 'sometext', $.cookie('current_url'));
              matchFiltersClass(window.location.pathname);
            } else {
              window.location.hash = '#!' + $.cookie('current_path');
              matchFiltersClass($.cookie('current_path'));
            }
            $('#main_content').html(responseText);
          });       // NEW LINE
        }
      });
      return false;
    });