1use std::sync::Arc;
2
3use axum_core::extract::FromRequestParts;
4use http::{StatusCode, request::Parts};
5use tower_cookies::Cookies;
6
7use crate::session::Inner;
8use crate::store::SessionStore;
9use crate::{Id, Session};
10
11impl<S, T> FromRequestParts<S> for Session<T>
13where
14 S: Sync + Send,
15 T: SessionStore,
16{
17 type Rejection = (StatusCode, &'static str);
18
19 async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
20 let session_inner = parts.extensions.get::<Arc<Inner<T>>>().ok_or_else(|| {
21 tracing::error!("session layer not found in the request extensions");
22 (
23 StatusCode::INTERNAL_SERVER_ERROR,
24 "Session not found in the request",
25 )
26 })?;
27
28 let cookie_name = session_inner
30 .cookie_name
31 .ok_or((StatusCode::INTERNAL_SERVER_ERROR, "Missing cookie options"))?;
32
33 let cookies_ext = parts.extensions.get::<Cookies>().ok_or_else(|| {
34 tracing::error!("cookies not found in the request extensions");
35 (
36 StatusCode::INTERNAL_SERVER_ERROR,
37 "Cookies not found in the request",
38 )
39 })?;
40
41 session_inner.set_cookies_if_empty(cookies_ext.to_owned());
42
43 if let Some(cookie) = cookies_ext.get(cookie_name) {
44 let session_id = cookie
45 .value()
46 .parse::<Id>()
47 .map_err(|err| {
48 tracing::warn!(
49 err = %err,
50 "malformed session id"
51 )
52 })
53 .ok();
54 session_inner.set_id(session_id);
55 }
56
57 Ok(Session::new(session_inner.clone()))
58 }
59}