1use std::io::{Read, Write};
2use std::net::{TcpListener, TcpStream};
3use std::thread;
4use json::{array, JsonValue, object};
5use crate::cryptos;
6use crate::datetime::datetime;
7use crate::datetime::timestamp::timestamp;
8use crate::files::file::{file_content_get_stream, file_content_put, is_file, remove};
9use crate::tools::string;
10
11
12pub struct Cors {
14 allow_origin: String,
15 allow_methods: String,
16 allow_headers: String,
17 allow_credentials: bool,
18 max_age: i32,
19}
20
21impl Cors {
22 pub fn default() -> Self {
24 Self {
25 allow_origin: "*".to_string(),
26 allow_methods: "*".to_string(),
27 allow_headers: "*".to_string(),
28 allow_credentials: true,
29 max_age: 0,
30 }
31 }
32 pub fn allow_origin(mut self, origin: &str) -> Self {
34 self.allow_origin = origin.to_string();
35 self
36 }
37
38 pub fn allow_methods(mut self, methods: &str) -> Self {
40 self.allow_methods = methods.to_string();
41 self
42 }
43 pub fn allow_headers(mut self, headers: &str) -> Self {
45 self.allow_headers = headers.to_string();
46 self
47 }
48 pub fn allow_credentials(mut self, open: bool) -> Self {
50 self.allow_credentials = open;
51 self
52 }
53 pub fn max_age(mut self, int: i32) -> Self {
55 self.max_age = int;
56 self
57 }
58}
59
60struct Response {
62 stream: TcpStream,
63 public: String,
64 header: JsonValue,
65 get: JsonValue,
66 post: JsonValue,
67 files: JsonValue,
68 cors: Cors,
69}
70
71impl Response {
72 pub fn default(stream: TcpStream, cors: JsonValue, public: String) -> Self {
74 let cors = Cors::default()
75 .allow_origin(cors["allow_origin"].as_str().unwrap())
76 .allow_methods(cors["allow_methods"].as_str().unwrap())
77 .allow_headers(cors["allow_headers"].as_str().unwrap())
78 .allow_credentials(cors["allow_credentials"].as_bool().unwrap())
79 .max_age(cors["max_age"].as_i32().unwrap());
80 Self {
81 stream,
82 public,
83 header: object! {},
84 get: object! {},
85 post: object! {},
86 files: object! {},
87 cors,
88 }
89 }
90 pub fn handle(&mut self, fun: fn(response: JsonValue) -> (JsonValue, i32, String)) {
92 let mut buf: Vec<u8> = vec![];
93 let mut buffer = [0; 1024];
95 let count = self.stream.read(&mut buffer).unwrap();
96 buf = [buf, buffer[0..count].to_vec()].concat();
97 let data_length = buf.len();
98 self._header(buf.clone());
99
100 if self.header["method"].as_str().unwrap() == "OPTIONS" {
102 self._options();
103 return;
104 }
105 let file = format!("{}{}", self.public, self.header["uri"].as_str().unwrap());
107 if is_file(file.as_str()) {
108 self._file_html(file.as_str());
109 return;
110 }
111 let body_length = self.header["content-length"].as_usize().unwrap();
112 let header_length = self.header["header_length"].as_usize().unwrap();
113 let mut mun = data_length - header_length;
114 while mun < body_length {
116 let mut buffer = [0; 1024];
117 let count = self.stream.read(&mut buffer).unwrap();
118 mun += count;
119 buf = [buf, buffer[0..count].to_vec()].concat();
120 };
121 let body = buf[header_length..].to_owned();
122 self._body(body.clone());
123
124 let response = object! {
125 header:self.header.clone(),
126 post:self.post.clone(),
127 get:self.get.clone(),
128 files:self.files.clone()
129 };
130 let (contents, code, content_type) = fun(response);
131 self.write(contents, code, content_type);
132 for (_, files) in self.files.entries_mut() {
134 for item in files.members() {
135 if is_file(item["temp"].as_str().unwrap()) {
136 remove(item["temp"].as_str().unwrap());
138 }
139 }
140 }
141 }
142 fn _header(&mut self, data: Vec<u8>) {
144 let data = String::from_utf8(data.to_vec()).unwrap();
145 let list = string::split(data, "\r\n\r\n");
146 let data = list[0].to_string();
147 let headers = string::split(data.clone(), "\r\n");
148 let list = string::split(headers[0].to_string(), " ");
149 self.header["header_length"] = (data.len() + 4).into();
150 self.header["method"] = list[0].clone();
151 self.header["uri"] = list[1].clone();
152 self.header["version"] = list[2].clone();
153 self._query(self.header["uri"].to_string());
154 for header in headers.members() {
155 let list = string::split(header.to_string(), ": ");
156 if list.len() == 2 {
157 self.header[list[0].to_string().to_lowercase().as_str()] = list[1].clone();
158 continue;
159 }
160 }
161 self.header["content-type"] = self._content_type(self.header["content-type"].to_string(), self.header["accept"].to_string()).into();
162 self.header["content-length"] = self.header["content-length"].to_string().parse::<i32>().unwrap_or(0).into();
163 }
164 fn _body(&mut self, data: Vec<u8>) {
166 match self.header["content-type"].as_str().unwrap() {
167 "multipart/form-data" => {
168 self._multipart(data.clone());
169 }
170 "application/x-www-form-urlencoded" => {
171 let text = String::from_utf8(data.clone()).unwrap();
172 let text = string::split(text.to_string(), "&");
173 for item in text.members() {
174 let row = string::split(item.to_string(), "=");
175 self.post[row[0].clone().as_str().unwrap()] = row[1].clone();
176 }
177 }
178 "application/json" => {
179 let text = String::from_utf8(data).unwrap();
180 let length = self.header["content-length"].to_string().parse::<usize>().unwrap();
181 if length == 0 {
182 return;
183 }
184 self.post = json::parse(&*text.clone()).unwrap();
185 }
186 _ => {
187 }
191 }
192 }
193 fn _multipart(&mut self, data: Vec<u8>) {
195 let boundary = self.header["boundary"].as_str().unwrap();
196 let text = unsafe { String::from_utf8_unchecked(data.clone()) };
197 let text = text.trim_start_matches("\r\n");
198 let text = text.trim_end_matches(format!("\r\n--{}--\r\n", boundary.clone()).as_str()).to_string();
199
200 let fg = format!("--{}\r\n", boundary.clone());
201 let list = string::split(text.clone(), fg.as_str().clone());
202 let mut index = 0;
203 let mut body = data[2 + fg.len()..].to_vec();
204 while index < list.len() {
205 let item = list[index].to_string();
206 let item = item.trim_start_matches(boundary.clone());
207 let len = item.len();
208 if len == 0 {
209 index += 1;
210 continue;
211 }
212 let mode = string::search(item, "filename=");
213 match mode {
214 false => {
215 let row = string::split(item.to_string(), "\r\n\r\n");
216 let field = string::split(row[0].to_string(), "\"");
217 let name = field[1].as_str().unwrap();
218 let row = string::split(row[1].to_string(), "\r\n");
219 let value = string::split(row[0].to_string(), "\"");
220 let value = value[0].clone();
221 self.post[name] = value.clone();
222 }
223 true => {
224 let text = string::split(item.to_string(), "\r\n\r\n");
225 let body = text[1].to_string();
226 let file = body.as_str().trim_start_matches("\u{0}");
227 let text = text[0].clone();
228 let text = string::split(text.to_string(), "\r\n");
229 let name = string::split(text[0].to_string(), "\"");
230 let types = string::split(text[1].to_string(), ": ");
231 let types = types[1].as_str().unwrap();
232 let field = name[1].as_str().unwrap();
233 let filename = name[3].as_str().unwrap();
234 fn _content_type_mode(data: &str) -> String {
235 match data {
236 "image/png" => "png",
237 "image/jpeg" => "jpeg",
238 "image/jpg" => "jpg",
239 _ => "txt"
240 }.to_string().clone()
241 }
242 let mut file_data = object! {};
243 file_data["type"] = types.into();
244 file_data["name"] = filename.into();
245 file_data["size"] = file.len().into();
246 file_data["sha"] = cryptos::sha::to_sha1(file.clone()).into();
247 file_data["mode"] = json::JsonValue::String(_content_type_mode(types.clone()).clone());
248 let temp_file = format!("{}.{}", timestamp("ms").to_string(), file_data["mode"]);
249 let filename = format!("{}/../temp/{}", self.public, temp_file);
250 file_data["temp"] = filename.clone().into();
251 file_content_put(&*filename, file.clone());
252 if self.files[field].is_empty() {
253 self.files[field] = array![file_data];
254 } else {
255 self.files[field].push(file_data).unwrap();
256 }
257 }
258 }
259 index += 1;
260 if index == list.len() {} else {
261 body = body[len + fg.len()..].to_vec();
262 }
263 }
264 }
265
266 fn _content_type(&mut self, data: String, accept: String) -> String {
268 if string::search(data.to_lowercase().as_str(), "text/html") {
269 return "text/html".to_string();
270 }
271 if string::search(data.to_lowercase().as_str(), "text/xml") {
272 return "text/xml".to_string();
273 }
274 if string::search(data.to_lowercase().as_str(), "application/json") {
275 return "application/json".to_string();
276 }
277 if string::search(data.to_lowercase().as_str(), "multipart/form-data") {
278 let ttt = string::split(data, "boundary=");
279 self.header["boundary"] = ttt[1].clone();
280 return "multipart/form-data".to_string();
281 }
282 if string::search(data.to_lowercase().as_str(), "application/x-www-form-urlencoded") {
283 return "application/x-www-form-urlencoded".to_string();
284 }
285 if string::search(data.to_lowercase().as_str(), "text/plain") {
286 return "text/plain".to_string();
287 }
288 if data.is_empty() {
289 if string::search(accept.to_lowercase().as_str(), "image/*") {
290 return "image/*".to_string();
291 }
292 if string::search(accept.to_lowercase().as_str(), "image/webp") {
293 return "image/*".to_string();
294 }
295 if string::search(accept.to_lowercase().as_str(), "image/gif") {
296 return "image/gif".to_string();
297 }
298 }
299 return "text/plain".to_string();
301 }
302 fn _query(&mut self, data: String) {
304 let query = string::split(data, "?");
305 let query = query[1].clone();
306 if query.is_empty() {
307 return;
308 }
309 let query = string::split(query.to_string(), "&");
310 let mut list = object! {};
311 for item in query.members() {
312 let row = string::split(item.to_string(), "=");
313 let key = row[0].clone();
314 let value = row[1].clone();
315 list[key.as_str().unwrap()] = value.into();
316 }
317 self.get = list;
318 }
319 fn _file_html(&mut self, filename: &str) {
321 let name = string::split(filename.to_string(), "/");
322 let name = name[name.len() - 1].as_str().unwrap();
323 let sufxx = string::split(filename.to_string(), ".");
324 let sufxx = sufxx[sufxx.len() - 1].as_str().unwrap();
325 let contents = file_content_get_stream(filename);
326 let crlf = "\r\n";
327 let status = format!("HTTP/1.1 200 OK{}", crlf);
328 let date = format!("Date: {}{}", datetime::to_gmt(), crlf);
329 let server = format!("Server: Rust{}", crlf);
330 let content_length = format!("Content-Length: {}{}", contents.len(), crlf);
331 let content_disposition = match sufxx {
332 "html" => {
333 format!("")
334 }
335 _ => {
336 format!("Content-Disposition: attachment; filename={}{}", name, crlf)
337 }
338 };
339 let content_type = match sufxx {
340 "jpg" => {
341 format!("content-type:image/jpg{}", crlf)
342 }
343 "png" => {
344 format!("content-type:image/png{}", crlf)
345 }
346 "bmp" => {
347 format!("content-type:image/bmp{}", crlf)
348 }
349 "jpeg" => {
350 format!("content-type:image/jpeg{}", crlf)
351 }
352 "svg" => {
353 format!("content-type:image/svg{}", crlf)
354 }
355 "webp" => {
356 format!("content-type:image/webp{}", crlf)
357 }
358 "ico" => {
359 format!("content-type:image/ico{}", crlf)
360 }
361 "gif" => {
362 format!("content-type:image/gif{}", crlf)
363 }
364 _ => {
365 format!("content-type: text/plain;charset=utf-8{}", crlf)
366 }
367 };
368 let response = format!("{}{}{}{}{}{}{}{}", status, date, server, content_disposition, content_type, content_length, crlf, contents);
369 self.stream.write_all(response.as_bytes()).unwrap();
370 self.stream.flush().unwrap();
371 }
372 fn _options(&mut self) {
373 let crlf = "\r\n";
374 let status = format!("HTTP/1.1 200 OK{}", crlf);
375 let date = format!("Date: {}{}", datetime::to_gmt(), crlf);
376 let server = format!("Server: Rust{}", crlf);
377 let allow_origin = format!("Access-Control-Allow-Origin: {}{}", self.cors.allow_origin, crlf);
378 let allow_methods = format!("Access-Control-Allow-Methods: {}{}", self.cors.allow_methods, crlf);
379 let allow_headers = format!("Access-Control-Allow-Headers: {}{}", self.cors.allow_headers, crlf);
380 let max_age = format!("Access-Control-Max-Age: {}{}", self.cors.max_age, crlf);
381 let allow_credentials = format!("Access-Control-Allow-Credentials: {}{}", self.cors.allow_credentials, crlf);
382
383 let response = format!("{}{}{}{}{}{}{}{}{}",
384 status, date, server,
385 allow_origin,
386 allow_methods,
387 allow_credentials,
388 max_age,
389 allow_headers,
390 crlf);
391 self.stream.write(response.as_bytes()).unwrap();
392 self.stream.flush().unwrap();
393 }
394 fn write(&mut self, contents: JsonValue, code: i32, content_type: String) {
396 let crlf = "\r\n";
397 let status = format!("HTTP/1.1 {} {}{}", code, "OK", crlf);
398 let content_type = {
399 match content_type.as_str() {
400 "json" => {
401 format!("content-type: application/json;charset=utf-8{}", crlf)
402 }
403 _ => {
404 format!("content-type: text/html;charset=utf-8{}", crlf)
405 }
406 }
407 };
408 let access_control_allow_origin = format!("Access-Control-Allow-Origin: *{}", crlf);
409 let content_length = format!("Content-Length: {}{}", contents.to_string().as_bytes().len(), crlf);
410 let response = format!("{}{}{}{}{}{}", status, content_type, access_control_allow_origin, content_length, crlf, contents);
411 self.stream.write(response.as_bytes()).unwrap();
412 self.stream.flush().unwrap();
413 }
414}
415
416pub struct Web {
417 ip: String,
418 public: String,
420}
421
422impl Web {
423 pub fn bind(ip: &str, public: &str) -> Self {
424 Self {
425 ip: ip.to_string(),
426 public: public.to_string(),
427 }
428 }
429 pub fn run(&mut self, cors: JsonValue, handle: fn(response: JsonValue) -> (JsonValue, i32, String)) {
431 let listener = TcpListener::bind(self.ip.as_str()).unwrap();
432 for stream in listener.incoming() {
433 let cors = cors.clone();
434 let public = self.public.clone();
435 let stream = stream.unwrap();
436 thread::spawn(move || Response::default(stream, cors, public).handle(handle));
437 }
438 }
439}