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