Rust 如何设置;“到期”;或;“缓存控制”;使用actix文件提供静态文件时的标头?

Rust 如何设置;“到期”;或;“缓存控制”;使用actix文件提供静态文件时的标头?,rust,cache-control,actix-web,Rust,Cache Control,Actix Web,我想使用设置静态文件的缓存TTL 与Nginx config类似:expires max将添加这样的标题:过期时间:2037年12月31日星期四23:55:55 GMT 如何使用actix\u文件 use actix_files::Files; use actix_web::{App, HttpServer, web, HttpResponse, http, cookie, middleware}; #[actix_web::main] async fn main() { HttpSe

我想使用设置静态文件的缓存TTL

与Nginx config类似:
expires max将添加这样的标题:
过期时间:2037年12月31日星期四23:55:55 GMT

如何使用
actix\u文件

use actix_files::Files;
use actix_web::{App, HttpServer, web, HttpResponse, http, cookie, middleware};

#[actix_web::main]
async fn main() {
    HttpServer::new(move || {
        App::new()
            .wrap(middleware::Logger::default())
            .wrap(middleware::Compress::default())
            .service(Files::new("/dist", "dist/"))
    })
        .bind("0.0.0.0:8080").unwrap()
        .run()
        .await.unwrap();
}

我建议的方法是通过。 使用
.wrap\fn
可以减少此代码的冗长程度

use actix_files::Files;
use actix_service::{Service, Transform};
use actix_web::{
    dev::ServiceRequest,
    dev::ServiceResponse,
    http::header::{HeaderValue, EXPIRES},
    middleware, web, App, Error, HttpServer,
};
// use actix_http::http::header::Expires;
use futures::{
    future::{ok, Ready},
    Future,
};

use std::pin::Pin;
use std::task::{Context, Poll};

struct MyCacheInterceptor;

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

    fn new_transform(&self, service: S) -> Self::Future {
        ok(MyCacheInterceptorMiddleware { service })
    }
}

pub struct MyCacheInterceptorMiddleware<S> {
    service: S,
}

impl<S, B> Service for MyCacheInterceptorMiddleware<S>
where
    S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Request = ServiceRequest;
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = Pin<Box<dyn Future<Output = 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 fut = self.service.call(req);

        Box::pin(async move {
            let mut res = fut.await?;
            let headers = res.headers_mut();
            headers.append(
                EXPIRES,
                HeaderValue::from_static("Thu, 31 Dec 2037 23:55:55 GMT"),
            );
            return Ok(res);
        })
    }
}

#[actix_web::main]
async fn main() {
    HttpServer::new(move || {
        App::new()
            .wrap(middleware::Logger::default())
            .wrap(middleware::Compress::default())
            .service(
                web::scope("/dist")
                    .wrap(MyCacheInterceptor)
                    .service(Files::new("", ".").show_files_listing()),
            )
    })
    .bind("0.0.0.0:8080")
    .unwrap()
    .run()
    .await
    .unwrap();
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::{test, web, App};

    #[actix_rt::test]
    async fn test_expire_header() {
        let mut app = test::init_service(
            App::new().service(
                web::scope("/")
                    .wrap(MyCacheInterceptor)
                    .service(Files::new("", ".").show_files_listing()),
            ),
        )
        .await;
        let req = test::TestRequest::with_header("content-type", "text/plain").to_request();
        let resp = test::call_service(&mut app, req).await;
        assert!(resp.status().is_success());
        assert!(resp.headers().get(EXPIRES).is_some());
        assert_eq!(
            resp.headers().get(EXPIRES).unwrap(),
            HeaderValue::from_static("Thu, 31 Dec 2037 23:55:55 GMT"),
        );
    }
}
使用actix_文件::文件;
使用actix_服务::{service,Transform};
使用actix_web::{
dev::ServiceRequest,
dev::ServiceResponse,
http::header::{HeaderValue,EXPIRES},
中间件、web、应用程序、错误、HttpServer、,
};
//使用actix_http::http::header::Expires;
使用期货:{
未来:{好的,准备好了},
未来,,
};
使用std::pin::pin;
使用std::task::{Context,Poll};
结构MyCacheInterceptor;
MyCacheInterceptor的impl转换
哪里
S:服务,
未来:“静态,
B:静态,
{
类型请求=服务请求;
类型响应=服务响应;
类型错误=错误;
类型InitError=();
类型转换=MyCacheInterceptorMiddleware;
输入Future=Ready;
fn新的_转换(&self,service:S)->self::未来{
ok(MyCacheInterceptorMiddleware{service})
}
}
发布结构MyCacheInterceptorMiddle{
服务:S,,
}
MyCacheInterceptorMiddle软件的impl服务
哪里
S:服务,
未来:“静态,
B:静态,
{
类型请求=服务请求;
类型响应=服务响应;
类型错误=错误;
类型Future=Pin;
fn轮询准备就绪(&mut-self,cx:&mut-Context)