Estou tentando passar o pool de banco de dados que está em State(app_state): State<AppState>
fn authorize
dentro do meu auth.rs
from, api.rs
onde estou usando esse middleware como JWT para proteger minhas URLs assim.
api.rs
pub fn api_routes() -> Router<AppState> {
let route = Router::new()
.route("/api", get(main_page_get).post(main_page_post))
.route("/api/{query}", get(id_page_get))
.route("/demo.json", get(get_demo_json).put(put_demo_json)
.layer(middleware::from_fn(auth::authorize))
);
return route;
}
autor.rs
pub async fn authorize(
mut req: Request<Body>,
State(app_state): State<AppState>,
next: Next
) -> Result<Response<Body>, AuthError> {
Estou recebendo um erro nesta linha middleware::from_fn(auth::authorize)
dizendo:
the trait bound `axum::middleware::FromFn<fn(http::Request<Body>, axum::extract::State<AppState>, Next) -> impl Future<Output = Result<Response<Body>, AuthError>> {authorize}, (), Route, _>: tower_service::Service<http::Request<Body>>` is not satisfied
the trait `tower_service::Service<http::Request<Body>>` is not implemented for `FromFn<fn(Request<Body>, ..., ...) -> ... {authorize}, ..., ..., ...>`
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 othersrustcClick for full compiler diagnostic
api.rs(17, 10): required by a bound introduced by this call
method_routing.rs(967, 21): required by a bound in `MethodRouter::<S, E>::layer`
E não sei por quê, porque a authorize
assinatura parece boa.
EDIT: Meu estado compartilhado é implementado assim
use std::sync::Arc;
use sqlx::postgres::PgPool;
#[derive(Clone)]
pub struct AppState {
pub html_path: Arc<String>,
pub db_pool: Arc<PgPool>,
}
impl AppState {
pub fn new(html_path: String, db_pool: PgPool) -> Self {
AppState {
html_path: Arc::new(html_path),
db_pool: Arc::new(db_pool),
}
}
}
Este é um erro relativamente simples. É assim que o código deve ser
Além disso, PgPool por padrão é clonável, e String também é clonável. Então colocar um Arc em cima desses 2 parece bem inútil. O critério para o estado do aplicativo manter campos arc seria se o campo precisa de modificações no tempo de execução, então você deve introduzir Arc com um RwLock ou Mutex. Quando não se espera que o estado do seu aplicativo mude, usar clone seria suficiente.
Também para auth.rs. O estado deve ser o primeiro parâmetro, depois a solicitação e todas as outras coisas.
editar:
É assim que passo o estado do meu aplicativo para a função do roteador
estado.rs
principal.rs