I'm trying to implement an HTTP layer on top of RocksDB as a toy project. My idea was to create an endpoint which returns a "never-ending" stream of data which is finished when client closes connection.
I need the lifetime of a variable to last as long as the lifetime of the HTTP request: Rust playground
extern crate hyper;
extern crate tokio;
use std::convert::Infallible;
use std::net::SocketAddr;
use bytes::Bytes;
use futures::Stream;
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
async fn hello_world(_: Request<Body>) -> Result<Response<Body>, Infallible> {
let add_underscore = "_";
let iter = vec!["hello", "world"]
.into_iter()
.map(|x| format!("{}{}", x, add_underscore))
.map(|x| Ok(Bytes::from(x)));
let stream: Box<dyn Stream<Item=Result<Bytes, Box<dyn std::error::Error + Send + Sync>>> + Send + Sync>
= Box::new(futures::stream::iter(iter));
let response = http::Response::builder()
.header(
"Content-Type",
"application/octet-stream",
)
.body(Body::from(stream))
.unwrap();
Ok(response)
}
#[tokio::main]
async fn main() {
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let make_svc = make_service_fn(|_conn| async {
Ok::<_, Infallible>(service_fn(hello_world))
});
let server = Server::bind(&addr).serve(make_svc);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
}
error[E0597]: `add_underscore` does not live long enough
--> src/main.rs:16:37
|
16 | .map(|x| format!("{}{}", x, add_underscore))
| --- ^^^^^^^^^^^^^^ borrowed value does not live long enough
| |
| value captured here
...
19 | let stream: Box<dyn Stream<Item=Result<Bytes, Box<dyn std::error::Error + Send + Sync>>> + Send + Sync> = Box::new(futures::stream::iter(iter));
| ------------------------------------- cast requires that `add_underscore` is borrowed for `'static`
...
29 | }
| - `add_underscore` dropped here while still borrowed
If you run the code locally and comment the 2 lines with add_underscore
you get a compiling version:
curl -XGET -v --silent 127.0.0.1:3000
* Trying 127.0.0.1:3000...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: application/octet-stream
< transfer-encoding: chunked
< date: Wed, 04 Mar 2020 15:03:39 GMT
<
* Connection #0 to host 127.0.0.1 left intact
helloworld
I think I understand the problem: add_underscore
only lives as long as the hello_world
function but the request lives longer because it's a future. I could make it 'static
but in the real project that's something dynamic, created on demand (inside the function or injected as a parameter).
I think I have to attach the lifetime of add_underscore
to the lifetime of the future (I think), but I don't know how.
I'm not even sure which part of the crates is the one requiring a 'static
lifetime.