actix-webのFromRequestでasyncを使う
-
Rust 製のフレームワークである Actix に含まれる FromRequest
。この trait を継承した impl のメソッド from_request
内で async
関数を使いたいときの備忘録です。
リクエストハンドラーが取りうる User
struct を作り、FromRequest
を User
に継承させます。is_authorized
が async 関数です。
src/models/user.rs
use actix_web::dev::Payload;
use actix_web::error::ErrorUnauthorized;
use actix_web::{Error, FromRequest, HttpRequest};
use serde::{Deserialize, Serialize};
use std::future::Future;
use std::pin::Pin;
#[derive(Deserialize, Serialize, Debug)]
pub struct User {
pub uid: String,
}
impl FromRequest for User {
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
type Config = ();
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
Box::pin(async move {
// async function
match is_authorized("token_value").await {
Ok(_) => Ok(User {
uid: "abcde".to_string(),
}),
Err(_) => Err(ErrorUnauthorized("Unauthorized")),
}
})
}
}
async fn is_authorized(_: &str) -> Result<(), ()> {
Ok(())
}
src/main.rs
#[get("/me")]
async fn me(user: models::user::User) -> HttpResponse {
HttpResponse::Ok().json(user)
}
// => { "uid": "abcde" }
ちなみに Box::pin
を使わなければ以下のようなエラーによりコンパイルできません。
src/models/user.rs
impl FromRequest for User {
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
type Config = ();
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
// async fn is_authorized(_: &str) -> Result<(), ()>
// `await` is only allowed inside `async` functions and blocks
// only allowed inside `async` functions and blocksrustc(E0728)
match is_authorized("token_value").await {
Ok(_) => Ok(User {
uid: "user_id".to_string(),
}),
Err(_) => Err(ErrorUnauthorized("Unauthorized")),
}
}
}