Клиент для HTTP-сервера push (streaming) в Rust?

Из-за отсутствия лучшего примера, скажем, я хочу написать простой клиент с Rust, который мог бы установить соединение и получать данные из Twitter HTTP Streaming API. Возможно ли это? Я следил за Iron и Nickel, которые выглядят как хорошие рамки, но я не думаю, что у них есть эта функция еще?

1 ответ

Клиент http hyper поддерживает чтение ответов постепенно (как и все, что реализует черту ржавчины Reader), но я не смог найти что-либо, чтобы анализировать ответ поэтапно, или который реализует твиттер определенного протокола (для завершения objecs с помощью \r\n).

Тем не менее, я смог реализовать краткое доказательство концепции:

EDIT: см. и играйте с ним в github.

use rustc_serialize::json::Json;
use std::str;
pub trait JsonObjectStreamer {
 fn json_objects(&mut self) -> JsonObjects<self>;
}
impl<t: buffer=""> JsonObjectStreamer for T {
 fn json_objects(&mut self) -> JsonObjects<t> {
 JsonObjects { reader: self }
 }
}
pub struct JsonObjects<'a, B> where B: 'a {
 reader: &'a mut B
}
impl<'a, B> Iterator for JsonObjects<'a, B> where B: Buffer + 'a {
 type Item = Json;
 fn next(&mut self) -> Option<json> {
 let mut line_bytes = match self.reader.read_until(b'\r') {
 Ok(bytes) => bytes,
 Err(_) => return None,
 };
 if line_bytes.last() == Some(&b'\r') {
 // drop the \r
 line_bytes.pop();
 // skip the \n
 match self.reader.read_char() {
 Ok(_) => (),
 Err(_) => return None,
 }
 }
 let line = match str::from_utf8(&line_bytes) {
 Ok(line) => line,
 Err(_) => return None
 };
 Json::from_str(line).ok()
 }
}
</json></t></t:></self>

Использование: (предполагается, что вы отбросили его в файле src/json_streamer.rs в своем проекте)

#![feature(io)]
extern crate hyper;
extern crate "rustc-serialize" as rustc_serialize;
mod json_streamer;
use hyper::Client;
use std::old_io::BufferedReader;
use json_streamer::JsonObjectStreamer;
fn main() {
 let mut client = Client::new();
 let res = client.get("http://localhost:4567/").send().unwrap();
 for obj in BufferedReader::new(res).json_objects() {
 println!("object arrived: {}", obj);
 }
}

Я использовал это крошечное приложение для синатра, чтобы проверить его:

require 'sinatra'
require 'json'
class Stream
 def each
 hash = { index: 0 }
 loop do
 hash[:index] += 1
 yield hash.to_json + "\r\n"
 sleep 0.5
 end
 end
end
get '/' do
 Stream.new
end

licensed under cc by-sa 3.0 with attribution.