diff options
Diffstat (limited to 'src/handler/staticfile.rs')
| -rw-r--r-- | src/handler/staticfile.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/handler/staticfile.rs b/src/handler/staticfile.rs new file mode 100644 index 0000000..f208528 --- /dev/null +++ b/src/handler/staticfile.rs @@ -0,0 +1,75 @@ +use crate::{ + handler::{self, Handle}, + request::{Method, Request}, + response::{Body, Response, Status}, +}; + +use std::{ffi::OsString, os::unix::ffi::OsStringExt, path::PathBuf}; + +use mlua::{FromLua, Value}; + +use tokio::{ + fs::File, + io::{self}, +}; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("io error: {0}")] + Io(#[from] io::Error), +} + +#[derive(Debug, Clone)] +pub struct StaticFile { + path: PathBuf, + mime: String, +} + +impl Handle for StaticFile { + async fn handle(self, request: Request) -> Result<Response, handler::Error> { + match request.method() { + Method::Get | Method::Head => match File::open(&self.path).await { + Ok(file) => { + let metadata = file.metadata().await.map_err(Error::Io)?; + + if metadata.is_file() { + Ok(Response::builder() + .status(Status::Ok) + .headers([ + ("content-length", format!("{}", metadata.len())), + ("content-type", self.mime), + ]) + .body(match request.method() { + Method::Get => Body::File(file), + Method::Head => Body::Empty, + })) + } else { + Ok(Response::builder() + .status(Status::NotFound) + .headers([("content-length", "0")]) + .body(Body::Empty)) + } + } + Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => Ok(Response::builder() + .status(Status::NotFound) + .headers([("content-length", "0")]) + .body(Body::Empty)), + Err(e) => Err(Error::Io(e))?, + }, + } + } +} + +impl FromLua for StaticFile { + fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result<Self> { + match value { + Value::Table(table) => Ok(Self { + path: PathBuf::from(OsString::from_vec( + table.get::<mlua::String>("path")?.as_bytes().to_vec(), + )), + mime: table.get::<String>("mime")?, + }), + _ => Err(mlua::Error::runtime("expected table")), + } + } +} |
