gpt4 book ai didi

ruby-on-rails - 使用 Rack::Deflater 时,rails 中的 HTTP 流不起作用

转载 作者:行者123 更新时间:2023-12-04 19:17:14 24 4
gpt4 key购买 nike

我已经在 rails 3.1 中设置了 unicorn,并且在启用 Rack::Deflater 之前,http 流媒体可以正常工作。
我已经尝试过使用和不使用 Rack::Chunked。在 curl 中我可以看到我的响应,而在 chrome 中我得到以下错误:ERR_INVALID_CHUNKED_ENCODING

结果在其他浏览器(firefox、safari)以及开发(osx)和生产(heroku)之间是相同的。

配置.ru:

require ::File.expand_path('../config/environment',  __FILE__)
use Rack::Chunked
use Rack::Deflater
run Site::Application

unicorn .rb:
listen 3001, :tcp_nopush => false
worker_processes 1 # amount of unicorn workers to spin up
timeout 30 # restarts workers that hang for 30 seconds

Controller :
render "someview", :stream => true

谢谢你的帮助。

最佳答案

问题是 Rails ActionController::Streaming 直接渲染到 Chunked::Body 中。这意味着内容首先被分块,然后由 Rack::Deflater 中间件 gzipped,而不是 gzipped 然后分块。

根据HTTP/1.1 RFC 6.2.1 , chunked 必须最后应用编码到传输。

Since "chunked" is the only transfer-coding required to be understood by HTTP/1.1 recipients, it plays a crucial role in delimiting messages on a persistent connection. Whenever a transfer-coding is applied to a payload body in a request, the final transfer-coding applied must be "chunked".



我通过在初始化程序中猴子修补 ActionController::Streaming _process_options 和 _render_template 方法为我们修复了它,因此它不会将主体包装在 Chunked::Body 中,而是让 Rack::Chunked 中间件来完成。
module GzipStreaming
def _process_options(options)
stream = options[:stream]
# delete the option to stop original implementation
options.delete(:stream)
super
if stream && env["HTTP_VERSION"] != "HTTP/1.0"
# Same as org implmenation except don't set the transfer-encoding header
# The Rack::Chunked middleware will handle it
headers["Cache-Control"] ||= "no-cache"
headers.delete('Content-Length')
options[:stream] = stream
end
end

def _render_template(options)
if options.delete(:stream)
# Just render, don't wrap in a Chunked::Body, let
# Rack::Chunked middleware handle it
view_renderer.render_body(view_context, options)
else
super
end
end
end

module ActionController
class Base
include GzipStreaming
end
end

并将您的 config.ru 保留为
require ::File.expand_path('../config/environment',  __FILE__)
use Rack::Chunked
use Rack::Deflater
run Roam7::Application

不是一个很好的解决方案,它可能会破坏其他一些检查/修改主体的中间件。如果有人有更好的解决方案,我很乐意听到。

如果你使用的是new relic,它的中间件也必须是 disabled when streaming .

关于ruby-on-rails - 使用 Rack::Deflater 时,rails 中的 HTTP 流不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7986150/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com