diff --git a/src/cgi.rs b/src/cgi.rs index e9045ec..441d773 100644 --- a/src/cgi.rs +++ b/src/cgi.rs @@ -36,6 +36,6 @@ pub async fn cgi(mut con: util::Connection, path: PathBuf, url: Url) -> Result<( return Ok(()); } let cmd = String::from_utf8(cmd.stdout).unwrap(); - con.send_raw(cmd).await?; + con.send_raw(cmd.as_bytes()).await?; return Ok(()); } diff --git a/src/main.rs b/src/main.rs index cd35d7d..3d57bb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,8 @@ use std::collections::HashMap; use std::error::Error; use std::fs; use std::fs::File; -use std::io::{self, BufReader}; +use std::io::{self, BufReader, BufRead}; +use std::io::prelude::*; use std::net::SocketAddr; use std::net::ToSocketAddrs; use std::os::unix::fs::PermissionsExt; @@ -35,6 +36,39 @@ mod status; mod tls; mod util; +fn get_mime(path: &PathBuf) -> String { + let mut mime = "text/gemini"; + let m: mime::Mime; + + let ext = match path.extension() { + Some(p) => p.to_str().unwrap(), + None => mime, + }; + if ext != "gemini" { + m = mime_guess::from_ext(ext).first().unwrap(); + mime = m.essence_str(); + } + mime.to_string() +} + +async fn get_binary(mut con: util::Connection, path:PathBuf, meta: String) -> io::Result<()> { + let fd = File::open(path)?; + let mut reader = BufReader::with_capacity(1024*1024,fd); + con.send_status(status::Status::Success, &meta).await?; + loop { + let len = { + let buf = reader.fill_buf()?; + con.send_raw(buf).await?; + buf.len() + }; + if len == 0 { + break + } + reader.consume(len); + } + Ok(()) +} + fn get_content(path: PathBuf, u: url::Url) -> Result { let meta = fs::metadata(&path).expect("Unable to read metadata"); if meta.is_file() { @@ -116,18 +150,15 @@ async fn handle_connection(mut con: util::Connection) -> Result<(), io::Error> { return Ok(()); } - let mut mime = "text/gemini"; - let m: mime::Mime; - - if path.extension().unwrap().to_str() != Some("gemini") { - m = mime_guess::from_path(&path).first().unwrap(); - mime = m.essence_str(); + let mime = get_mime(&path); + if !mime.starts_with("text/") { + get_binary(con, path, mime).await?; + return Ok(()); } - let content = get_content(path, url)?; con.send_body( status::Status::Success, - mime, + mime.as_str(), Some(content), ) .await?; diff --git a/src/util.rs b/src/util.rs index e92f8e4..a613634 100644 --- a/src/util.rs +++ b/src/util.rs @@ -34,12 +34,12 @@ pub async fn send_body( if let Some(b) = body { s += &b; } - self.send_raw(s).await?; + self.send_raw(s.as_bytes()).await?; Ok(()) } -pub async fn send_raw(&mut self, body: String) -> Result<(), io::Error> { - self.stream.write_all(body.as_bytes()).await?; +pub async fn send_raw(&mut self, body: &[u8]) -> Result<(), io::Error> { + self.stream.write_all(body).await?; self.stream.flush().await?; Ok(()) }