如何与超级请求处理程序共享不可变的配置数据?

Hel*_*got 2 rust hyper

我正在尝试在 Rust 中开发一个基于超级服务器的应用程序。有一个 INI 文件保存配置,如绑定 IP、数据库等。

我不想在每个请求上解析 INI 文件,并且可以保留配置数据直到服务器重新启动。如何将已解析数据的结构提供给请求处理程序?

我尝试了多种方法,例如 using std::sync::Arc,但目前唯一有效的方法是使用 a static,但我想避免unsafe阻塞。

这是一个完整的(非工作)示例:

Cargo.toml

[package]
name = "demo"
version = "0.1.0"
edition = "2018"

[dependencies]
hyper = "0.12"
rust-ini = "0.13"
Run Code Online (Sandbox Code Playgroud)

演示文件

[Demo]
value="some value"
Run Code Online (Sandbox Code Playgroud)

src/main.rs

[package]
name = "demo"
version = "0.1.0"
edition = "2018"

[dependencies]
hyper = "0.12"
rust-ini = "0.13"
Run Code Online (Sandbox Code Playgroud)

错误

[Demo]
value="some value"
Run Code Online (Sandbox Code Playgroud)

E_n*_*ate 5

应仔细serve观察两个级别的关闭。使用service_fn_ok定义的第二级闭包(传递给)move将尝试将唯一的实例cfg移入其中,甚至在对 进行任何调用之前clone()。没有克隆就不能多次执行此操作,因此闭包只会实现FnOnce。这是一个双重移动的情况:第二个闭包想要在一个只允许它做一次的环境中接收资源。

为了解决这个问题,我们希望第一个闭包接收到cfg,并且每次在那里克隆它。

fn main() {
    let cfg = read_ini("demo.ini");
    let addr = "127.0.0.1:3000".parse().unwrap();

    let server = Server::bind(&addr)
        .serve(move || {
            let cfg = cfg.clone();
            service_fn_ok(move |req| request_handler(req, &cfg))
        })
        .map_err(|e| println!("server error: {}", e));

    rt::run(server);
}
Run Code Online (Sandbox Code Playgroud)