ActionController ::与SSE一起生效无法正常工作

我正在尝试在一个项目中使用Rails 4.0.1中的直播,但我发现问题……

我有这个动作:

def realtime_push response.headers['Content-Type'] = 'text/event-stream' sse = SSE.new(response.stream) d = Domain.find(params[:domain_id]) begin loop do backlinks = d.backlinks.page(params[:page]).per(10) pagination = render_to_string(:partial => 'backlinks/pagination', :layout => false, :locals => { :backlinks => backlinks }) sse.write({ :html => pagination }, :event => 'pagination') sleep 1 end rescue IOError # When the client disconnects, we'll get an IOError on write logger.debug "DISCONNECTED" ensure sse.close end end 

当我启动Puma并尝试获取更新时:

 curl http://localhost:3000/domains/16/backlinks/realtime_push 

curl立即返回,没有输出。

curl标题:

 HTTP/1.1 200 OK X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block X-Content-Type-Options: nosniff X-UA-Compatible: chrome=1 Content-Type: text/event-stream Cache-Control: no-cache X-Request-Id: 1a07be2f-de8d-4ca8-87d0-eee2787ea649 X-Runtime: 0.250782 Transfer-Encoding: chunked 

和Puma日志显示:

 Started GET "/domains/16/backlinks/realtime_push" for 127.0.0.1 at 2013-11-08 12:22:30 +0100 ActiveRecord::SchemaMigration Load (0.7ms) SELECT "schema_migrations".* FROM "schema_migrations" Processing by BacklinksController#realtime_push as */* Parameters: {"domain_id"=>"16"} Domain Load (1.9ms) SELECT "domains".* FROM "domains" WHERE "domains"."id" = $1 LIMIT 1 [["id", "16"]] (3.3ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] Rendered backlinks/_pagination.haml (60.6ms) (0.6ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] Rendered backlinks/_pagination.haml (36.0ms) (0.8ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] Rendered backlinks/_pagination.haml (37.5ms) (0.8ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] Rendered backlinks/_pagination.haml (35.6ms) (0.7ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] Rendered backlinks/_pagination.haml (38.7ms) (0.7ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] Rendered backlinks/_pagination.haml (37.0ms) 

所以这些事情很奇怪:

  • curl没有输出
  • 日志表示它会分页6次
  • 日志中没有“DISCONNECT”消息

有任何想法吗? 如果我注释掉sse.write上面的两行并返回一些文本而不是分页内容,它就有效……

这是SSE课程:

 class SSE def initialize io @io = io end def write object, options = {} options.each do |k,v| @io.write "#{k}: #{v}\n" end @io.write "data: #{JSON.dump(object)}\n\n" end def close @io.close end end 

这是render_to_string中的一个错误。

修补此问题的补丁( 实际上并不能解决问题 – 见下文 ):

 def render_to_string(*) orig_stream = response.stream super ensure if orig_stream response.instance_variable_set(:@stream, orig_stream) end end 

资料来源: http : //blog.sorah.jp/2013/07/28/render_to_string-in-ac-live

更新:这似乎只能解决问题…虽然它会导致控制器实际发送数据,但由于某种原因,JavaScript中的接收端仍然不会收到事件通知,请参见此处: SSE(服务器发送的事件) )不工作