use std::io;
use std::path::{Path, PathBuf};
use std::ops::{Deref, DerefMut};
use tokio::fs::File;
use crate::request::Request;
use crate::response::{self, Responder};
use crate::http::ContentType;
#[derive(Debug)]
pub struct NamedFile(PathBuf, File);
impl NamedFile {
pub async fn open<P: AsRef<Path>>(path: P) -> io::Result<NamedFile> {
let file = File::open(path.as_ref()).await?;
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 take_file(self) -> File {
self.1
}
#[inline(always)]
pub fn path(&self) -> &Path {
self.0.as_path()
}
}
impl<'r> Responder<'r, 'static> for NamedFile {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
let mut response = self.1.respond_to(req)?;
if let Some(ext) = self.0.extension() {
if let Some(ct) = ContentType::from_extension(&ext.to_string_lossy()) {
response.set_header(ct);
}
}
Ok(response)
}
}
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
}
}