Rack::Deflater 和 Rack::URLMap
Rack::Deflater and Rack::URLMap
我想根据响应的大小 body 有条件地启用 Rack::Deflater
,如下所示:
use Rack::Deflater, :if => lambda { |*, body| body.map(&:bytesize).reduce(0, :+) > 512 }
如果我在我的一个 Rack 应用程序中插入 Rack::Deflater
中间件,这个 lambda 可以正常工作; body
是一个字符串数组。但是,如果我在 Rack::URLMap
之前(在 config.ru
中)插入 Rack::Deflater
中间件,它不会;因为 body
现在是 Rack::BodyProxy
object.
我查看了 Rack::BodyProxy
的定义,它似乎有点不透明。没有明确的方法从这个 object 中解析实际的 body; body.body
returnsnil
。在这种情况下,easiest/best 确定响应 body 大小的方法是什么,而不是将 Rack::Deflater
中间件向下移动到我的每个 Rack 应用程序中?
tl;dr:在给定 Rack::BodyProxy
object 的情况下,如何确定响应 body 的大小?
看起来 Rack::BodyProxy
确实提供了 #each
方法作为问题 rack/rack#434 的解决方法。此方法 returns 对私有 @body
ivar 的元素进行枚举。在调用链中添加一个 .each
可以解决 Rack::BodyProxy
对象的这个问题,并且对于更普通的基于数组的主体来说这是一个空操作,所以现在这让我到达了我需要去的地方。但是,我仍然想了解为什么我会得到这些对象,以及是否有更好的方法来处理它们。
这是修改后的有效解决方案:
use Rack::Deflater, :if => lambda { |*, body|
body.each.map(&:bytesize).reduce(0, :+) > 512
}
更新: 哎呀,有时 body
是一个 Rack::BodyProxy
对象,而 body.body
是一个 Rack::Response
对象。这有点失控了……!这是我现在使用的解决方案:
use Rack::Deflater, :if => lambda { |*, body|
body.map(&:bytesize).reduce(0, :+) > 512 \
if body.respond_to?(:map) \
or body.respond_to?(:each) and (body = body.each).respond_to?(:map)
}
远非优雅...
我想根据响应的大小 body 有条件地启用 Rack::Deflater
,如下所示:
use Rack::Deflater, :if => lambda { |*, body| body.map(&:bytesize).reduce(0, :+) > 512 }
如果我在我的一个 Rack 应用程序中插入 Rack::Deflater
中间件,这个 lambda 可以正常工作; body
是一个字符串数组。但是,如果我在 Rack::URLMap
之前(在 config.ru
中)插入 Rack::Deflater
中间件,它不会;因为 body
现在是 Rack::BodyProxy
object.
我查看了 Rack::BodyProxy
的定义,它似乎有点不透明。没有明确的方法从这个 object 中解析实际的 body; body.body
returnsnil
。在这种情况下,easiest/best 确定响应 body 大小的方法是什么,而不是将 Rack::Deflater
中间件向下移动到我的每个 Rack 应用程序中?
tl;dr:在给定 Rack::BodyProxy
object 的情况下,如何确定响应 body 的大小?
看起来 Rack::BodyProxy
确实提供了 #each
方法作为问题 rack/rack#434 的解决方法。此方法 returns 对私有 @body
ivar 的元素进行枚举。在调用链中添加一个 .each
可以解决 Rack::BodyProxy
对象的这个问题,并且对于更普通的基于数组的主体来说这是一个空操作,所以现在这让我到达了我需要去的地方。但是,我仍然想了解为什么我会得到这些对象,以及是否有更好的方法来处理它们。
这是修改后的有效解决方案:
use Rack::Deflater, :if => lambda { |*, body|
body.each.map(&:bytesize).reduce(0, :+) > 512
}
更新: 哎呀,有时 body
是一个 Rack::BodyProxy
对象,而 body.body
是一个 Rack::Response
对象。这有点失控了……!这是我现在使用的解决方案:
use Rack::Deflater, :if => lambda { |*, body|
body.map(&:bytesize).reduce(0, :+) > 512 \
if body.respond_to?(:map) \
or body.respond_to?(:each) and (body = body.each).respond_to?(:map)
}
远非优雅...