Anu*_*aki 2 middleware rust actix-web
通常,我可以像这样设置数据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;
Run Code Online (Sandbox Code Playgroud)
// 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!()
}
Run Code Online (Sandbox Code Playgroud)
如何获取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>
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道 actix-web 如何将参数传递给最终的路由函数。
我想req.app_data()这就是你想要的。
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let pool = req.app_data::<web::Data<Pool<MySql>>>().unwrap();
// ...
}
Run Code Online (Sandbox Code Playgroud)
当您调用 时App::data(),actix-web 会将给定值存储到内部映射中。关键是它的类型。当您致电 时app_data(),您会尝试从这张地图中获取价值。
我不知道 actix-web 如何将参数传递给最终的路由函数。
最终的路由函数只是调用<ParamType as FromRequest>::from_request来获取值。例如,当您尝试获取时会发生以下情况web::Data:
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let pool = req.app_data::<web::Data<Pool<MySql>>>().unwrap();
// ...
}
Run Code Online (Sandbox Code Playgroud)
您可以看到在内部from_request,从web::Data获取值(您的web::Data<T>参数)req.app_data()。
顺便说一句,我注意到你正在使用sqlx,它Pool实际上有一个Arc内部。但Data也有Arc内在。这是多余的。如果您介意这一点,您可以定义 的包装类型Pool,并FromRequest为其实现特征。
| 归档时间: |
|
| 查看次数: |
2646 次 |
| 最近记录: |