Added cgi and util mod

This commit is contained in:
int 80h
2020-04-23 18:35:33 -04:00
parent a5c52dd4d9
commit 5cf4e41863
3 changed files with 81 additions and 57 deletions

43
src/cgi.rs Normal file
View File

@@ -0,0 +1,43 @@
use std::io::{self, BufReader};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::collections::HashMap;
use tokio::net::TcpStream;
use tokio_rustls::server::TlsStream;
use url::Url;
use crate::config;
use crate::status;
use crate::util;
pub async fn cgi(
stream: TlsStream<TcpStream>,
path: PathBuf,
url: Url,
cfg: config::Config,
) -> Result<(), io::Error> {
let mut envs = HashMap::new();
envs.insert("GEMINI_URL", url.as_str());
envs.insert("SERVER_NAME", url.host_str().unwrap());
envs.insert("SCRIPT_NAME", path.file_name().unwrap().to_str().unwrap());
envs.insert("SERVER_PROTOCOL", "GEMINI");
// envs.insert("SERVER_PORT", &(cfg.port as str));
if let Some(q) = url.query() {
envs.insert("QUERY_STRING", q);
}
let cmd = Command::new(path.to_str().unwrap())
.env_clear()
.envs(&envs)
.output()
.unwrap();
if !cmd.status.success() {
util::send(stream, status::Status::CGIError, "CGI Error!", None).await?;
return Ok(());
}
let cmd = String::from_utf8(cmd.stdout).unwrap();
util::send(stream, status::Status::Success, "text/gemini", Some(cmd)).await?;
return Ok(());
}

View File

@@ -25,26 +25,11 @@ use tokio_rustls::server::TlsStream;
use tokio_rustls::TlsAcceptor; use tokio_rustls::TlsAcceptor;
use url::Url; use url::Url;
mod cgi;
mod config; mod config;
mod status; mod status;
mod tls; mod tls;
mod util;
async fn send(
mut stream: TlsStream<TcpStream>,
stat: status::Status,
meta: String,
body: Option<String>,
) -> Result<(), io::Error> {
let mut s = format!("{}\t{}\r\n", stat as u8, meta);
stream.write_all(s.as_bytes()).await?;
stream.flush().await?;
if let Some(b) = body {
s = format!("{}", b);
}
stream.write_all(s.as_bytes()).await?;
stream.flush().await?;
Ok(())
}
fn get_content(path: PathBuf, u: url::Url) -> Result<String, io::Error> { fn get_content(path: PathBuf, u: url::Url) -> Result<String, io::Error> {
let meta = fs::metadata(&path).expect("Unable to read metadata"); let meta = fs::metadata(&path).expect("Unable to read metadata");
@@ -77,10 +62,10 @@ async fn handle_connection(
let url = Url::parse(&request).unwrap(); let url = Url::parse(&request).unwrap();
if url.scheme() != "gemini" { if url.scheme() != "gemini" {
send( util::send(
stream, stream,
status::Status::ProxyRequestRefused, status::Status::ProxyRequestRefused,
"Not a gemini scheme!\r\n".to_string(), "Not a gemini scheme!\r\n",
None, None,
) )
.await?; .await?;
@@ -88,10 +73,10 @@ async fn handle_connection(
} }
if url.path().to_string().contains("..") { if url.path().to_string().contains("..") {
send( util::send(
stream, stream,
status::Status::PermanentFailure, status::Status::PermanentFailure,
"Not in path!".to_string(), "Not in path!",
None, None,
) )
.await?; .await?;
@@ -100,11 +85,11 @@ async fn handle_connection(
let mut dir = String::new(); let mut dir = String::new();
let mut cgi = String::new(); let mut cgi = String::new();
for server in cfg.server { for server in &cfg.server {
if Some(server.hostname.as_str()) == url.host_str() { if Some(server.hostname.as_str()) == url.host_str() {
dir = server.dir; dir = server.dir.to_string();
if server.cgi.is_some() { if server.cgi.is_some() {
cgi = server.cgi.unwrap(); cgi = server.cgi.as_ref().unwrap().to_string();
} }
} }
} }
@@ -115,13 +100,7 @@ async fn handle_connection(
} }
if !path.exists() { if !path.exists() {
send( util::send(stream, status::Status::NotFound, "Not found!\r\n", None).await?;
stream,
status::Status::NotFound,
"Not found!\r\n".to_string(),
None,
)
.await?;
return Ok(()); return Ok(());
} }
@@ -130,10 +109,10 @@ async fn handle_connection(
if meta.is_dir() { if meta.is_dir() {
if !url.path().ends_with("/") { if !url.path().ends_with("/") {
send( util::send(
stream, stream,
status::Status::RedirectPermanent, status::Status::RedirectPermanent,
format!("{}/\r\n", url), format!("{}/\r\n", url).as_str(),
None, None,
) )
.await?; .await?;
@@ -146,36 +125,15 @@ async fn handle_connection(
// add timeout // add timeout
if cgi.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() { if cgi.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() {
let cmd = Command::new(path.to_str().unwrap()) cgi::cgi(stream, path, url, cfg).await?;
.env_clear()
.wait_timeout(time)
.output()?;
if !cmd.status.success() {
send(
stream,
status::Status::CGIError,
"CGI Error!".to_string(),
None,
)
.await?;
return Ok(());
}
let cmd = String::from_utf8(cmd.stdout).unwrap();
send(
stream,
status::Status::Success,
"text/gemini".to_string(),
Some(cmd),
)
.await?;
return Ok(()); return Ok(());
} }
let content = get_content(path, url)?; let content = get_content(path, url)?;
send( util::send(
stream, stream,
status::Status::Success, status::Status::Success,
"text/gemini".to_string(), "text/gemini",
Some(content), Some(content),
) )
.await?; .await?;

23
src/util.rs Normal file
View File

@@ -0,0 +1,23 @@
use std::io;
use tokio::net::TcpStream;
use tokio::prelude::*;
use tokio_rustls::server::TlsStream;
use crate::status;
pub async fn send(
mut stream: TlsStream<TcpStream>,
stat: status::Status,
meta: &str,
body: Option<String>,
) -> Result<(), io::Error> {
let mut s = format!("{}\t{}\r\n", stat as u8, meta);
stream.write_all(s.as_bytes()).await?;
stream.flush().await?;
if let Some(b) = body {
s = format!("{}", b);
}
stream.write_all(s.as_bytes()).await?;
stream.flush().await?;
Ok(())
}