Example of session while using tower_cookies and axum?
SylvainMartel opened this issue · 6 comments
Hi, when using the flash crate in axum, we also have to use the crate tower_cookies too for cookie management. As such, the session example in the axum repo will not work(I remember reading somewhere that tower_cookies kinda override any cookies made by other means?).
Right now, I have no idea how to get current cookies while inside axum FromRequest implementation. When I do a cookies.list()) in the FromRequest implementation, it shows an Empty list even though there are 2 cookies that were created upon the user logging in(I can see them correctly in the browser.)
Having an example of session using tower-cookies would be much appreciated :)
Hey :) If you see cookies in the browser, cookies.list()
should certainly work. Check if middlewares are initialized correctly and are in a meaningful order. Check if you can see these cookies using extractor: async fn handler(cookies: Cookies)
. If it won't help you can simplify and share your code and I'll check it.
Hi, thanks for the reply. Yes, I can see and grab the cookies normally inside a handler, but not inside a "FromRequest" implementation. I'm no dev, so it might be something trivial that I am missing. :)
This simple route works fine:
async fn greet(
extract::Path(name): extract::Path<String>,
cookies: Cookies,
) -> HelloTemplate {
dbg!(&cookies.list()); //<<<<<- The cookie is seen correctly
let template = HelloTemplate { name };
template
}
But if I want to see the cookies through another FromRequest (like the jwt example,or the session example) then I cannot see the cookie from inside that implementation:
async fn greet(
extract::Path(name): extract::Path<String>,
cookies: Cookies,
claim: Claims, //<<<<<<<<<<<<<------- This verifies the jwt token, but since it's inside a cookie I need to get the cookies too
) -> HelloTemplate {
let template = HelloTemplate { name };
template
}
pub struct Claims {
pub sub: String,
pub role: String,
pub exp: i64,
}
impl Display for Claims {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Email: {}\nRole: {}", self.sub, self.role)
}
}
#[async_trait]
impl<B> FromRequest<B> for Claims
where
B: Send,
{
type Rejection = AuthError;
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
let cookies = Cookies::default();
dbg!(&cookies.list()); // <<<<<<< --- Empty
//code to extract token and verify it
Ok(token_data.claims)
}
}
and the loading order:
let app = Router::new()
//snip all trhe routes
.layer(
ServiceBuilder::new()
.layer(CookieManagerLayer::new())
.layer(AddExtensionLayer::new(shared_state))
.layer(axum_flash::layer(key).with_cookie_manager()),
);
To get an extension inside the FromRequest, we usually have to use something like let Extension(user_state) = Extension::<Arc<UserState>>::from_request(req)
but I cannot find a way to make it work with CookieManagerLayer.
I'd say it's rather courageous to use rust not being a dev 🙇
The problem is in Cookies::default()
- it knows nothing about headers, so it just creates a new empty jar. I've added an example how to use already initialized one instead: https://github.com/imbolc/tower-cookies/blob/main/examples/counter-extractor.rs#L24-L33
That did it :) Huge thanks! I learned a new way to call extensions too(and indeed, reading the RequestParts doc clearly shows it's part of that struct.)
Yes, Rust can be a bit daunting for a hobbyist like me, but somehow, it's what click the most for me syntax wise. Before moving to pure electronic and then IT, I learned basic programming in college in the mid-90's with Quick Basic, Assembly and C, and Rust feels just "right" for me with that background. What I lack is all the years of experience devs have reading API docs, or all the coding patterns you learn as you go on. I did a small gym software for a friend in python(django) and was looking at another language to make it faster, so I tired GO, but I simply cannot wrap my head around the signature of a function in GO. The brain refuses to compute it :P So Rust it is. Even with the struggles, I like it alot, and the fact that there isn't really any fully mature framework yet forces me to learn what's under the hood. I just wish there was a complete book on what "subsystems" you have to make for a modern web app. The closest I have found so far is "Let's Go" by Alex Edwards.
But enough babbling, time to go extract the info from that cookie :D
I'd agree completely, Rust seem to be the best mainstream language right now. The learning curve could be quite overwhelming though :) But after I lower my anticipations and take my time, it always feels more than rewarding.
Have you seen this book: https://www.zero2prod.com/
Have you seen this book: https://www.zero2prod.com/
I just pulled the triggeron that one and finally got it. Chapter 10 is about session so it is indeed a good time to get it :)