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

Rust 如何与hyper请求处理程序共享不可变的配置数据?,rust,hyper,Rust,Hyper,我正在尝试在Rust中开发一个基于超链接的服务器应用程序。有一个INI文件包含绑定IP、数据库等配置 我不想在每个请求上解析INI文件,在服务器重新启动之前保留配置数据是可以的。如何向请求处理程序提供已解析数据的结构 我已经尝试过几种方法,比如使用std::sync::Arc,但到目前为止唯一有效的方法是使用静态,但我希望避免不安全的块 以下是一个完整的(非工作)示例: Cargo.toml [package] name = "demo" version = "0.1.0" edition =

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

我不想在每个请求上解析INI文件,在服务器重新启动之前保留配置数据是可以的。如何向请求处理程序提供已解析数据的结构

我已经尝试过几种方法,比如使用
std::sync::Arc
,但到目前为止唯一有效的方法是使用
静态
,但我希望避免
不安全的

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

Cargo.toml

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

[dependencies]
hyper = "0.12"
rust-ini = "0.13"
demo.ini

[Demo]
value="some value"
src/main.rs

extern板条箱超链接;
外部板条箱;
使用hyper::rt::{self,Future};
使用hyper::service::service\u fn\u ok;
使用hyper::{Body,Request,Response,Server};
使用ini::ini;
使用std::sync::Arc;
发布结构配置{
pub值:String,
}
fn请求处理程序(请求:请求,配置:&config)->响应{
让user_agent=req.headers()[“user agent”]到_str().unwrap();
println!(“用户代理:{:?},&用户代理);
println!(“配置值:{:?},&config.value);
响应::新建(正文::from(“”)
}
fn read_ini(配置文件:&str)->Arc{
匹配Ini::从\u文件(配置\u文件)加载\u{
Ok(c)=>{
让demo_section=c.section(一些(“demo.to_owned())).unwrap();
让value=匹配demo_section.get(“value”){
一些(v)=>v,
无=>{
println!(“读取ini时出错”);
std::流程::退出(-1)
}
};
Arc:::新建(配置{
value:value.to_string(),
})
}
_ => {
eprintln!(“关键:无法打开配置文件:{:?},&config_文件);
std::流程::退出(-1)
}
}
}
fn main(){
让cfg=read_ini(“demo.ini”);
让addr=“127.0.0.1:3000”;
让server=server::bind(&addr)
.serve(| | service|fn_ok(move | req:Request | Request | Request_handler(req,&cfg.clone()))
.map_err(| e | println!(“服务器错误:{},e));
rt::运行(服务器);
}
错误

error[E0525]:应为实现`Fn`特性的闭包,但此闭包只实现`Fn`一次`
-->src/main.rs:49:16
|
49.发球(| |发球|正常(移动|请求:请求|请求处理程序(req,&cfg.clone()))
|                ^^^^^^^^^^^^^^^^^-------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|                |                |
||闭包是'FnOnce',因为它将变量'cfg'移出其环境
|此闭包实现了'FnOnce',而不是'Fn'`

应小心观察
serve
中的两级闭包。 使用
move
定义的第二级闭包(传递给
service\u fn\u ok
)将尝试将唯一的实例
cfg
移动到其中,甚至在调用
clone()
之前。 如果不进行克隆,则无法多次执行此移动,因此闭包将只执行一次
fn
。这是双重移动的情况:第二个闭包希望在只允许它这样做一次的环境中接收资源

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

fn main(){
让cfg=read_ini(“demo.ini”);
让addr=“127.0.0.1:3000”;
让server=server::bind(&addr)
.发球(移动){
设cfg=cfg.clone();
服务| fn | ok(移动|请求|请求|处理程序(请求和cfg))
})
.map_err(| e | println!(“服务器错误:{},e));
rt::运行(服务器);
}