英文:
Data stored in warp Session does not persist [SOLVED - but don't know why]
问题
我在我的Rust之旅的开头。尝试设置服务器后端作为一项练习。我卡住了。请帮帮我。
我试图将一些数据存储在warp_sessions::MemoryStore
中,但我无法实现它。我以warp_sessions/examples/shared_mutable_session
示例为基础。
我可以将数据写入会话中。我可以在写入后立即读取它(在下面的代码中的变量_a
和_b
),但它们在调用之间不会保留。在连续的处理程序调用上,变量_a_pre
和_b_pre
返回空字符串。
现在的问题是:
-
我做错了什么?[代码如下]
-
如果我想在不同的路由中使用相同的会话,并且我将
session_store.clone()
传递给过滤器,就像在warp示例中一样,会话的修改会被保存吗?目前我不使用存储的克隆实例,但数据仍然丢失。然而,我确实需要数据被不同的路由使用。 -
在warp_sessions的文档中说
MemoryStore
不应该在生产中使用。在生产中应该使用什么?
我的路由处理函数如下:
pub async fn verify_handler(body: warp::hyper::body::Bytes, mut session_with_store: SessionWithStore<MemoryStore>) -> Result<(Html<String>, SessionWithStore<MemoryStore>), Rejection> {
session_with_store.cookie_options = warp_sessions::CookieOptions {
cookie_name: "siwe_minimal",
cookie_value: None,
max_age: Some(3600),
domain: None,
path: None,
secure: true,
http_only: true,
same_site: Some(SameSiteCookieOption::Strict),
};
let shared_session = Arc::new(RwLock::new(session_with_store.session));
let _a_pre: String = shared_session
.read()
.unwrap()
.get("nonce")
..unwrap_or_default();
shared_session
.write()
.unwrap()
.insert("nonce", nonce )
.unwrap();
let _a: String = shared_session
.read()
.unwrap()
.get("nonce")
.unwrap();
let msgstr = message.to_string();
let _b_pre: String = shared_session
.read()
.unwrap()
.get("siwe")
..unwrap_or_default();
shared_session
.write()
.unwrap()
.insert("siwe", msgstr)
.unwrap();
let _b: String = shared_session
.read()
.unwrap()
.get("siwe")
.unwrap();
session_with_store.session = Arc::try_unwrap(shared_session)
.unwrap()
.into_inner()
.unwrap();
Ok::<_, Rejection>(
(
warp::reply::html("req".to_string()),
session_with_store
)
)
}
路由定义如下(如果有关系的话):
let session_store = MemoryStore::new();
let verify_route
= warp::path("verify")
.and(warp::post())
.and(warp::body::bytes())
.and(warp_sessions::request::with_session(session_store, None))
.and_then(verify_handler)
.untuple_one()
.and_then(warp_sessions::reply::with_session)
.recover(handle_rejection)
.with(&cors);
更新:
有趣的是,当我从lambda中调用处理程序时,它可以工作。不过我不知道为什么:
let verify_route
= warp::path("verify")
.and(warp::post())
.and(warp::body::bytes())
.and(warp_sessions::request::with_session(session_store, None))
.and_then(move |body: warp::hyper::body::Bytes, mut session_with_store: SessionWithStore<MemoryStore>| async move {
let result = verify_handler(body, session_with_store.clone()).await.unwrap();
Ok::<_, Rejection>((
warp::reply::html("_foo".to_string()),
session_with_store,
))
},
)
.untuple_one()
.and_then(warp_sessions::reply::with_session)
.with(&cors);
英文:
I am at the beginning of my Rust journey. Trying to set up a server backend as an exercise. I am stuck. Please help.
I am trying to store some data in warp_sessions::MemoryStore but I cannot achieve it. I base on the warp_sessions/examples/shared_mutable_session example.
I can get the data written into the session. I can read it back immediately after I write into it (variables _a
and _b
in the code below), but they don't persist between the calls. The variables _a_pre
and _b_pre
return empty string on the consecutive handler calls.
Now the questions:
-
What am I doing wrong? [code below]
-
if I want to use the same session for different routes and I pass the
session_store.clone()
in the filter, like it is done in warp example - will the modifications of the session be stored? For now I don't use the cloned instance of the store but the data is lost anyway. I do however need the data to be used by different routes -
In the docs of warp_sessions it is said that MemoryStore should not be used in production. What should be used in production instead?
my route handler function looks like this:
pub async fn verify_handler(body: warp::hyper::body::Bytes, mut session_with_store:SessionWithStore<MemoryStore> ) -> Result<(Html<String>, SessionWithStore<MemoryStore>), Rejection> {
session_with_store.cookie_options = warp_sessions::CookieOptions {
cookie_name: "siwe_minimal",
cookie_value: None,
max_age:Some(3600),
domain: None,
path: None,
secure: true,
http_only: true,
same_site: Some(SameSiteCookieOption::Strict),
};
let shared_session = Arc::new(RwLock::new(session_with_store.session));
let _a_pre: String = shared_session
.read()
.unwrap()
.get("nonce")
..unwrap_or_default();
shared_session
.write()
.unwrap()
.insert("nonce", nonce )
.unwrap();
let _a: String = shared_session
.read()
.unwrap()
.get("nonce")
.unwrap();
let msgstr = message.to_string();
let _b_pre: String = shared_session
.read()
.unwrap()
.get("siwe")
..unwrap_or_default();
shared_session
.write()
.unwrap()
.insert("siwe", msgstr)
.unwrap();
let _b: String = shared_session
.read()
.unwrap()
.get("siwe")
.unwrap();
session_with_store.session = Arc::try_unwrap(shared_session)
.unwrap()
.into_inner()
.unwrap();
Ok::<_, Rejection>(
(
warp::reply::html("req".to_string()),
session_with_store
)
)
}
the route is defined like this (if it matters):
let session_store = MemoryStore::new();
let verify_route
= warp::path("verify")
.and(warp::post())
.and(warp::body::bytes())
.and(warp_sessions::request::with_session(session_store, None))
.and_then( verify_handler)
.untuple_one()
.and_then(warp_sessions::reply::with_session)
.recover(handle_rejection)
.with(&cors);
UPDATE:
Interestingly when i call the handler from the lambda, it works. I dont know why though:
let verify_route
= warp::path("verify")
.and(warp::post())
.and(warp::body::bytes())
.and(warp_sessions::request::with_session(session_store, None))
.and_then( move |body: warp::hyper::body::Bytes, mut session_with_store: SessionWithStore<MemoryStore>| async move {
let result = verify_handler(body, session_with_store.clone()).await.unwrap();
Ok::<_, Rejection>((
warp::reply::html("_foo"),
session_with_store,
))
},
)
.untuple_one()
.and_then(warp_sessions::reply::with_session)
.with(&cors);
答案1
得分: 1
看起来你在路由定义中将CookieOptions设置为None,这意味着warp_sessions代码将期望一个名为sid
的Cookie来获取会话ID。显示此行为的代码链接:
然而,在路由处理程序中,你将cookie_options覆盖为一个不同的值,使用的Cookie名称是siwe_minimal
。这意味着在warp_sessions逻辑的回复部分期间,包含会话ID的Cookie将被命名为与路由定义期望的不同的名称。
在warp_sessions回复代码中定义Set-Cookie标头的链接:https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/session.rs#L98
显示CookieOptions的to_string
定义,其中显示了如何使用cookie_name
:https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/cookie.rs#L24
为了解决这个问题,我建议:
-
在你的路由定义中,不要将CookieOptions设置为
None
,而是在那里设置你的选项。 -
保留路由定义中的
None
,并完全删除路由处理程序中的选项覆盖。
英文:
It looks like you're setting the CookieOptions in the route definition to None, meaning that the warp_sessions code will expect a cookie named sid
to get the session ID. Link to code showing this behavior:
However, in the route handler, you override the cookie_options to a different value, with a cookie name of siwe_minimal
. This means that, during the reply portion of the warp_sessions logic, the cookie containing the session ID that will persist your session across calls will be named something different than what the route definition expects.
Link to where Set-Cookie header is defined in the warp_sessions reply code: https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/session.rs#L98
Link to to_string
definition of CookieOptions which shows how cookie_name
is used: https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/cookie.rs#L24
In order to solve this, I would suggest either:
-
Instead of setting CookieOptions to
None
in your route definition, set your options there -
Keeping
None
in the route definition, and removing the options override in the route handler entirely
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论