0

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); 
Chris
  • 570
  • 2
  • 9
  • 19
  • 1
    I don't think the example really justifies itself, it looks to be an example demonstrating a way to make the session into a shared mutable reference inside your handler if you need that. But you just want to modify the session so simply... do that. All the sharing stuff is unnecessary. – Masklinn Jul 31 '23 at 16:29
  • 1
    And so is keeping on locking and unlocking the RWLock incidentally, you want to mutate the object so just `write()` the object once, keep a reference to the lock guard and do all your reading from and writing to that, then drop it once you're done with the session to zip it back up. – Masklinn Jul 31 '23 at 16:31
  • 1
    "In the docs of warp_sessions it is said that MemoryStore should not be used in production. What should be used in production instead?" probably your own [`SessionStore`](https://docs.rs/warp-sessions/latest/warp_sessions/trait.SessionStore.html) implementation based on some sort of persistent storage e.g. filesystem, database, ... – Masklinn Jul 31 '23 at 16:33
  • 1
    Actually `MemorySession` and `SessionStore` are just re-exports from [`async-session`](https://github.com/http-rs/async-session), and their readme [lists a few backends](https://github.com/http-rs/async-session#available-session-stores), though surprisingly nothing FS-based. Also from the issues some backends are apparently dead. – Masklinn Jul 31 '23 at 16:38
  • hmm. i dont know - this is the only example in the repo that creates the cookie. My rust is not strong enough with me to question dev provided examples that much. I rather learn from them. I will try to simplify the write procedure. – Chris Jul 31 '23 at 17:29
  • 1
    Nitpick: `.unwrap_or_else(|| "".to_string())` is the same as `.unwrap_or_default()` – jthulhu Aug 01 '23 at 08:09

1 Answers1

1

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:

https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/request.rs#L17

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:

  1. Instead of setting CookieOptions to None in your route definition, set your options there

  2. Keeping None in the route definition, and removing the options override in the route handler entirely

ajp
  • 381
  • 2
  • 4
  • Thank you. That was exactly the issue! Working code at https://github.com/chris-the-wiz/siwe_minimal_rust/ – Chris Aug 14 '23 at 17:20