我正在创建REST API客户端,我需要使用serde
反序列化对结构的JSON API响应。我使用hyper
发出HTTP请求。我的客户看起来像这样:
use std::boxed::Box;
use std::str;
use tokio_core;
use hyper;
use hyper_tls;
use serde;
use serde_json;
use futures::{self, Stream};
use futures::future::Future;
type HttpsClient = hyper::Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>;
pub struct Client {
https_client: HttpsClient
}
#[derive(Debug)]
pub enum ClientError {
DeserializationError(serde_json::Error),
UrlParsingError(hyper::error::UriError),
RequestError(hyper::Error),
}
impl Client {
pub fn new(core: &tokio_core::reactor::Core) -> Client {
let client = hyper::Client::configure()
.connector(hyper_tls::HttpsConnector::new(4, &core.handle()).unwrap())
.build(&core.handle());
Client {
https_client: client
}
}
pub fn get<'a>(&'a self, url: &str) -> Box<Future<Item=hyper::Chunk, Error=ClientError> + 'a> {
let res = futures::future::result(url.parse())
.map_err(ClientError::UrlParsingError)
.and_then(move |parsed_url| {
let mut req = hyper::Request::new(hyper::Method::Get, parsed_url);
self.https_client.request(req).map_err(ClientError::RequestError)
})
.and_then(|res| res.body().concat2().map_err(ClientError::RequestError));
Box::new(res)
}
}
我可以像这样使用它并且工作正常:
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate hyper;
extern crate hyper_tls;
extern crate futures;
use futures::future::Future;
use futures::sink::Sink;
use futures::stream::Stream;
use tokio_core::reactor::Core;
mod client;
#[derive(Deserialize, Debug)]
struct Bar {
values: Vec<f64>
}
fn main() {
let mut core = Core::new().expect("Failed to create core");
let url = "https://api.foo.com/bar";
let client = client::Client::new(&core);
let future = client.get(&url).and_then(|chunk: hyper::Chunk| {
let bar: Bar = serde_json::from_slice(&chunk).unwrap();
println!("{:?}", bar);
Ok(())
});
core.run(future);
}
现在我想为我的客户端创建一个更好的API并在get
函数中处理JSON反序列化,所以希望像这样使用它:
let future = client.get(&url).and_then(|bar: Bar| {
println!("{:?}", bar);
Ok(())
});
我将get
功能更改为:
pub fn get<'a, T>(&'a self, url: &str) -> Box<Future<Item=T, Error=ClientError> + 'a>
where T: serde::de::Deserialize<'a> + 'a
{
let res = futures::future::result(url.parse())
.map_err(ClientError::UrlParsingError)
.and_then(move |parsed_url| {
let mut req = hyper::Request::new(hyper::Method::Get, parsed_url);
self.https_client.request(req).map_err(ClientError::RequestError)
})
.and_then(|res| res.body().concat2().map_err(ClientError::RequestError))
.map(|data| serde_json::from_slice(&data).unwrap());
Box::new(res)
}
然而,编译器给了我一个错误,告诉我'data' does not live long enough
,哪种有意义,但我不知道如何规避这一点。