summaryrefslogtreecommitdiff
path: root/src/server/handler.rs
blob: e122e96bcff850e7dc2cb1f86397c432622b8957 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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) => {}
    }
}