use crate::mime; use crate::server::response; use crate::server::ServerConfig; use openssl::ssl::SslStream; use std::fs::File; use std::io::{copy, BufReader, BufWriter}; use std::net::TcpStream; use std::path::{Path, PathBuf}; use url::Url; fn send_header(stream: &mut SslStream, header: &response::Header) { match stream.ssl_write(&header.to_vec()) { Ok(_s) => { return; } Err(_e) => { return; } }; } pub fn handle_request(config: &ServerConfig, mut stream: SslStream) { let mut buffer = [0; 1026]; match stream.ssl_read(&mut buffer) { Ok(s) => { if s == 0 { send_header(&mut stream, &response::bad_request()); return; } } Err(_) => { send_header(&mut stream, &response::bad_request()); return; } }; let request = match String::from_utf8(buffer.to_vec()) { Ok(request) => request, Err(_) => { send_header(&mut stream, &response::bad_request()); return; } }; let location = match Url::parse(&request) { Ok(url) => url, Err(_) => config.default_host.join(&request).unwrap(), }; handle_response(config, location, &mut stream); } fn gen_path_index(path: &Path) -> PathBuf { match path.is_dir() { true => path.join("index.gmi"), false => PathBuf::from(path), } } fn handle_response(config: &ServerConfig, url: Url, mut stream: &mut SslStream) { println!("responding for: {}", url); if url.scheme() != "gemini" { send_header(&mut stream, &response::permanent_failure()); return; } if url.host() != config.default_host.host() { send_header(&mut stream, &response::proxy_request_refused()); return; } let rel_path = match Path::new(url.path()).strip_prefix("/") { Ok(path) => path, Err(_) => { send_header(&mut stream, &response::bad_request()); return; } }; let path = gen_path_index(&config.gem_root.join(rel_path)); let file = match File::open(&path) { Ok(file) => file, Err(_) => { println!("not found: {:?}", path); send_header(&mut stream, &response::not_found()); return; } }; println!("sending file: {:?}", path); let mime_type = match path.extension() { Some(ext) => mime::get_mime_type(ext), None => mime::default_mime_type(), }; let header = response::Header::new(response::Status::Success, mime_type); send_header(&mut stream, &header); let mut buf_file = BufReader::new(file); let mut buf_stream = BufWriter::new(stream); match copy(&mut buf_file, &mut buf_stream) { Ok(_s) => {} Err(_e) => {} } }