Rocket/lib/src/response/named_file.rs

114 lines
2.6 KiB
Rust

use std::fs::File;
use std::path::{Path, PathBuf};
use std::io;
use std::ops::{Deref, DerefMut};
use response::{Responder, Outcome};
use http::hyper::{header, FreshHyperResponse};
use http::ContentType;
#[derive(Debug)]
pub struct NamedFile(PathBuf, File);
impl NamedFile {
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<NamedFile> {
let file = File::open(path.as_ref())?;
Ok(NamedFile(path.as_ref().to_path_buf(), file))
}
#[inline(always)]
pub fn file(&self) -> &File {
&self.1
}
#[inline(always)]
pub fn file_mut(&mut self) -> &mut File {
&mut self.1
}
#[inline(always)]
pub fn path(&self) -> &Path {
self.0.as_path()
}
}
impl Responder for NamedFile {
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
if let Some(ext) = self.path().extension() {
let ext_string = ext.to_string_lossy().to_lowercase();
let content_type = ContentType::from_extension(&ext_string);
if !content_type.is_any() {
res.headers_mut().set(header::ContentType(content_type.into()));
}
}
self.file_mut().respond(res)
}
}
impl Deref for NamedFile {
type Target = File;
fn deref(&self) -> &File {
&self.1
}
}
impl DerefMut for NamedFile {
fn deref_mut(&mut self) -> &mut File {
&mut self.1
}
}
impl io::Read for NamedFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.file().read(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.file().read_to_end(buf)
}
}
impl io::Write for NamedFile {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.file().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.file().flush()
}
}
impl io::Seek for NamedFile {
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
self.file().seek(pos)
}
}
impl<'a> io::Read for &'a NamedFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.file().read(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.file().read_to_end(buf)
}
}
impl<'a> io::Write for &'a NamedFile {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.file().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.file().flush()
}
}
impl<'a> io::Seek for &'a NamedFile {
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
self.file().seek(pos)
}
}