1pub struct Server {
5 auth: super::OAuth,
6 app_name: String,
7}
8
9#[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 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 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 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 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}