Rocket: More HTTP headers for NamedFile

Created on 2 Jan 2017  路  2Comments  路  Source: SergioBenitez/Rocket

Hi,

happy new year with successfull Rust projects!

I'm building a little personal project with Rust and Rocket.
I have to serve static pages (js, images) and using the Firefox Inspector (to see how fast is this little app) I saw that static files served with NamedFile are not cached by the browser... as the only HTTP headers are Content-Type, Date, Server and Transfert-Encoding.

I thing that at least the header Last-Modified should be added (maybe also Expires and Cache-Control).

I'm still new to Rust and do not know how to derive/override the standard NamedFile to add the header using Response.set_header().
Looking at NamedFile source, it seems that adding new header could be done inside the original code.

Thanks for your project.

request

Most helpful comment

The code from @majkcramer is now obsolete, I've found this way to do it with current Rocket:

struct CachedFile(NamedFile);

impl<'r> Responder<'r> for CachedFile {
    fn respond_to(self, req: &Request) -> response::Result<'r> {
        Response::build_from(self.0.respond_to(req)?)
            .raw_header("Cache-control", "max-age=86400") //  24h (24*60*60)
            .ok()
    }
}

#[get("/resources/<file..>")]
fn files(file: PathBuf) -> Option<CachedFile> {
    NamedFile::open(Path::new("resources/").join(file)).ok().map(|nf| CachedFile(nf))
}

All 2 comments

@eliovir: In the meantime i found a 'dirty' and maybe expensive workarround to fulfill our need.

#[get("/static/<file..>")]
fn files<'a>(file: PathBuf) -> Response<'a>
{
    let result_read: io::Result<NamedFile> = NamedFile::open(Path::new("static/").join(file));
    let result_namefile1 = result_read.ok();
    let mut response_build = Response::build();
    match result_namefile1
    {
        None => {  }
        Some(mut nfile) => { 
            let nfile_result: Result<Response,Status> = nfile.respond();
            match nfile_result {
                Ok(nfile_result_response) => {
                    response_build = Response::build_from(nfile_result_response);
                    response_build.raw_header("Cache-control","max-age=86400"); //  24h (24*60*60)
                },
                Err(nfile_result_status) => {
                    response_build.raw_status(nfile_result_status.code, nfile_result_status.reason);
                },
            }
        }
    }
    response_build.finalize()
}

The code from @majkcramer is now obsolete, I've found this way to do it with current Rocket:

struct CachedFile(NamedFile);

impl<'r> Responder<'r> for CachedFile {
    fn respond_to(self, req: &Request) -> response::Result<'r> {
        Response::build_from(self.0.respond_to(req)?)
            .raw_header("Cache-control", "max-age=86400") //  24h (24*60*60)
            .ok()
    }
}

#[get("/resources/<file..>")]
fn files(file: PathBuf) -> Option<CachedFile> {
    NamedFile::open(Path::new("resources/").join(file)).ok().map(|nf| CachedFile(nf))
}
Was this page helpful?
0 / 5 - 0 ratings