app fails to compile after adding an extra await point in middleware::from_fn
#3544
Answered
by
mladedav
sumit-modak
asked this question in
Q&A
-
Version0.8.6 PlatformDescriptionI have been getting this error error[E0277]: the trait bound `FromFn<fn(..., ...) -> ... {auth_middleware}, (), ..., _>: Service<...>` is not satisfied
--> server/src/lib.rs:22:16
|
22 | .layer(axum::middleware::from_fn(middleware::auth_middleware))
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `tower_service::Service<axum::http::Request<Body>>` is not implemented for `FromFn<fn(Request<Body>, Next) -> ... {auth_middleware}, (), ..., _>`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `tower_service::Service<Request>`:
axum::middleware::FromFn<F, S, I, (T1, T2)>
axum::middleware::FromFn<F, S, I, (T1, T2, T3)>
axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4)>
axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5)>
axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6)>
axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7)>
axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7, T8)>
axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7, T8, T9)>
and 8 others
note: required by a bound in `Router::<S>::layer`
--> /home/sumit/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axum-0.8.6/src/routing/mod.rs:306:21
|
303 | pub fn layer<L>(self, layer: L) -> Router<S>
| ----- required by a bound in this associated function
...
306 | L::Service: Service<Request> + Clone + Send + Sync + 'static,
| ^^^^^^^^^^^^^^^^ required by this bound in `Router::<S>::layer`
= note: the full name for the type has been written to '/home/sumit/dev/main/basic-auth/target/debug/deps/server-1f7a443a9073956d.long-type-7524813056611610554.txt'
= note: consider using `--verbose` to print the full type name to the consoleand this is the middleware code use axum::{extract::Request, http::header, middleware::Next, response::Response};
use common::{
AppError,
user_session::{self, ActiveUserSession, UserSessionStatus},
};
pub async fn auth_middleware(mut req: Request, next: Next) -> Result<Response, AppError> {
// collecting all the user sent cookie headers into `cookies`
let cookies = req
.headers()
.get_all(header::COOKIE)
.iter()
.map(|h| h.to_str().unwrap_or_default().to_string())
.collect::<Vec<String>>();
// parsing all user sent cookies to create a valid `ActiveUserSession`
let active_user_session = ActiveUserSession::parse(&cookies)?;
// checking whether cookies inside `active_user_session` is tampered or not
let decrypted_ssid = active_user_session.verify()?;
let db = database::Db::new().await;
// when the use is found inside `Db::active`
if let Some(user) = db.get_active_user(&active_user_session) {
req.extensions_mut().insert(active_user_session);
req.extensions_mut().insert(user);
} else {
// when the user is not found inside `Db::active`
match db.get_user_by_decrypted_ssid(&decrypted_ssid).await {
Ok(mut user) => {
let i = user_session::get_session_index(&user.sessions, decrypted_ssid)?;
match user.sessions[i].session_status() {
UserSessionStatus::Valid(_) => {
// adding session and `User` to `Db::active` for faster access
db.make_user_active(active_user_session.clone(), user.clone());
req.extensions_mut().insert(active_user_session);
req.extensions_mut().insert(user);
}
UserSessionStatus::Expiring(_) => {
// when the user session is about to expire
}
UserSessionStatus::Refreshable(_) => {
// automatic session refresh if ssid expiration is not older than `UserSession::MAX_REFRESH_DURATION`
let user_agent = req
.headers()
.get(header::USER_AGENT)
.map(|v| v.to_str().unwrap_or_default().to_owned())
.unwrap_or_default();
// creating session
let (user_session, active_user_session, set_cookie_headermap) =
user_session::create_session(user_agent);
// replacing the old session with new session
user.sessions[i] = user_session;
// updating session in primary database
db.update_sessions(&user.username, &user.sessions).await?;
// activating session by adding it to `Db::active`
db.make_user_active(active_user_session, user);
return Err(AppError::RefreshSession(set_cookie_headermap));
}
UserSessionStatus::Invalid => {
return Err(AppError::InvalidSession(Some(active_user_session.expire())));
}
};
}
Err(e) => return Err(e),
}
}
Ok(next.run(req).await)
}I figured out that, this // updating session in primary database
db.update_sessions(&user.username, &user.sessions).await?;await point in my middleware code is creating this problem let main_router = Router::new()
.route("/api/user/{id}", get(user::get_user))
.layer(axum::middleware::from_fn(middleware::auth_middleware))
.with_state(database::Db::new().await);and this is the pub async fn update_sessions(
self: &Arc<Self>,
username: &str,
sessions: &[UserSession],
) -> Result<(), AppError> {
// Serialize the sessions array slice to Bson
let sessions_bson = mongodb::bson::to_bson(sessions).map_err(|e| {
tracing::error!("Failed to serialize sessions: {e}");
AppError::ServerDefault
})?;
let update = doc! {"username": username};
let filter = doc! {"$set": doc! {"sessions": sessions_bson}};
match self.users.update_one(filter, update).await {
Ok(v) => {
tracing::info!("Updated User Sessions: {:?}", v.upserted_id);
Ok(())
}
Err(e) => {
tracing::error!("{e:?}");
Err(AppError::ServerDefault)
}
}
} |
Beta Was this translation helpful? Give feedback.
Answered by
mladedav
Oct 31, 2025
Replies: 1 comment 2 replies
-
|
@jplatte hey can you say whats the problem? |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You're most likely holding a
!Sendobject across the await point. Using#[debug_middleware]might improve the message.