So I'm working with both the tokio-rustls server example and the hyper-staticfile document server example however I'm running into lifetime issues that I've have not been able to resolve. I'm wondering if someone may give me some guidance on how to get around this problem.
The following is my src:
src/main.rs:
extern crate futures;
extern crate hyper;
extern crate rustls;
extern crate tokio_core;
extern crate tokio_rustls;
extern crate hyper_rustls;
#[macro_use] extern crate lazy_static;
extern crate hyper_staticfile;
use tokio_core::net::TcpListener;
use rustls::internal::pemfile;
use std::env;
use tokio_rustls::ServerConfigExt;
use futures::{Future, Stream, future};
use hyper::{Error, Uri};
use hyper::server::{Http, Request, Response, Service};
use hyper_staticfile::Static;
use std::path::Path;
use tokio_core::reactor::{Core, Handle};
fn load_certs(filename: &str) -> Vec<rustls::Certificate> {
let certfile = std::fs::File::open(filename).expect("cannot open certificate file");
let mut reader = std::io::BufReader::new(certfile);
pemfile::certs(&mut reader).unwrap()
}
fn load_private_key(filename: &str) -> rustls::PrivateKey {
let keyfile = std::fs::File::open(filename).expect("cannot open private key file");
let mut reader = std::io::BufReader::new(keyfile);
let keys = pemfile::rsa_private_keys(&mut reader).unwrap();
assert!(keys.len() == 1);
keys[0].clone()
}
// example: DOMAIN=https://mediadepot-qa1.its.txstate.edu:8443
lazy_static! {
static ref DOMAIN: Uri = {
match env::var("DOMAIN") {
Ok(domain) => domain.parse::<Uri>().unwrap(),
Err(_) => panic!("No DOMAIN defined."),
}
};
}
type ResponseFuture = Box<Future<Item=Response, Error=Error>>;
struct MainService {
static_: Static,
}
impl MainService {
fn new(handle: &Handle) -> MainService {
MainService {
static_: Static::new(handle, Path::new("target/doc/")),
}
}
}
impl Service for MainService {
type Request = Request;
type Response = Response;
type Error = Error;
type Future = ResponseFuture;
fn call(&self, req: Request) -> Self::Future {
if req.path() == "/" {
let res = Response::new()
.with_status(hyper::StatusCode::MovedPermanently)
.with_header(hyper::header::Location::new("/hyper_staticfile/"));
Box::new(future::ok(res))
} else {
self.static_.call(req)
}
}
}
fn main() {
let address = match std::env::var("ADDRESS") {
Ok(a) => a.to_owned(),
Err(_) => "127.0.0.1:8443".to_owned(),
};
let addr = address.parse().unwrap();
let certs = load_certs("private/local.cert.pem");
let certs_key = load_private_key("private/local.key.pem");
let mut config = rustls::ServerConfig::new();
config.set_single_cert(certs, certs_key);
let arc_config = std::sync::Arc::new(config);
let mut core = Core::new().unwrap();
let handle = core.handle();
let socket = TcpListener::bind(&addr, &handle).unwrap();
let http = Http::new();
let done = socket.incoming()
.for_each(|(sock, remote_addr)| {
println!("Info: {:?}", remote_addr);
let done = arc_config.accept_async(sock)
.map(|stream| {
let s = MainService::new(&handle);
http.bind_connection(&handle, stream, remote_addr, s);
})
.map_err(move |err| println!("Error: {:?} - {}", err, remote_addr));
handle.spawn(done);
Ok(())
});
println!("Starting to serve on https://{} ...", addr);
core.run(done).unwrap();
}
Which gives the following errors:
error[E0373]: closure may outlive the current function, but it borrows `**handle`, which is owned by the current function
--> src/main.rs:141:22
|
141 | .map(|stream| {
| ^^^^^^^^ may outlive borrowed value `**handle`
142 | let s = MainService::new(&handle);
| ------ `**handle` is borrowed here
|
help: to force the closure to take ownership of `**handle` (and any other referenced variables), use the `move` keyword
|
141 | .map(move |stream| {
| ^^^^^^^^^^^^^
error[E0373]: closure may outlive the current function, but it borrows `**http`, which is owned by the current function
--> src/main.rs:141:22
|
141 | .map(|stream| {
| ^^^^^^^^ may outlive borrowed value `**http`
...
144 | http.bind_connection(&handle, stream, remote_addr, s);
| ---- `**http` is borrowed here
|
help: to force the closure to take ownership of `**http` (and any other referenced variables), use the `move` keyword
|
141 | .map(move |stream| {
| ^^^^^^^^^^^^^
error[E0373]: closure may outlive the current function, but it borrows `remote_addr`, which is owned by the current function
--> src/main.rs:141:22
|
141 | .map(|stream| {
| ^^^^^^^^ may outlive borrowed value `remote_addr`
...
144 | http.bind_connection(&handle, stream, remote_addr, s);
| ----------- `remote_addr` is borrowed here
|
help: to force the closure to take ownership of `remote_addr` (and any other referenced variables), use the `move` keyword
|
141 | .map(move |stream| {
| ^^^^^^^^^^^^^
error: aborting due to 3 previous errors
error: Could not compile `statictest`.
I tried the suggestion from the compiler of utilizing the move but then ran into issues with the handle and http variables. I do not understand how the closure can outlive the handle variable which was generated outside the closure.