【问题标题】:How to use async code in actix-web extractors?如何在 actix-web 提取器中使用异步代码?
【发布时间】:2020-08-10 23:16:30
【问题描述】:

我正在使用 sqlx 在 actix-web 2.0.0 中实现身份验证提取器来访问数据库。我有这个代码:

use actix_web::{dev, web, Error, HttpRequest, FromRequest};
use actix_web::error::ErrorUnauthorized;
use futures::future::{ok, err, Ready};
use sqlx::PgPool;
use serde_derive::Deserialize;

use crate::model::User;

#[derive(Debug, Deserialize)]
pub struct Auth {
    user_id: u32,
}

impl FromRequest for Auth {
    type Error = Error;
    type Future = Ready<Result<Self, Self::Error>>;
    type Config = ();

    fn from_request(req: &HttpRequest, _: &mut dev::Payload) -> Self::Future {
        use actix_web::HttpMessage;

        let db_pool = req.app_data::<web::Data<PgPool>>().unwrap();
        let error = ErrorUnauthorized("{\"details\": \"Please log in\"}");

        if let Some(session_id) = req.cookie("sessionid") {
            log::info!("Session id {}", session_id);
            // let result = User::find_by_session(db_pool.get_ref(), session_id).await;
            ok(Auth { user_id: 0 })
        } else {
            err(error)
        }

    }
}

当然,我不能在那里使用await。我看到了一个使用type Future = Pin&lt;Box&lt;dyn Future&lt;Output = Result&lt;Self, Self::Error&gt;&gt;&gt;&gt; 并返回Box::pin(async move { ... }) 的示例,但我无法使其工作(req 的生命周期存在问题)。

【问题讨论】:

    标签: rust async-await actix-web


    【解决方案1】:

    我设法做到了。我在async move 之前提取了cookie,所以req 没有问题。

    use std::pin::Pin;
    use futures::Future;
    use actix_web::{dev, web, Error, HttpRequest, FromRequest};
    use actix_web::error::ErrorUnauthorized;
    use sqlx::PgPool;
    use serde_derive::Deserialize;
    
    use crate::model::User;
    
    #[derive(Debug, Deserialize)]
    pub struct Auth {
        user_id: u32,
    }
    
    impl FromRequest for Auth {
        type Error = Error;
        type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
        type Config = ();
    
        fn from_request(req: &HttpRequest, _: &mut dev::Payload) -> Self::Future {
            use actix_web::HttpMessage;
    
            let db_pool = req.app_data::<web::Data<PgPool>>().unwrap().clone();
            let cookie = req.cookie("sessionid");
    
            Box::pin(async move {
                let error = Err(ErrorUnauthorized("{\"details\": \"Please log in\"}"));
    
                if let Some(session_id) = cookie {
                    let result = User::find_by_session(db_pool.get_ref(), session_id).await;
                    // auth code
                    Ok(Auth { user_id: 0 })
                } else {
                    error
                }
            })
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-01
      • 1970-01-01
      • 2021-02-02
      • 2022-10-23
      • 1970-01-01
      • 1970-01-01
      • 2020-03-17
      • 2015-01-16
      • 1970-01-01
      相关资源
      最近更新 更多