我想创建一个有四种方法的结构:
new(), handle_interaction(), add_shortcut(), async start_server()
该结构应包含一个 Web 服务器,该服务器使用
async start_server()
启动,这是一个由用户添加的可用快捷方式列表(回调闭包)。
当服务器启动时,我想要一个单一的端点(
/
)然后将接收 JSON 数据。收到json数据后,服务器会判断传入的是哪个交互,并发关闭交互。
我尝试了很多不同的解决方案,我必须说其中很多都包含了我还不熟悉的锈类型和概念。
我现在登陆的代码仍然失败了,是这样的: (我已经用评论突出了错误,只是让你知道什么失败了)
use axum::{
routing::{get, post},
http::StatusCode,
Json, Router,
};
use std::{net::SocketAddr, future::Future, pin::Pin, collections::HashMap};
use tracing::{debug, info, error};
use futures::{FutureExt, future::BoxFuture};
pub struct Interaction {
r#type: String,
}
#[derive(Default)]
pub struct App {
router: Router,
shortcuts: HashMap<String, Box<dyn Fn(Interaction) -> BoxFuture<'static, ()>>>
}
impl App {
pub fn new() -> Self {
Self::default()
}
async fn handle_interaction(
&self,
Json(interaction): Json<Interaction>
) -> StatusCode {
let t = interaction.r#type.clone();
debug!("Got shortcut");
debug!("{t}");
let closure = self.shortcuts.get(&t).unwrap();
tokio::task::spawn(closure(interaction));
StatusCode::OK
}
pub fn add_shortcut<C, Fut>(
mut self,
callback_id: &str,
fun: C,
) -> Self
where
Fut: Future<Output = ()> + Send + 'static,
C: Fn(Interaction) -> Pin<Box<Fut>>,
{
self.shortcuts.insert(callback_id.to_string(), Box::new(move |interaction| Box::pin(fun(interaction))));
self
}
async fn start(self, addr: SocketAddr) {
let interaction_handler = move |interaction| async move {
self.handle_interaction(interaction).await
};
// ERROR: `interaction_handler` doesn't match axums route-types... Don't know why this is the case either.
let router = Router::new()
.route("/", post(interaction_handler));
debug!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(self.router.into_make_service())
.await
.unwrap();
}
}
async fn shortcut1(i: Interaction) {
println!("Hello, World!");
}
async fn shortcut2(i: Interaction) {
println!("Hello, Other World!")
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
// ERROR: `shortcut1` and `shortcut2` doesn't match input type,
// and i don't know how to do this properly.
let app = App::new()
.add_shortcut("shortcut1", shortcut1)
.add_shortcut("shortcut2", shortcut2);
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
app.start(addr).await;
}
其中很多是跟踪和错误、chatgpt 和随机文档的结果——我不熟悉 box、pin 和类似的东西。
我也读过 Mutex 或 Arc 可能有助于解决问题,但我也无法让它工作。
我希望这里有人能帮我指明正确的方向!