我在Iron处理程序中发出客户端请求。如何重用Tokio的Core
和Hyper的Client
?我使用的是超0.11.0和tokio-core 0.1。
fn get_result(req: &mut Request) -> IronResult<Response> {
let mut payload = String::new();
req.body.read_to_string(&mut payload).unwrap();
// can we re-use core and client somehow. Making then global with lazy_static!() does not work.
let mut core = tokio_core::reactor::Core::new().unwrap();
let client = Client::new(&core.handle());
let uri = "http://host:port/getResult".parse().unwrap();
let mut req: hyper::Request = hyper::Request::new(hyper::Method::Post, uri);
req.headers_mut().set(ContentType::json());
req.headers_mut().set(ContentLength(payload.len() as u64));
req.set_body(payload);
let mut results: Vec<RequestFormat> = Vec::new();
let work = client.request(req).and_then(|res| {
res.body().for_each(|chunk| {
let re: ResultFormat = serde_json::from_slice(&chunk).unwrap();
results.push(re);
Ok(())
})
});
Ok(Response::with(
(iron::status::Ok, serde_json::to_string(&results).unwrap()),
))
}
答案 0 :(得分:1)
我创建了一个包装客户端和核心的Downloader类。以下是摘录。
exports.BoughtHiLo = functions.database.ref('/buy/hilo/{uid}/').onWrite(event => {
if (!event.data.exists()){return}
const val = event.data.val()
const userUID = event.params.uid
const game = val.game
const gemCost = hiLoInfo[game].gemCost
const gamesRecieved = hiLoInfo[game].gamesRecieve
return db.ref('/users/' + userUID + '/server/gems/').transaction(function(gems) {return (gems || 0) - gemCost}).then(function(gemsLeft) {
const currentGems = gemsLeft.snapshot.val()
promArr = []
if (currentGems >= 0){
promArr.push(db.ref('/users/' + userUID + '/server/hilogames/').transaction(function(hilogames) {return (hilogames || 0) + gamesRecieved}))
}else{
promArr.push(db.ref('/users/' + userUID + '/server/gems/').transaction(function(gemsUser) {return (gemsUser || 0) + gemCost}))
}
promArr.push(event.data.adminRef.remove())
return Promise.all(promArr)
})
})
现在这个类的客户端可以有一个静态变量。
use hyper;
use tokio_core;
use std::sync::{mpsc};
use std::thread;
use futures::Future;
use futures::stream::Stream;
use std::time::Duration;
use std::io::{self, Write};
use time::precise_time_ns;
use hyper::Client;
pub struct Downloader {
sender : mpsc::Sender<(hyper::Request, mpsc::Sender<hyper::Chunk>)>,
#[allow(dead_code)]
tr : thread::JoinHandle<hyper::Request>,
}
impl Downloader {
pub fn new() -> Downloader {
let (sender, receiver) = mpsc::channel::<(hyper::Request,mpsc::Sender<hyper::Chunk>)>();
let tr = thread::spawn(move||{
let mut core = tokio_core::reactor::Core::new().unwrap();
let client = Client::new(&core.handle());
loop {
let (req , sender) = receiver.recv().unwrap();
let begin = precise_time_ns();
let work = client.request(req)
.and_then(|res| {
res.body().for_each(|chunk| {
sender.send(chunk)
.map_err(|e|{
//io::sink().write(&chunk).unwrap();
io::Error::new(io::ErrorKind::Other, e)
})?;
Ok(())
})
//sender.close();
//res.body().concat2()
});
core.run(work).map_err(|e|{println!("Error Is {:?}", e);});
//This time prints same as all request processing time.
debug!("Time taken In Download {:?} ms", (precise_time_ns() - begin) / 1000000);
}
});
Downloader{sender,
tr,
}
}
pub fn download(&self, req : hyper::Request, results: mpsc::Sender<Vec<u8>>){
self.sender.send((req, results)).unwrap();
}
}
然后通过接收频道阅读。 可能需要使用sender.drop()
关闭发送方通道