1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use rocket::response::{Response, Responder};
use rocket::http::{Status, ContentType};
use rocket::request::Request;
use std::result;
use std::sync::Arc;
use std::path::PathBuf;
use std::io;
use sized_file::SizedFile;
#[derive(Debug, Clone)]
pub struct CachedFile {
pub(crate) path: PathBuf,
pub(crate) file: Arc<SizedFile>,
}
impl CachedFile {
pub fn open(path: PathBuf) -> io::Result<CachedFile> {
let sized_file: SizedFile = SizedFile::open(&path)?;
Ok(CachedFile {
path,
file: Arc::new(sized_file)
})
}
#[inline]
pub(crate) fn set_response_body(self, response: &mut Response) {
let file: *const SizedFile = Arc::into_raw(self.file);
unsafe {
response.set_streamed_body((*file).bytes.as_slice());
let _ = Arc::from_raw(file);
}
}
}
impl Responder<'static> for CachedFile {
fn respond_to(self, _: &Request) -> result::Result<Response<'static>, Status> {
let mut response = Response::new();
if let Some(ext) = self.path.extension() {
if let Some(ct) = ContentType::from_extension(&ext.to_string_lossy()) {
response.set_header(ct);
}
}
self.set_response_body(&mut response);
Ok(response)
}
}