106 lines
2.8 KiB
Rust
106 lines
2.8 KiB
Rust
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<TcpStream>, 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<TcpStream>) {
|
|
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<TcpStream>) {
|
|
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) => {}
|
|
}
|
|
}
|