1

我需要在 Rails 应用程序中代理请求。我希望我可以用分块来代理它(所以,收到 1 个块,发送一个块)。该应用程序在没有分块的情况下工作正常(将请求加载到内存中并传输)。

这是我将块代理到最终客户端的代码:

self.response.headers['Last-Modified'] = Time.now.ctime.to_s
self.response_body = Enumerator.new do |y|
  client = HTTPClient.new
  http_response = client.get(proxy_url, nil, headers) do |chunk|
    y << chunk
  end
end

问题是,在收到所有块之前,我无法检查“http_response”,因此我无法根据客户端的标头设置标头。

我要做的是在发送第一个块之前传输从客户端返回的标头。这可能吗?

如果不是,这种模式在任何其他 Ruby HTTP 客户端 gem 中是否可行?

4

1 回答 1

1

更新

我有一个解决方案给你。

如果您get_async改为调用,它将立即返回一个HTTPClient::Connection对象,该对象在收到后立即使用标头信息进行更新。此代码示例演示。

几乎可以肯定,补丁对HTTPClient::Connection您来说不是必需的,但它可以让您编写诸如conn.queue.size?和之类的东西conn.queue.empty?

conn.pop 阻塞,直到异步线程将响应(或异常)推送到队列,然后返回正常HTTP::Message对象。(注意,如果你使用的是猴子补丁,你可以使用conn.queue.empty?看看是否pop会阻塞。)

resp.content返回一个IO对象,它是一个管道读取端点,并且可以在pophs 返回后立即调用。另一端由异步线程在数据到达时写入,​​您可以一次性读取全部内容或使用您喜欢的任何大小的块read

require 'httpclient'

class HTTPClient::Connection
  attr_reader :queue
end

client = HTTPClient.new

conn = client.get_async 'http://en.wikipedia.org/wiki/Ruby_(programming_language)'

resp = conn.pop
resp.header.all.each { |name, val| puts "#{name}=#{val}" }
puts
pipe = resp.content
while chunk = pipe.read(8192)
  print chunk
end

可以解析收到的第一个块以提取标头,但我建议您head先调用以获取标头信息。然后也这样做get

(已更新 - 第一个块包含内容的开头,因此这不起作用。)

于 2013-08-05T08:36:45.773 回答