从HTTP请求反序列化响应时的生命周期错误

时间:2018-01-28 12:14:10

标签: asynchronous rust lifetime serde

我正在创建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,哪种有意义,但我不知道如何规避这一点。

Playground

0 个答案:

没有答案