我正在尝试创建一个小的ruby脚本,它使用HTTP Chunked Transfer编码接收流数据。所以我在客户端结束时使用了ruby。我可以找到很多关于ruby(和rails)提供流的问题和信息,但关于使用它们并不多。也许是因为它是微不足道的,应该只是作为HTTP的低级功能。那么有人可以给我一些示例脚本吗?
我尝试了几件事。这个使用open-uri:
require 'open-uri'
streamURL = 'http://localhost/sample-stream.php'
puts "Opening"
open(streamURL) do |f|
puts "Opening steam " + streamURL + " (never gets here)"
p f.meta
p "Content-Type: " + f.content_type
p "last modified" + f.last_modified.to_s
no = 1
# print the first three lines
f.each do |line|
print "#{no}: #{line}"
no += 1
break if no > 4
end
end
...这个使用net http:
require 'net/http'
require 'uri'
streamURL = 'http://localhost/sample-stream.php'
url = URI.parse(streamURL)
full_path = (url.query.empty?) ? url.path : "#{url.path}?#{url.query}"
the_request = Net::HTTP::Get.new(full_path, {'Transfer-Encoding' => 'chunked', 'content-type' => 'text/plain'})
#(Side question: Does it even make sense to specify 'chunked' in the request?)
puts "Opening stream " + streamURL
the_response = Net::HTTP.start(url.host, url.port) { |http|
http.request(the_request)
}
puts the_response.body #never gets here
在这两种情况下它都不会输出任何东西,我可以在apache中看到我的PHP脚本忙着喷出越来越多的数据。我觉得很清楚这里出了什么问题。在这两种情况下,我认为我的脚本在处理它之前都在等待获得整个响应(这将永远不会发生)。
我应该提一下我的php脚本(服务器)可能有问题,但我可以看到它很好地融入了firefox。
那么有一种简单的红宝石方式来传输数据吗?或者我应该期望需要特殊的宝石/库来做到这一点? (例如,我遇到了this library)
答案 0 :(得分:2)
我认为以下代码应该有效。
require 'net/http'
streamURL = 'http://localhost/sample-stream.php'
uri = URI.parse(streamURL)
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri.request_uri
http.request request do |response|
response.read_body do |chunk|
#We get the data here chunk-by-chunk
puts chunk
end
end
end
实际上这对我的sample-stream.php不起作用,但我很幸运得到类似于这个脚本的东西,指向另一台服务器。我的工作代码更复杂,因为它还需要身份验证,但我在这里删除了一点。
指向我的测试php脚本,此代码会产生一些有用的错误消息:
`read_chunked': wrong chunk size line: (Net::HTTPBadResponse)
...这清楚地表明我在php服务器端做错了。不确定是什么问题,但这是另一个问题。
答案 1 :(得分:0)
我尝试了先前答案(Net::HTTP.start
和wget
)中的方法,但没有得到任何输出。对我有用的是:
url = <...>
IO.popen "curl -s #{url}" do |io|
io.sync = true
io.each do |line|
break if !(process_line line)
end
end
答案 2 :(得分:-1)
调用'wget'系统命令的另一种方法。
wget_command = "wget #{streamURL} --user=myusername --password=mypassword -qO-"
puts "Opening stream: #{wget_command}"
f = open("|" + wget_command)
while (line = f.gets)
puts "LINE:" + line
end #(loops forever)
end
这看起来比使用ruby的net http更可靠,而且它肯定是更紧凑的代码。作为一个额外的好处,我可以轻松地逐行获取数据(我不得不从块读取方法中捏造的东西)不确定缺点是什么。以这种方式管道stdout数据可能效率低下。此代码也不会在没有wget命令的平台上工作(windows)但对我来说这似乎比net http好一点......
然而,三四分钟后它仍然会遇到问题。我想象这可能是因为流进来太快而某些缓冲区正在填满,或者因为这个特定的流在几分钟后减速(不要问我原因。它只是这样做)所以也许是当它最终赶上时会出现错误。