Мои клиенты авторизуются с помощью токена в заголовке Authorization
, который необходимо проверять для каждого запроса. Если этот заголовок отсутствует или я не могу найти соответствующего пользователя, я хочу вернуть HTTP-код Unauthorized
, иначе я хочу обработать запрос в обычном режиме.
В настоящее время у меня много повторяющегося кода, потому что я проверяю этот заголовок в каждом обработчике запросов. В actix docs в самом первом абзаце говорится, что halt request processing to return a response early
возможно. Как этого добиться?
Поскольку я не нашел примера, реализующего это поведение, я попытался придумать свою собственную функцию промежуточного программного обеспечения, но она не компилируется.
Я уже поместил возвращаемые значения в коробку, чтобы решить проблему возврата двух разных типов (ServiceResponse
и Map
), поэтому проблема задается в Как мне условно вернуть разные типы фьючерсов? не является проблемой. Более того, я не знаю, какие типы и какие реализации трейтов в точности требуются в качестве возвращаемого значения для этой wrap_fn
функции. Те, которые у меня сейчас есть, не работают.
App::new()
.wrap(Cors::new().allowed_origin("http://localhost:8080"))
.register_data(state.clone())
.service(
web::scope("/routing")
.wrap_fn(|req, srv| {
let unauth: Box<dyn IntoFuture<Item = ServiceResponse>> = Box::new(ServiceResponse::new(req.into_parts().0, HttpResponse::Unauthorized().finish()));
let auth_header = req.headers().get("Authorization");
match auth_header {
None => unauth,
Some(value) => {
let token = value.to_str().unwrap();
let mut users = state.users.lock().unwrap();
let user_state = users.iter_mut().find(|x| x.auth.token == token);
match user_state {
None => unauth,
Some(user) => {
Box::new(srv.call(req).map(|res| res))
}
}
}
}
})
.route("/closest", web::get().to(routing::find_closest))
.route("/fsp", web::post().to(routing::fsp))
.route("/preference", web::get().to(routing::get_preference))
.route("/preference", web::post().to(routing::set_preference))
.route("/find_preference", web::post().to(routing::find_preference))
.route("/reset", web::post().to(routing::reset_data)),
)
.bind("0.0.0.0:8000")
.expect("Can not bind to port 8000")
.run()
.expect("Could not start sever");
При компиляции я получаю две ошибки.
1.
error[E0191]: the value of the associated types `Future` (from the trait `futures::future::IntoFuture`), `Error` (from the trait `futures::future::IntoFuture`) must be specified
--> src/server/mod.rs:36:41
|
36 | let unauth: Box<dyn IntoFuture<Item = ServiceResponse>> =
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| associated type `Future` must be specified
| associated type `Error` must be specified
2.
error[E0277]: the trait bound `dyn futures::future::IntoFuture<Item = actix_web::service::ServiceResponse>: futures::future::Future` is not satisfied
--> src/server/mod.rs:35:22
|
35 | .wrap_fn(|req, srv| {
| ^^^^^^^ the trait `futures::future::Future` is not implemented for `dyn futures::future::IntoFuture<Item = actix_web::service::ServiceResponse>`
|
= note: required because of the requirements on the impl of `futures::future::Future` for `std::boxed::Box<dyn futures::future::IntoFuture<Item = actix_web::service::ServiceResponse>>`