You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust Axum后端共享可变状态实现及编译错误求助

关于Axum共享状态与Handler编译错误的问题

背景

我正在基于Axum和HTMX开发类ChatGPT网站,在Axum后端实现共享可变状态时遇到困难。参考了Axum官方的键值存储示例,但克隆后无法编译,担心参考了过时资料。

当前main函数代码与疑惑

我的main()函数代码如下:

pub type SharedState = Arc<RwLock<AppState>>;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AppState {
    chats: Vec<Chat>,
    current_chat_idx: u8,
}

#[tokio::main]
async fn main() {
    let state = SharedState::default();
    let router: Router<()> = Router::new()
        .route("/", get(home))
        .route("/chat/:current_agent", get(chat))
        .route("/snippets/chat_list", get(chat_list))
        .route("/snippets/chat_buttons", get(chat_buttons))
        .route("/snippets/chat_history", get(chat_history))
        .layer(Extension(state))
        .with_state(AppState::default());
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(router.into_make_service())
        .await
        .unwrap();
}

这段代码能编译运行,但我有个疑问:既然通过.layer()已经能访问SharedState结构体,为什么还要用.with_state()传入另一个AppState实例?这是不是内存浪费且无意义的操作?

正常工作的端点代码

我编写的部分端点使用state: Extension<SharedState>作为参数,能正常编译且网页端工作正常:

pub async fn chat_history(state: Extension<SharedState>) -> Html<String> {
    let mut shared_state = state.write().unwrap();
    let agent = shared_state.current_agent();

    let messages: Vec<MessageRender> = agent
        .memory
        .cache()
        .as_ref()
        .into_iter()
        .map(|m| MessageRender::from(m))
        .collect();

    let template = fs::read_to_string("src/html/snippets/chat_history.html").unwrap();
    let r = render!(&template, messages => messages);
    Html(r)
}
pub async fn chat_list(state: Extension<SharedState>) -> Html<String> {
    let shared_state = state.read().unwrap();
    let current_chat_name = &shared_state.current_chat().name;
    println!(
        "Chat list current name, idx: {}, {}",
        current_chat_name,
        state.read().unwrap().current_chat_idx
    );

    let template = fs::read_to_string("src/html/snippets/chat_list.html").unwrap();
    let r = render!(&template,chats => shared_state.chats, current_chat_name => current_chat_name );
    Html(r)
}

编译错误的端点与问题

但当我尝试编译如下端点时:

pub async fn post_prompt(
    state: Extension<super::SharedState>,
    Form(prompt): Form<PromptForm>,
) -> Html<String> {
    let mut shared_state = state.write().unwrap();
    let agent = shared_state.current_agent();

    let res = agent.prompt(prompt.user_input).await;
    if let Ok(response) = res {
        println!("{}", response);
    }
    Html(String::new())
}

出现以下错误:

error[E0277]: the trait bound `fn(axum::Extension<Arc<std::sync::RwLock<AppState>>>, Form<PromptForm>) -> impl Future<Output = axum::response::Html<std::string::String>> {api::post_prompt}: Handler<_, _, _>` is not satisfied
   --> src/main.rs:83:58
    |
83  |         .route("/chat/:current_agent/prompt_agent", post(post_prompt))
    |                                                     ---- ^^^^^^^^^^^ the trait `Handler<_, _, _>` is not implemented for fn item `fn(axum::Extension<Arc<std::sync::RwLock<AppState>>>, Form<PromptForm>) -> impl Future<Output = axum::response::Html<std::string::String>> {api::post_prompt}`
    |                                                     |
    |                                                     required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S, B>`:
              <Layered<L, H, T, S, B, B2> as Handler<T, S, B2>>
              <MethodRouter<S, B> as Handler<(), S, B>>

我尝试移除Form参数,仅保留Extension参数,但仍遇到相同错误,恳请帮助。

内容的提问来源于stack exchange,提问作者voidkandy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 21:16:09