2016-09-12 08:51:02 +00:00
|
|
|
use std::fs::File;
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use std::io;
|
2016-09-12 09:43:34 +00:00
|
|
|
use std::ops::{Deref, DerefMut};
|
2016-09-12 08:51:02 +00:00
|
|
|
|
2016-10-25 09:17:49 +00:00
|
|
|
use response::{Responder, Outcome};
|
2016-10-04 00:09:13 +00:00
|
|
|
use http::hyper::{header, FreshHyperResponse};
|
|
|
|
use http::ContentType;
|
|
|
|
|
2016-09-12 09:43:34 +00:00
|
|
|
#[derive(Debug)]
|
2016-09-12 08:51:02 +00:00
|
|
|
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))
|
|
|
|
}
|
|
|
|
|
2016-09-25 11:07:03 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn file(&self) -> &File {
|
|
|
|
&self.1
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn file_mut(&mut self) -> &mut File {
|
|
|
|
&mut self.1
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2016-09-12 08:51:02 +00:00
|
|
|
pub fn path(&self) -> &Path {
|
|
|
|
self.0.as_path()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Responder for NamedFile {
|
2016-10-25 09:17:49 +00:00
|
|
|
fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
2016-09-12 08:51:02 +00:00
|
|
|
if let Some(ext) = self.path().extension() {
|
|
|
|
let ext_string = ext.to_string_lossy().to_lowercase();
|
2016-09-25 09:51:18 +00:00
|
|
|
let content_type = ContentType::from_extension(&ext_string);
|
|
|
|
if !content_type.is_any() {
|
|
|
|
res.headers_mut().set(header::ContentType(content_type.into()));
|
2016-09-12 08:51:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-25 11:07:03 +00:00
|
|
|
self.file_mut().respond(res)
|
2016-09-12 08:51:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-12 09:43:34 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-25 11:07:03 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2016-09-30 22:20:11 +00:00
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
|
|
self.file().flush()
|
|
|
|
}
|
2016-09-25 11:07:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2016-09-30 22:20:11 +00:00
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
|
|
self.file().flush()
|
|
|
|
}
|
2016-09-25 11:07:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> io::Seek for &'a NamedFile {
|
|
|
|
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
|
|
|
self.file().seek(pos)
|
|
|
|
}
|
|
|
|
}
|