axum
比较陌生,我正在尝试将其用作我正在创建的服务的网络服务器。
我有一些状态,其中包含我想写入会话/会话元数据的数据库。
我希望访问任何路由的所有用户都设置会话 cookie(如果它尚未出现在标头中)。然后我想将此会话 cookie 写入数据库(以某种状态存储)。
tower_cookies
板条箱,试图使 cookie 读取和写入更符合人体工程学,所以我更希望中间件能够访问 Cookies
结构,而不是读取和写入原始 Request<...>
和Response<...>
。
我所做的所有尝试在某种程度上都是不够的——要么是一个独立的处理程序(而不是自动应用于所有路由的中间件),要么不使用
Cookie
类(并处理原始 Cookie
/ Set-Cookie
直接标头),或类似不符合人体工程学的东西。我觉得这是一件很常见的事情,所以我一定错过了一些东西。对于这些不符合人体工程学但编译方法之一的精炼示例:
// Problem: not using Cookies from the CookieManager, instead dealing with the headers directly.
pub async fn set_and_store_cookie_if_absent<B>(
State(state): State<MyState>,
request: Request<B>,
next: Next<B>,
) -> Response {
// Read request cookies, create / write new session to state.db if needed
let response = next.run(request).await;
// Write to response cookies.
response
}
let state = MyState::new();
Route(...)
.layer(
ServiceBuilder::new()
.layer(CookieManagerLayer::new())
.layer(middleware::from_fn_with_state(state.clone(), set_and_store_cookie_if_absent)));
但这并没有使用我想要使用的
CookieManagerLayer
。
啊,经过一些研究,我尝试的一些方法是正确的,除了我的
State
包装了一种不能很好地与异步配合的类型:https://github.com/tokio-rs/axum/discussions /964#讨论评论-2629585
所以正确的做法是这样的:
pub async fn set_and_store_cookie_if_absent<B>(
State(state): State<MyState>,
cookies: Cookies,
request: Request<B>,
next: Next<B>,
) -> Response {
if cookies.get(SESSION_COOKIE).is_none() {
// handle, write to State, etc.
}
next.run(request).await
}
但这给了我很多以前很难解决的错误——因为我使用的是
rusqlite
而不是 tokio-rusqlite
之类的东西。