df_web/
request.rs

1use std::{fs};
2use std::fs::{remove_file};
3use std::path::Path;
4use chrono::{Utc};
5use json::{JsonValue, object};
6use log::info;
7use crate::cors::Cors;
8
9
10/// http请求
11pub struct Http {
12    cors: Cors,
13}
14
15impl Http {
16    pub fn default(cors: Cors) -> Self {
17        Self {
18            cors: cors.clone(),
19        }
20    }
21    pub fn handle(&mut self, header: JsonValue, mut body: JsonValue, fun: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) -> (bool, String) {
22
23
24        // 判断是否检查请求
25        if header["method"].as_str().unwrap() == "OPTIONS" {
26            return (true, self._write(200, object! {}, ""));
27        }
28
29        // 检查是否是文件路径
30        let file = format!("{}{}", header["public"], header["uri"].as_str().unwrap());
31
32        if Path::new(file.as_str()).is_file() {
33            return (true, self._file_html(file.as_str()));
34        }
35
36        body["header"] = header.clone();
37        let (code, content_type, contents) = fun(body.clone());
38        // // 清理temp临时缓存文件
39        for (_, files) in body["files"].entries() {
40            for item in files.members() {
41                if Path::new(item["temp"].as_str().unwrap()).is_file() {
42                    match remove_file(item["temp"].as_str().unwrap()) {
43                        Ok(_) => true,
44                        Err(_) => {
45                            info!("删除文件失败:{}", item["temp"]);
46                            false
47                        }
48                    };
49                }
50            }
51        }
52
53        let data = self._write(code.clone(), contents.clone(), content_type.clone());
54        match content_type {
55            "download" => {
56                match remove_file(contents.as_str().unwrap()) {
57                    Ok(_) => true,
58                    Err(_) => {
59                        info!("删除文件失败:{}",contents);
60                        false
61                    }
62                };
63                (true, data)
64            }
65            _ => {
66                (true, data)
67            }
68        }
69    }
70    /// 读取文件返回
71    fn _file_html(&mut self, filename: &str) -> String {
72        let name: Vec<&str> = filename.split("/").collect();
73        let name = name[name.len() - 1];
74        let sufxx: Vec<&str> = filename.split(".").collect();
75        let sufxx = sufxx[sufxx.len() - 1];
76
77        let file = fs::read(filename).unwrap();
78        let contents = unsafe { String::from_utf8_unchecked(file) };
79
80        let crlf = "\r\n";
81        let status = format!("HTTP/1.1 200 OK{}", crlf);
82
83
84        let date = format!("Date: {}{}", Utc::now().format("%a %d %b %Y %H:%M:%S GMT").to_string(), crlf);
85        let server = format!("Server: Rust{}", crlf);
86        let content_length = format!("Content-Length: {}{}", contents.len(), crlf);
87        let content_disposition = match sufxx {
88            "html" => {
89                format!("")
90            }
91            _ => {
92                format!("Content-Disposition: attachment; filename={}{}", name, crlf)
93            }
94        };
95        let content_type = match sufxx {
96            "jpg" => {
97                format!("content-type:image/jpg{}", crlf)
98            }
99            "png" => {
100                format!("content-type:image/png{}", crlf)
101            }
102            "bmp" => {
103                format!("content-type:image/bmp{}", crlf)
104            }
105            "jpeg" => {
106                format!("content-type:image/jpeg{}", crlf)
107            }
108            "svg" => {
109                format!("content-type:image/svg{}", crlf)
110            }
111            "webp" => {
112                format!("content-type:image/webp{}", crlf)
113            }
114            "ico" => {
115                format!("content-type:image/ico{}", crlf)
116            }
117            "gif" => {
118                format!("content-type:image/gif{}", crlf)
119            }
120            _ => {
121                format!("content-type: text/plain;charset=utf-8{}", crlf)
122            }
123        };
124        let response = format!("{}{}{}{}{}{}{}{}", status, date, server, content_disposition, content_type, content_length, crlf, contents);
125        // self.stream.write_all(response.as_bytes()).unwrap();
126        // self.stream.flush().unwrap();
127        response
128    }
129
130    /// 将响应写出到流
131    fn _write(&mut self, code: i32, contents: JsonValue, content_type: &str) -> String {
132        let crlf = "\r\n";
133        let mut list = vec![];
134
135        match code {
136            200 => {
137                list.push(format!("HTTP/1.1 {} {}", code, "OK"))
138            }
139            _ => {
140                list.push(format!("HTTP/1.1 {} {}", code, "Permanently Moved"))
141            }
142        };
143        list.push(format!("Date: {}", Utc::now().format("%a %d %b %Y %H:%M:%S GMT").to_string()));
144        list.push(format!("Connection: keep-alive"));
145
146        list.push(format!("Server: Rust"));
147        list.push(format!("Access-Control-Allow-Origin: {}", self.cors.allow_origin));
148        list.push(format!("Access-Control-Allow-Methods: {}", self.cors.allow_methods));
149        list.push(format!("Access-Control-Allow-Headers: {}", self.cors.allow_headers));
150        list.push(format!("Access-Control-Allow-Credentials: {}", self.cors.allow_credentials));
151
152        match content_type {
153            "json" => {
154                list.push(format!("Cache-Control: no-cache,max-age=0"));
155                list.push(format!("Content-type: application/json;charset=utf-8"))
156            }
157            "html" => {
158                list.push(format!("Access-Control-Max-Age: {}", self.cors.max_age));
159                list.push(format!("Content-type: text/html;charset=utf-8"))
160            }
161            "url" => {
162                list.push(format!("Cache-control: no-cache"));
163                list.push(format!("Content-Type: text/html;"))
164            }
165            "download" => {
166                list.push(format!("Cache-Control: no-cache,max-age=0"));
167                list.push(format!("Content-type: application/octet-stream"));
168                let path = contents.to_string();
169                let filename: Vec<&str> = path.split("/").collect();
170                let filename = filename[filename.len() - 1];
171                list.push(format!("Content-disposition: attachment; filename={}", filename))
172            }
173            _ => {
174                list.push(format!("Cache-Control: no-cache,max-age=0"));
175                list.push(format!("Content-type: text/html;charset=utf-8"))
176            }
177        }
178
179        match code {
180            200 => {
181                match content_type {
182                    "download" => {
183                        let file = fs::read(contents.to_string()).unwrap();
184                        let contents = unsafe { String::from_utf8_unchecked(file) };
185                        list.push(format!("Content-Length: {}\r\n", contents.len()));
186                        list.push(contents);
187                    }
188                    _ => {
189                        list.push(format!("Content-Length: {}\r\n", contents.to_string().as_bytes().len()));
190                        list.push(format!("{}", contents));
191                    }
192                }
193            }
194            301 => {
195                list.push(format!("Location: {}", contents.to_string()))
196            }
197            _ => {}
198        }
199        list.join(crlf)
200    }
201}