Время жизни ржавчины с замыканиями с использованием гипер - PullRequest
1 голос
/ 19 июня 2020

Изучал ржавчину и имел проблемы со сроком службы при передаче conn в request_handler. Я получаю сообщение об ошибке:

error[E0312]: lifetime of reference outlives lifetime of borrowed content...
  --> src/main.rs:33:70
   |
33 |         let request_handler = |req: Request<Body>| async { request_handler(conn, req).await };
   |                                                                            ^^^^
   |
   = note: ...the reference is valid for the static lifetime...

, но я не уверен, как обрабатывать время жизни с закрытием и почему / как это stati c. Я плохо понимаю время жизни и заимствования, но этот случай кажется более сложным. Я бы также просто не использовал замыкание, но возвращаемый тип одного из замыканий имеет тип, который не экспортируется гипер-ящиком, поэтому я не знаю, как создать fn, не имея возможности объявить Тип возвращаемого значения.

Также я могу подтвердить, удаляю ли я передачу conn, я могу заставить все работать, но я хочу использовать объект conn в request_handler.

use hyper::server::conn::AddrStream;
use hyper::service::make_service_fn;
use hyper::Version;
use hyper::{Body, Error, Method, Request, Response, Server};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
mod http_models;
mod utils;
use hyper::service::service_fn;

async fn request_handler(
    conn: &'static AddrStream,
    req: Request<Body>,
) -> Result<Response<Body>, hyper::Error> {
    println!("req: {:?}", req);
    if req.method() == Method::CONNECT {
        println!("Connect")
    }
    let res: Response<Body> = Response::builder()
        .status(200)
        .version(Version::HTTP_11)
        .body(Body::empty())
        .unwrap();
    return Ok(res);
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
    let addr = SocketAddr::new(ip, 1337);
    //let client = Client::new();

    let make_service = make_service_fn(|conn: &AddrStream| async {
        let request_handler = |req: Request<Body>| async { request_handler(conn, req).await };
        let service = service_fn(request_handler);
        Ok::<_, Error>(service)
    });

    let server = Server::bind(&addr).serve(make_service);

    println!("Listening on http://{}", addr);

    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
    Ok(())
}

1 Ответ

2 голосов
/ 19 июня 2020

Аргумент conn замыкания, переданный в make_service_fn, существует только до тех пор, пока тело замыкания, но возвращаемое значение замыкания (Ok(service)) ссылается на него. Замыкание должно иметь тип FnMut(&Target) -> impl Future, что означает, к сожалению, не разрешено возвращать значение, которое ссылается на его аргумент.

Единственное решение - скопировать / клонировать все, что вам нужно, из conn при настройке обработчика запросов, поскольку вы не можете сохранить ссылку на него после возврата закрытия.

...