mal/auth/
redirect.rs

1/// HTTP server on host system
2/// ex. 127.0.0.1:7878
3/// blocks until one request is recieved (auth redirect) and parses it to get the code
4pub struct Server {
5    auth: super::OAuth,
6    app_name: String,
7}
8
9/// Error type for server methods
10#[derive(Debug)]
11pub enum ServerError {
12    IOError(std::io::Error),
13    HTTParseError(httparse::Error),
14    InvalidRequestURL(String),
15    AuthError(super::AuthError),
16}
17
18impl From<std::io::Error> for ServerError {
19    fn from(e: std::io::Error) -> Self {
20        ServerError::IOError(e)
21    }
22}
23
24impl From<httparse::Error> for ServerError {
25    fn from(e: httparse::Error) -> Self {
26        ServerError::HTTParseError(e)
27    }
28}
29
30impl From<super::AuthError> for ServerError {
31    fn from(e: super::AuthError) -> Self {
32        ServerError::AuthError(e)
33    }
34}
35
36impl Server {
37    /// Create the server
38    pub fn new<A: ToString>(app_name: A, auth: super::OAuth) -> Self {
39        Server {
40            auth,
41            app_name: app_name.to_string(),
42        }
43    }
44
45    /// Run the server.
46    /// Blocks until it recieves exactly one response.
47    pub fn go(self) -> Result<super::OAuth, ServerError> {
48        use std::io::prelude::*;
49        use std::net::TcpListener;
50
51        let listener = TcpListener::bind(&self.auth.redirect_url)?;
52        let mut socket_stream = listener.incoming().next().unwrap()?;
53
54        // read all bytes of the request
55        let mut request_bytes = Vec::new();
56        loop {
57            const BUF_SIZE: usize = 4096;
58            let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
59            match socket_stream.read(&mut buf) {
60                Ok(val) => {
61                    if val > 0 {
62                        request_bytes.append(&mut Vec::from(&buf[0..val]));
63                        if val < BUF_SIZE {
64                            break;
65                        }
66                    } else {
67                        break;
68                    }
69                }
70                Err(e) => return Err(ServerError::IOError(e)),
71            };
72        }
73
74        let mut headers = [httparse::EMPTY_HEADER; 16];
75        let mut parsed_request = httparse::Request::new(&mut headers);
76
77        parsed_request.parse(&request_bytes)?;
78
79        let raw_url = if let Some(path) = parsed_request.path {
80            format!("http://{}{}", self.auth.redirect_url, path)
81        } else {
82            return Err(ServerError::InvalidRequestURL("".to_string()));
83        };
84
85        let parsed_url = match url::Url::parse(&raw_url) {
86            Ok(url) => url,
87            Err(_) => return Err(ServerError::InvalidRequestURL(raw_url)),
88        };
89
90        let query = if let Some(query) = parsed_url.query() {
91            query
92        } else {
93            return Err(ServerError::InvalidRequestURL(
94                "No query string".to_string(),
95            ));
96        };
97
98        let mut ret_auth = self.auth;
99
100        ret_auth.parse_redirect_query_string(query)?;
101
102        // return a minimal http response to the browser
103        let r = format!("HTTP/1.1 200 OK\r\n\r\n<html><head><title>{} Authorized</title></head><body>{} Authorized</body></html>", self.app_name, self.app_name);
104        socket_stream.write_all(r.as_bytes())?;
105        socket_stream.flush()?;
106
107        Ok(ret_auth)
108    }
109}