如何在没有明确终生的情况下脱落生锈?
我需要一种方法来使重要的数据在整个应用程序中可以读取可读取的线程安全。
我的Web应用程序与Actix-Web一起使用。应用程序启动时,请先预取许可数据。为了有用,请求周期必须能够访问此数据并测试当前用户。
示例:
#[get("/forums/{forum}/")]
pub async fn view_forum(client: ClientCtx) -> Result<impl Responder, Error> {
if !client.can_view_forum() {
// return error
}
// ...
权限数据可作为app_data提供给Actix-Web Web服务器,因此可能会起作用。
#[get("/forums/{forum}/")]
pub async fn view_forum(
client: ClientCtx,
permissions: web::Data<PermissionData>,
) -> Result<impl Responder, Error> {
if !permissions.can_view_forum(client) {
// return error
}
// ...
我想尽可能避免增加路线功能签名的大小。我将需要在用户也可以访问的任何地方都可以访问权限。
允许data
很大,clientctx
的用户数据都会在每个请求上取出。将数据直接撤回每个请求都是不切实际的。
Actix-Web的中间件系统在请求周期中创建了这些结构。它的工作方式使客户无法将其附加到客户端人。
pub struct ClientCtxInner<'a> {
pub client: Option<ClientUser>,
pub permission: &PermissionData, // Doesn't work.
pub request_start: Instant,
}
简而言之:
- 用户永不需要写入权限。它只需要阅读它们即可。
- 始终在所有线程上的许多用户都会读取相同的数据。
- 我不能使用正常的生命。
- 如果出于组织原因,我非常希望通过客户结构直接访问数据。
这是中间件组装客户端的地方。
fn call(&self, req: ServiceRequest) -> Self::Future {
let (httpreq, payload) = req.into_parts();
let cookies = Session::extract(&httpreq).into_inner();
let req = ServiceRequest::from_parts(httpreq, payload);
let permissions: Option<&PermissionData> = req.app_data::<PermissionData>(); // My data!
let ctx = ClientCtx::get_client_ctx(&mut *req.extensions_mut());
let fut = self.service.call(req);
async move {
match cookies {
Ok(cookies) => {
let result = authenticate_client_ctx(&cookies).await;
// Data needs to be attached here.
// ctx.0.borrow_mut().permissions = ???;
// Assign the user to our ClientCtx struct.
if let Some(user) = result {
ctx.0.borrow_mut().client = Some(user);
}
}
Err(e) => {
log::error!("ClientCtxMiddleware: Session::extract(): {}", e);
}
};
let result = fut.await?;
Ok(result)
}
.boxed_local()
}
I need a way to make important data read-accessible, thread-safe throughout my application.
My web application in Rust with Actix-Web. Permission data is prefetched when the application starts. To be useful, the request cycle must be able to access this data and test if the current user.
Example:
#[get("/forums/{forum}/")]
pub async fn view_forum(client: ClientCtx) -> Result<impl Responder, Error> {
if !client.can_view_forum() {
// return error
}
// ...
The permission data is made available to the Actix-Web web server as app_data, so this might work.
#[get("/forums/{forum}/")]
pub async fn view_forum(
client: ClientCtx,
permissions: web::Data<PermissionData>,
) -> Result<impl Responder, Error> {
if !permissions.can_view_forum(client) {
// return error
}
// ...
I would like to avoid increasing the size of my route function signatures as much as possible. I will need permissions accessible everywhere the user is also accessible.
PermissionData
is quite large and ClientCtx
's user data is pulled on every request. Refetching data directly to the client every request is not practical.
Actix-Web's middleware system creates these structs during the request cycle. It works in such a way that lifetimes cannot be attached to the ClientUser.
pub struct ClientCtxInner<'a> {
pub client: Option<ClientUser>,
pub permission: &PermissionData, // Doesn't work.
pub request_start: Instant,
}
In short:
- The user never needs to write to permissions. It just needs to read them.
- Many users on all threads at all times will be reading this same data.
- I can't use normal lifetimes.
- I would very much prefer if the data is accessible directly through the Client struct for organization reasons.
This is where the middleware assembles the client.
fn call(&self, req: ServiceRequest) -> Self::Future {
let (httpreq, payload) = req.into_parts();
let cookies = Session::extract(&httpreq).into_inner();
let req = ServiceRequest::from_parts(httpreq, payload);
let permissions: Option<&PermissionData> = req.app_data::<PermissionData>(); // My data!
let ctx = ClientCtx::get_client_ctx(&mut *req.extensions_mut());
let fut = self.service.call(req);
async move {
match cookies {
Ok(cookies) => {
let result = authenticate_client_ctx(&cookies).await;
// Data needs to be attached here.
// ctx.0.borrow_mut().permissions = ???;
// Assign the user to our ClientCtx struct.
if let Some(user) = result {
ctx.0.borrow_mut().client = Some(user);
}
}
Err(e) => {
log::error!("ClientCtxMiddleware: Session::extract(): {}", e);
}
};
let result = fut.await?;
Ok(result)
}
.boxed_local()
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论