Unable modify a variable when handling HTTP request with warp due to an error

Hello, I am new to Rust and I am using the warp library for http server, however, Rust refuses to let me modify the ngrok_server variable due to errors that I do not understand at all. What I can do to fix those errors? I am just trying to start a process on HTTP request and store it in a variable so that I can access it later.

Code sample:

let mut ngrok_server: Option<std::process::Child>; // line 39

let server_expose_to_internet = warp::path!("server" / String / "expose-to-internet").map(|_| {
	ngrok_server = Some(helper::start_ngrok_server());

	"true"
}); // line 45

Errors:

the trait bound `&mut Option<std::process::Child>: Clone` is not satisfied in `[closure@src\main.rs:41:92: 41:95]`
the trait `Clone` is implemented for `Option<T>`
`Clone` is implemented for `&std::option::Option<std::process::Child>`, but not for `&mut std::option::Option<std::process::Child>`rustcClick for full compiler diagnostic
main.rs(41, 92): within this `[closure@src\main.rs:41:92: 41:95]`
main.rs(41, 88): required by a bound introduced by this call
main.rs(41, 92): required because it's used within this closure
mod.rs(194, 34): required by a bound in `warp::Filter::map`

Warp requires closures that are passed to filters to be clonable, which is what's causing the errors you see. A mutable reference can't be cloned, and that's how the closure captures ngrok_server since you aren't moving it into the closure.

You can wrap the Option in a Mutex to fix that problem[1], but then you'll get an error that you're borrowing from a variable that may not live long enough. So you also need some kind of shared ownership to keep the value alive as long as the filters are still around. Arc is the simplest option here.

let ngrok_server = Arc::new(Mutex::new(None));

let server_expose_to_internet = warp::path!("server" / String / "expose-to-internet").map({
    // Clone the Arc before moving it into the closure, so we can still use it in other filters after the call to `map`.
    let ngrok_server = ngrok_server.clone();
    
    // Return the closure from the block, passing it to `map`
    move |_| {
        *ngrok_server.lock().unwrap() = Some(helper::start_ngrok_server());

        "true"
    }
});

  1. Mutexes can mutate through a normal reference which can be cloned ↩ī¸Ž

1 Like