【问题标题】:Overriding Content-Length header with Rack/Sinatra使用 Rack/Sinatra 覆盖 Content-Length 标头
【发布时间】:2014-06-05 11:59:30
【问题描述】:

在 Sinatra 中,如何覆盖响应中的 Content-Length 标头以设置我自己的值?

我方法的最后一行返回以下内容:

[200, {'Content-Type' => component.content_type,
'Content-Length' => component.content_length.to_s}, component.content.data]

我希望通过这种方式覆盖内容值,但会导致异常:

Unexpected error while processing request: Content-Length header was 2, but should be 0

我想为内容长度返回一个不同的值。有没有办法做到这一点?

【问题讨论】:

  • 你为什么要覆盖内容长度——这肯定只会导致问题。行为取决于您使用的服务器(我无法重现您在 Sinatra 使用的任何默认服务器上看到的错误)。你想做什么?
  • 在这种情况下,用户代理是一个 SAP 系统,它正在查询数据并期望文档的长度,而不是文档本身,即它以自己的方式解释数据。我正在使用 Thin,如果这有什么不同的话,虽然我认为 Rack 正在处理内容长度的添加,但据我所知,它有一个中间件,我还没有完全掌握。

标签: sinatra rack


【解决方案1】:

Rack::Lint middleware 引发了此错误,因此快速解决方法是不使用该中间件。取决于您启动应用程序的方式,这可能会很棘手——如果您使用rackup,Rack 在某些情况下会添加它。

更好的解决方案是将您的客户端更改为使用HTTP HEAD request 而不是GET。在西纳特拉defining a GET route automatically defines a matching HEAD route。使用HEAD 将导致服务器发送标头而不是正文,您应该能够将Content-Length 设置为您想要的任何内容。它还将避免Rack::Lint 错误。

这里有一个要点解释如何禁用Rack::Lint

module Rack
  class Lint
    def call(env = nil)
      @app.call(env)
    end
  end
end

(取自https://gist.github.com/shtirlic/2146256)。

【讨论】:

  • 是的,使用 HEAD 请求更有意义。不幸的是,对于这个用户代理,标准合规性不是优先事项,改变它不是一种选择:-(但是,我可以只为一个特定的路线替换某个中间件吗?你有代码示例或其他东西的链接吗?您可以在此处粘贴说明如何执行此操作的说明?
  • 另外,我认为我不想完全禁用 Rack::Lint。既然我知道它就在那里,我不希望那种安全网的感觉消失。
  • 谢谢,我同意你禁用 Rack::Lint 的建议,因为在我找到更好的方法之前,这似乎是目前最快的。
  • @mydoghasworms 如果您知道客户端不会查看实际内容,另一种选择是发送您想要的长度的生成字符串,例如'-' * length
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-11
  • 2016-08-25
  • 1970-01-01
相关资源
最近更新 更多