【问题标题】:Is it possible to get the headers of a request using Ruby's HTTPClient gem before the request completes?是否可以在请求完成之前使用 Ruby 的 HTTPClient gem 获取请求的标头?
【发布时间】:2013-08-05 07:57:11
【问题描述】:

我需要在 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 中是否可行?

【问题讨论】:

    标签: ruby httpclient ruby-on-rails-4


    【解决方案1】:

    更新

    我有一个解决方案。

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

    HTTPClient::Connection 的补丁对您来说几乎肯定不是必需的,但它可以让您编写像 conn.queue.size?conn.queue.empty? 这样的东西。

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

    resp.content 返回一个IO 对象,它是一个管道读取端点,可以在pop hs 返回后立即调用。另一端由异步线程在数据到达时写入,​​您可以使用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

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

    【讨论】:

    • 我不想这样做,因为这意味着 2 个 HTTP 请求,这可能会抵消我试图通过传递分块首先获得的性能提升。我知道 HTTPClient 已经收到了标头(根据 HTTP 协议),我想我只是由于 HTTPClient API 限制而无法访问它们(除非我错过了什么)。
    • @WilliamDenniss:很公平。我自己没想到这是一个很好的答案!我一直在寻找HTTPClient 的来源,我想我已经找到了你想要的东西。看看我的更新。
    • @Bordin,感谢您的出色回答,很高兴有一个 get_async 的工作示例。但是,它不适用于二进制请求!用http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png 替换答案中的url,它将挂起(ruby 2.0.0,httpclient 2.3.4.1)。你能想到任何原因,还是 API 错误?我假设后者并在这里记录:github.com/nahi/httpclient/issues/173
    • 顺便说一句。一种优化是将read 切换为readpartial(并添加rescue EOFError),因为这将更接近地匹配输入流(有效地读取它拥有的任何数据)。
    • @WilliamDenniss:我不能说为什么,但如果你使用 sysread 而不是 readpartial 效果很好 :)
    猜你喜欢
    • 2023-03-28
    • 2011-10-04
    • 1970-01-01
    • 2013-04-13
    • 1970-01-01
    • 2020-02-21
    • 2012-11-06
    • 1970-01-01
    • 2012-06-28
    相关资源
    最近更新 更多