gpt4 book ai didi

rust - 如何在actix-web 2.0中间件中获取web::Data >?

转载 作者:行者123 更新时间:2023-12-03 11:47:48 25 4
gpt4 key购买 nike

通常,我可以像这样在App上设置数据并从web::Data获取数据:

let pool = sqlx::MySqlPool::connect("mysql://xxx")
.await
.expect("Mysql Connect error!");
HttpServer::new(move || {
// set the data pool: Pool<MySQL>
App::new()
.data(pool.clone())
.service(web::resource("/home").route(web::get().to(get_xxx)))
})
.bind("0.0.0.0:8000")?
.run()
.await;
// get the data: pool: Pool<MySQL> from argument.
pub async fn get_xxx(
pool: web::Data<Pool<MySql>>,
path: web::Path<String>,
) -> Result<HttpResponse, Error> {
let mut pool = pool.clone();
todo!()
}
如何在中间件中获取 pool: Pool<MySQL>
这是一个中间件样本:
use std::task::{Context, Poll};

use actix_service::{Service, Transform};
use actix_web::dev::{ServiceRequest, ServiceResponse};
use actix_web::{Error, HttpResponse};
use futures::future::{ok, Either, Ready};

pub struct CheckLogin;

impl<S, B> Transform<S> for CheckLogin
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
type Transform = CheckLoginMiddleware<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;

fn new_transform(&self, service: S) -> Self::Future {
ok(CheckLoginMiddleware { service })
}
}
pub struct CheckLoginMiddleware<S> {
service: S,
}

use actix_web::http::HeaderValue;
impl<S, B> Service for CheckLoginMiddleware<S>
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Either<S::Future, Ready<Result<Self::Response, Self::Error>>>;

fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}

fn call(&mut self, req: ServiceRequest) -> Self::Future {
let pool = todo!(); // here! how can I get the pool: Pool<MySQL>
}
}
我不知道actix-web如何将参数传递给最终的路由函数。

最佳答案

我认为 req.app_data() 是您想要的。

fn call(&mut self, req: ServiceRequest) -> Self::Future {
let pool = req.app_data::<web::Data<Pool<MySql>>>().unwrap();
// ...
}
当您调用 App::data()时,actix-web会将给定值存储到内部映射中。关键是它的类型。调用 app_data()时,您尝试从此 map 中获取值(value)。

I don't know how actix-web passes the arguments to the final route function.


最终的路由功能只需调用 <ParamType as FromRequest>::from_request即可获取值。例如,当您尝试获取 web::Data时发生了以下情况:
impl<T: 'static> FromRequest for Data<T> {
type Config = ();
type Error = Error;
type Future = Ready<Result<Self, Error>>;

#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
if let Some(st) = req.app_data::<Data<T>>() {
ok(st.clone())
} else {
log::debug!(
"Failed to construct App-level Data extractor. \
Request path: {:?}",
req.path()
);
err(ErrorInternalServerError(
"App data is not configured, to configure use App::data()",
))
}
}
}
您可以看到 from_request内部的 web::Dataweb::Data<T>获取值(您的 req.app_data()参数)。
顺便说一句,我注意到您正在使用 sqlx,其 Pool实际上内部有一个 Arc。但是 Data里面也有一个 Arc。这是多余的。如果您介意的话,可以定义包装类型 Pool,并为其实现 FromRequest特性。

关于rust - 如何在actix-web 2.0中间件中获取web::Data <Pool <MySql >>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64032247/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com