Ruby chunked клиент кодирования - PullRequest
2 голосов
/ 23 марта 2012

Я пытаюсь создать небольшой скрипт ruby, который получает потоковые данные с помощью кодировки HTTP Chunked Transfer.Поэтому я использую ruby ​​в конце client .Я могу найти много вопросов и информации о 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.

Так есть ли простой рубиновый способ для потоковой передачи данных?или я должен ожидать специальных гемов / библиотек для этого?(Я наткнулся на эту библиотеку например)

Ответы [ 3 ]

2 голосов
/ 14 мая 2012

Я думаю, что следующий код должен работать.

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-сервера.Не уверен, что не так, но это другой вопрос.

0 голосов
/ 25 июня 2018

Я попробовал подходы в предыдущих ответах (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
0 голосов
/ 29 мая 2012

Другой подход, вызывающий системную команду '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

Это казалось более надежным, чем поначалу использование net http в ruby, и, конечно, это более компактный код.В качестве дополнительного бонуса я могу легко получать данные построчно (что-то еще, что мне приходилось выдумывать из-за подхода к чтению чанков). Не совсем уверен, в чем недостатки.Возможно, есть неэффективность в передаче данных стандартного вывода таким способом.Также этот код не будет работать на платформе без команды wget (windows) Но для меня это, похоже, работает немного лучше, чем net http ...

Однако через три-четыре минуты проблемы все еще возникают.Я предполагаю, что это либо потому, что поток поступает слишком быстро и где-то буфер заполняется, либо потому, что этот конкретный поток замедляется через несколько минут (не спрашивайте меня, почему. Просто так), и поэтому, возможно,ошибки появляются, когда он, наконец, догоняет.

...