br_web_server/
request.rs

1use crate::{Authorization, Connection, ContentType, Encoding, HttpError, Language, Method, Upgrade, Uri};
2use crate::config::{Config};
3use chrono::{DateTime, Local};
4use json::{array, object, JsonValue};
5use log::{info};
6use std::io::{Write};
7use std::path::{Path};
8use std::{env, fs, io, thread};
9use std::cmp::PartialEq;
10use std::fs::OpenOptions;
11use std::sync::{Arc, Mutex};
12use std::time::Instant;
13use crate::stream::{Protocol, Scheme};
14
15/// 请求体
16#[derive(Clone, Debug)]
17pub struct Request {
18    pub config: Config,
19    /// 协议版本
20    pub protocol: Protocol,
21    /// 当前请求类型
22    pub method: Method,
23    /// 资源标识符
24    pub uri: Uri,
25    /// 源站
26    pub origin: String,
27    /// header信息
28    pub header: JsonValue,
29    /// Cookie信息
30    pub cookie: JsonValue,
31    /// 查询参数
32    pub query: JsonValue,
33    /// 请求参数
34    pub params: JsonValue,
35    /// 认证信息
36    pub authorization: Authorization,
37    /// 处理耗时
38    pub handle_time: String,
39    /// 请求时间
40    pub datetime: String,
41    /// 请求时间戳
42    pub timestamp: i64,
43    /// 客户端IP
44    pub client_ip: String,
45    /// 代理端IP
46    pub proxy_ip: String,
47    /// 服务端IP
48    pub server_ip: String,
49    // 升级协议
50    pub upgrade: Upgrade,
51    /// 连接方式
52    pub connection: Connection,
53    /// 压缩方式
54    pub accept_encoding: Encoding,
55    /// 开始时间
56    start_time: Instant,
57    /// 请求体数据
58    pub body_data: Vec<u8>,
59    /// 消息体长度
60    content_length: usize,
61    /// 消息体类型
62    pub content_type: ContentType,
63    /// 边界
64    boundary: String,
65    pub scheme: Arc<Mutex<Scheme>>,
66    /// 接受语音
67    pub accept_language: Language,
68}
69
70
71impl Request {
72    pub fn new(config: Config, scheme: Arc<Mutex<Scheme>>) -> Self {
73
74        // 获取请求客户端IP
75        let client_ip = scheme.lock().unwrap().client_ip();
76        // 获取服务端IP
77        let server_ip = scheme.lock().unwrap().server_ip();
78        let local: DateTime<Local> = Local::now();
79        Self {
80            config,
81            protocol: Protocol::Other(String::new()),
82            method: Method::Other(String::new()),
83            uri: Uri::default(),
84            origin: "".to_string(),
85            header: object! {},
86            cookie: object! {},
87            query: object! {},
88            params: object! {},
89            authorization: Authorization::Other(String::new()),
90            handle_time: String::new(),
91            scheme,
92            start_time: Instant::now(),
93            datetime: local.format("%Y-%m-%d %H:%M:%S").to_string(),
94            timestamp: local.timestamp(),
95            client_ip,
96            server_ip,
97            proxy_ip: String::new(),
98            upgrade: Upgrade::Other(String::new()),
99            connection: Connection::Other(String::new()),
100            accept_encoding: Encoding::None,
101            body_data: vec![],
102            content_length: 0,
103            content_type: ContentType::Other(String::new()),
104            boundary: String::new(),
105            accept_language: Language::ZhCN,
106        }
107    }
108
109    pub fn handle(&mut self) -> Result<(), HttpError> {
110
111        // 读开始行
112        {
113            let header_line = self.scheme.lock().unwrap().read_line()?;
114            self.handle_header_line(header_line.trim())?;
115            //data = self.scheme.lock().unwrap().read()?;
116            //if let Some(pos) = data.windows(2).position(|window| window == [13, 10]) {
117            //    let header_data = data.drain(..pos).collect::<Vec<u8>>();
118            //    data.drain(..2);
119            //    let header_data = String::from_utf8_lossy(header_data.as_slice());
120            //    self.handle_header_line(header_data.trim())?;
121            //} else if data.len() < 1024 * 1024 {
122            //    return Err(HttpError::new(400, "请求行错误"));
123            //}
124        }
125
126        // 请求头处理
127        match &self.protocol {
128            Protocol::HTTP1_0 | Protocol::HTTP1_1 => {
129                {
130                    loop {
131                        let mut data = self.scheme.lock().unwrap().read()?;
132                        if let Some(pos) = data.windows(4).position(|window| window == [13, 10, 13, 10]) {
133                            self.handle_header(data.drain(..pos).collect::<Vec<u8>>())?;
134                            data.drain(..4);
135                            self.body_data = data;
136                            break;
137                        } else {
138                            continue;
139                        }
140                    }
141                }
142                // 消息体处理
143                {
144                    if self.content_length > 0 {
145                        loop {
146                            if self.body_data.len() >= self.content_length {
147                                break;
148                            }
149                            self.body_data.extend(self.scheme.lock().unwrap().read()?);
150                        }
151                        self.handle_body(self.body_data.clone())?;
152                    }
153                }
154                self.handle_time = format!("{:?}", self.start_time.elapsed());
155            }
156            Protocol::HTTP2 => {
157                let mut data = vec![];
158                data.extend(self.scheme.lock().unwrap().read()?);
159                let header = data.drain(..8).collect::<Vec<u8>>();
160                if header.ne(b"\r\nSM\r\n\r\n") {
161                    return Err(HttpError::new(400, "HTTP2格式错误"));
162                }
163                let scheme_arc = self.scheme.clone();
164                let mut scheme = scheme_arc.lock().unwrap();
165                scheme.http2_handle_header(&mut data, self)?;
166                self.body_data = scheme.http2_handle_body(&mut data, self.clone())?;
167                self.handle_body(self.body_data.clone())?;
168                self.handle_time = format!("{:?}", self.start_time.elapsed());
169            }
170            Protocol::HTTP3 => return Err(HttpError::new(500, format!("未支持: HTTP3 {:?}", self.protocol).as_str())),
171            Protocol::Other(e) => return Err(HttpError::new(500, format!("未支持: Other {e} {:?}", self.protocol).as_str())),
172        }
173        Ok(())
174    }
175    /// 处理请求行
176    pub fn handle_header_line(&mut self, line: &str) -> Result<(), HttpError> {
177        let line = br_crypto::encoding::urlencoding_decode(line);
178        if line.is_empty() {
179            return Err(HttpError::new(400, "请求行错误"));
180        }
181        if self.config.debug {
182            info!("\r\n=================请求行 {:?}=================\r\n{line}\r\n========================================",thread::current().id());
183        }
184        let mut it = line.split_whitespace();
185        let method = it.next();
186        let target = it.next();
187        let version = it.next();
188
189        // 处理协议版本
190        self.protocol = match version {
191            None => return Err(HttpError::new(400, "协议版本错误")),
192            Some(e) => Protocol::from(e)
193        };
194        // 根据版本分别处理
195        match &self.protocol {
196            Protocol::HTTP1_0 => {
197                self.method = match method {
198                    None => return Err(HttpError::new(400, "请求类型错误")),
199                    Some(e) => Method::from(e)
200                };
201                self.uri = match target {
202                    None => return Err(HttpError::new(400, "请求资源错误")),
203                    Some(e) => Uri::from(e)
204                };
205                self.query = self.uri.get_query_params();
206            }
207            Protocol::HTTP1_1 => {
208                self.method = match method {
209                    None => return Err(HttpError::new(400, "请求类型错误")),
210                    Some(e) => Method::from(e)
211                };
212                self.uri = match target {
213                    None => return Err(HttpError::new(400, "请求资源错误")),
214                    Some(e) => Uri::from(e)
215                };
216                self.query = self.uri.get_query_params();
217            }
218            Protocol::HTTP2 => {}
219            Protocol::HTTP3 => return Err(HttpError::new(400, format!("{:?}协议暂未实现", self.protocol).as_str())),
220            Protocol::Other(name) => return Err(HttpError::new(400, format!("{name}协议暂未实现").as_str())),
221        }
222        Ok(())
223    }
224    pub fn handle_header(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
225        let headers = String::from_utf8_lossy(data.as_slice());
226        if self.config.debug {
227            info!("\r\n=================请求头 {:?}=================\r\n{headers}\r\n========================================",thread::current().id());
228        }
229        match &self.protocol {
230            Protocol::HTTP1_0 => {
231                for item in headers.lines() {
232                    self.header_line_set(item)?;
233                }
234            }
235            Protocol::HTTP1_1 => {
236                for item in headers.lines() {
237                    self.header_line_set(item)?;
238                }
239                if !self.header.has_key("host") {
240                    return Err(HttpError::new(400, "请求头错误"));
241                }
242            }
243            Protocol::HTTP2 => {
244                return Err(HttpError::new(400, "HTTP2格式错误"));
245            }
246            Protocol::HTTP3 => return Err(HttpError::new(400, "暂时未开放")),
247            Protocol::Other(name) => {
248                return Err(HttpError::new(400, format!("未知协议格式: {}", name).as_str()));
249            }
250        }
251        Ok(())
252    }
253
254    fn header_line_set(&mut self, line: &str) -> Result<(), HttpError> {
255        match line.trim().find(":") {
256            None => return Err(HttpError::new(400, format!("请求头[{line}]错误").as_str())),
257            Some(e) => {
258                let key = line[..e].trim().to_lowercase().clone();
259                let value = line[e + 1..].trim();
260                self.set_header(key.as_str(), value)?;
261            }
262        }
263        Ok(())
264    }
265    pub fn set_header(&mut self, key: &str, value: &str) -> Result<(), HttpError> {
266        self.header[key] = value.into();
267        if value.len() > 8192 {
268            return Err(HttpError::new(400, "header longer than 8192 characters"));
269        }
270        match key {
271            "origin" => self.origin = value.to_string(),
272            "content-type" => {
273                let t = value.split_whitespace().collect::<Vec<&str>>();
274                if !t.is_empty() {
275                    match t[0] {
276                        _ if t[0].contains("multipart/form-data") => {
277                            self.boundary = t[1].trim().trim_start_matches("boundary=").to_string();
278                            self.content_type = ContentType::from("multipart/form-data");
279                        }
280                        _ => {
281                            self.content_type = ContentType::from(t[0].trim_end_matches(";"));
282                        }
283                    }
284                }
285                self.header[key] = self.content_type.str().into();
286            }
287            "content-length" => self.content_length = value.parse::<usize>().unwrap_or(0),
288            "accept-language" => self.accept_language = Language::from(value),
289            "authorization" => self.authorization = Authorization::from(value),
290            "upgrade" => self.upgrade = Upgrade::from(value),
291            "connection" => self.connection = Connection::from(value),
292            "accept-encoding" => self.accept_encoding = Encoding::from(value),
293            "cookie" => {
294                let _ = value.split(';').collect::<Vec<&str>>().iter().map(|&x| {
295                    match x.find('=') {
296                        None => {}
297                        Some(index) => {
298                            let key = x[..index].trim().to_string();
299                            let val = x[index + 1..].trim().to_string();
300                            let _ = self.cookie.insert(key.as_str(), val);
301                        }
302                    }
303                    ""
304                }).collect::<Vec<&str>>();
305            }
306            "x-forwarded-for" => self.proxy_ip = value.to_string(),
307            "x-real-ip" => self.client_ip = value.to_string(),
308            _ => {}
309        }
310
311        Ok(())
312    }
313    pub fn handle_body(&mut self, data: Vec<u8>) -> Result<(), HttpError> {
314        if self.config.debug {
315            info!("\r\n=================请求体 {:?}=================\r\n长度: {}\r\n========================================",thread::current().id(),self.content_length);
316        }
317        if data.len() != self.content_length {
318            return Err(HttpError::new(400, format!("Content-Length mismatch: header={}, actual={}", self.content_length, data.len()).as_str()));
319        }
320        if self.content_length == 0 {
321            return Ok(());
322        }
323        match &self.content_type {
324            ContentType::FormData => {
325                let boundary_marker = format!("--{}", self.boundary);
326                let parts = split_vec_u8(&data, boundary_marker.as_bytes());
327
328                let mut fields = object! {};
329
330                for part in parts {
331                    let (header, body) = match part.windows(b"\r\n\r\n".len()).position(|window| window == b"\r\n\r\n") {
332                        None => continue,
333                        Some(_) => {
334                            let mut re = split_vec_u8(part.as_slice(), "\r\n\r\n".as_bytes());
335                            let header = re[0].clone();
336                            let t = re[1].len() - 2;
337                            let body = re[1].drain(..t).collect::<Vec<u8>>();
338                            (header, body)
339                        }
340                    };
341                    let headers = String::from_utf8_lossy(header.as_slice());
342                    let mut field_name = "";
343                    let mut filename = "";
344                    let mut content_type = ContentType::Other("".to_string());
345
346                    for header in headers.lines() {
347                        if header.to_lowercase().starts_with("content-disposition:") {
348                            match header.find("filename=\"") {
349                                None => {}
350                                Some(filename_start) => {
351                                    let filename_len = filename_start + 10;
352                                    let filename_end = header[filename_len..].find('"').unwrap() + filename_len;
353                                    filename = &header[filename_len..filename_end];
354                                }
355                            }
356                            match header.find("name=\"") {
357                                None => {}
358                                Some(name_start) => {
359                                    let name_start = name_start + 6;
360                                    let name_end = header[name_start..].find('"').unwrap() + name_start;
361                                    field_name = &header[name_start..name_end];
362                                }
363                            }
364                        }
365                        if header.to_lowercase().starts_with("content-type:") {
366                            content_type = ContentType::from(header.to_lowercase().trim_start_matches("content-type:").trim());
367                        }
368                    }
369
370                    if filename.is_empty() {
371                        let text = String::from_utf8_lossy(body.as_slice());
372                        fields[field_name.to_string()] = JsonValue::from(text.into_owned());
373                        continue;
374                    }
375                    let extension = Path::new(filename).extension().and_then(|ext| ext.to_str()); // 转换为 &str
376                    let suffix = extension.unwrap_or("txt");
377                    let filename = if extension.is_none() {
378                        format!("{filename}.txt")
379                    } else {
380                        filename.to_string()
381                    };
382
383                    let mut temp_dir = env::temp_dir();
384                    temp_dir.push(filename.clone());
385                    let Ok(mut temp_file) = fs::File::create(&temp_dir) else { continue };
386                    if temp_file.write(body.as_slice()).is_ok() {
387                        if fields[field_name.to_string()].is_empty() {
388                            fields[field_name.to_string()] = array![];
389                        }
390                        fields[field_name.to_string()].push(object! {
391                                        id:br_crypto::sha256::encrypt_hex(&body.clone()),
392                                        name:filename,
393                                        suffix:suffix,
394                                        size:body.len(),
395                                        type:content_type.str(),
396                                        file:temp_dir.to_str()
397                                    }).unwrap();
398                    }
399                }
400                self.params = fields;
401            }
402            ContentType::FormUrlencoded => {
403                let input = String::from_utf8_lossy(&data);
404                let mut list = object! {};
405                for pair in input.split('&') {
406                    if let Some((key, val)) = pair.split_once('=') {
407                        let key = br_crypto::encoding::urlencoding_decode(key);
408                        let val = br_crypto::encoding::urlencoding_decode(val);
409                        let _ = list.insert(key.as_str(), val);
410                    }
411                }
412                self.params = list;
413            }
414            ContentType::Json => {
415                let text = String::from_utf8_lossy(data.as_slice());
416                self.params = json::parse(text.into_owned().as_str()).unwrap_or(object! {});
417            }
418            ContentType::Xml | ContentType::Html | ContentType::Text | ContentType::Javascript => {
419                let text = String::from_utf8_lossy(data.as_slice());
420                self.params = text.into_owned().into();
421            }
422            ContentType::Other(_) => {}
423            ContentType::Stream => {}
424        }
425        Ok(())
426    }
427    /// 保存日志
428    pub fn save_log(&mut self) -> io::Result<()> {
429        if !self.config.log {
430            return Ok(());
431        }
432        let local: DateTime<Local> = Local::now();
433        let time_dir = local.format("%Y-%m-%d-%H").to_string();
434        let time_dir = time_dir.split('-').collect::<Vec<&str>>();
435
436        let mut res = self.config.root_path.join(self.config.runtime.clone()).join("log");
437        for item in &time_dir {
438            res.push(item);
439        }
440        fs::create_dir_all(res.parent().unwrap())?;
441        let log_file = format!("{}.log", res.to_str().unwrap());
442        let mut file = OpenOptions::new()
443            // 允许写入
444            .append(true) // 追加内容到文件末尾
445            .create(true) // 如果文件不存在,则创建
446            .open(log_file)?;
447        let data = format!(
448            "[{}] {} ClientIP: {} {} {} ContentLength: {} ContentType: {} Time: {:?}\r\n",
449            self.datetime,
450            self.protocol.str(),
451            self.client_ip,
452            self.method.str(),
453            self.uri.url,
454            self.content_length,
455            self.content_type.clone().str(),
456            self.handle_time
457        );
458        file.write_all(data.as_bytes())?;
459        Ok(())
460    }
461}
462
463fn split_vec_u8(data: &[u8], delimiter: &[u8]) -> Vec<Vec<u8>> {
464    let mut parts = Vec::new();
465    let mut start = 0;
466    let mut i = 0;
467
468    while i <= data.len().saturating_sub(delimiter.len()) {
469        if &data[i..i + delimiter.len()] == delimiter {
470            parts.push(data[start..i].to_vec());
471            i += delimiter.len();
472            start = i;
473        } else {
474            i += 1;
475        }
476    }
477    // 剩下的部分
478    if start <= data.len() {
479        parts.push(data[start..].to_vec());
480    }
481    parts
482}
483