firebolt/structures/server/
request.rs1use std::collections::HashMap;
2use regex::{Regex};
3use std::fmt::{Display, Formatter};
4use core::fmt;
5use crate::server::firebolt::MAX_PAYLOAD_SIZE;
6use crate::structures::common::header::Header;
7use crate::structures::common::method::Method;
8
9#[derive(Debug)]
10pub struct Request {
11 pub body: Option<String>,
12 pub raw_endpoint: String,
13 pub endpoint: String,
14 pub query_string: Option<HashMap<String, String>>,
15 pub headers: Header,
16 pub method: Option<Method>
17}
18
19fn retrieve_endpoint_with_qs(string: &str) -> String {
20 let regex = Regex::new(r"\s(.+)\s").unwrap();
21
22 let mut raw_endpoint = "";
23
24 match regex.find(string) {
25 Some(e) => raw_endpoint = e.as_str().trim(),
26 None => {}
27 }
28
29 let endpoint = raw_endpoint;
30
31 String::from(endpoint)
32}
33
34fn retrieve_endpoint(string: &str) -> String {
35 let regex = Regex::new(r"(&|\?).+").unwrap();
36
37 let raw_endpoint = regex.replace(string, "");
38
39 String::from(raw_endpoint)
40}
41
42
43fn retrieve_qs(string: &str) -> Option<HashMap<String, String>> {
44 let regex = Regex::new(r"([&?])([A-z0-9]+)=([A-z0-9]+)").unwrap();
45
46 let matches: Vec<&str> = regex.find_iter(string).into_iter().map(|m| m.as_str()).collect();
47
48 let mut qs : HashMap<String, String> = HashMap::new();
49 let mut has_initial_qs: bool = false;
50
51 for match_idx in 0..matches.len() {
52 let mut qs_match = matches[match_idx].to_owned();
53
54 let starting_qs_regex = Regex::new(r"\?").unwrap();
55 let is_match = starting_qs_regex.is_match(&qs_match);
56
57 if is_match {
58 has_initial_qs = true;
59 let raw_match = starting_qs_regex.replace(&qs_match, "").to_string();
60 qs_match = raw_match;
61 } else {
62 let another_qs_regex = Regex::new(r"&").unwrap();
63 let raw_match = another_qs_regex.replace(&qs_match, "").to_string();
64 qs_match = raw_match;
65 }
66 let split: Vec<&str> = qs_match.split('=').collect();
67
68 if split.len() == 2 {
69 qs.insert(split[0].to_owned(), split[1].to_owned());
70 } else if split.len() == 1 {
71 qs.insert(split[0].to_owned(), String::new());
72 }
73 }
74
75 if has_initial_qs {
76 Some(qs)
77 } else {
78 None
79 }
80}
81
82fn retrieve_headers(raw_headers: Vec<&str>) -> Header {
83 let mut headers: Header = Header::new();
84
85 for header in raw_headers.iter() {
86 let split: Vec<&str> = header.split(":").collect();
87 if split.len() == 2 {
88 headers.insert(split[0].to_string(), split[1].trim_start().to_string());
89 } else if split.len() == 1 {
90 headers.insert(split[0].to_string(), String::new());
91 }
92 }
93
94 headers
95}
96
97impl Request {
98 pub fn new(raw_request: Vec<&str>) -> Self {
99 let request_header = raw_request[0];
100 let method = Method::from_str(request_header);
101 let raw_endpoint_with_qs = retrieve_endpoint_with_qs(raw_request[0]);
102 let endpoint = retrieve_endpoint(raw_endpoint_with_qs.as_str());
103 let qs = retrieve_qs(&raw_endpoint_with_qs);
104 let mut raw_headers: Vec<&str> = Vec::new();
105 if raw_request.len() > 1 {
106 raw_headers = raw_request[1..raw_request.len() - 1].iter().filter_map(|h| -> Option<&str> {
107 if *h != "" {
108 Some(*h)
109 } else {
110 None
111 }
112 }).collect();
113 }
114
115 let raw_body = raw_request[raw_request.len() - 1].to_owned();
116 let headers = retrieve_headers(raw_headers.to_vec());
117
118 Self { body: Some(raw_body), headers, raw_endpoint: raw_endpoint_with_qs, query_string: qs, endpoint, method }
119 }
120
121 pub fn get_header(&self, key: &str) -> Option<&String> {
122 self.headers.get(key)
123 }
124
125 pub fn request_size(&self) -> usize {
126 let has_payload = self.body.is_none();
127 match self.get_header("Content-Length") {
128 Some(s) => s.parse().unwrap_or(MAX_PAYLOAD_SIZE + 1),
129 None => {
130 if has_payload {
131 self.body.as_ref().unwrap().bytes().len()
132 } else {
133 0
134 }
135 }
136 }
137 }
138}
139
140impl Display for Request {
141 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
142 write!(f, "{:?}\n{:?}\n{:?}\nHeaders: {:?}\nBody: {:?}", self.method.unwrap(), self.endpoint, self.raw_endpoint, self.headers, self.body)
143 }
144}