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#[derive(Clone, Debug)]
17pub struct Request {
18 pub config: Config,
19 pub protocol: Protocol,
21 pub method: Method,
23 pub uri: Uri,
25 pub origin: String,
27 pub header: JsonValue,
29 pub cookie: JsonValue,
31 pub query: JsonValue,
33 pub params: JsonValue,
35 pub authorization: Authorization,
37 pub handle_time: String,
39 pub datetime: String,
41 pub timestamp: i64,
43 pub client_ip: String,
45 pub proxy_ip: String,
47 pub server_ip: String,
49 pub upgrade: Upgrade,
51 pub connection: Connection,
53 pub accept_encoding: Encoding,
55 start_time: Instant,
57 pub body_data: Vec<u8>,
59 content_length: usize,
61 pub content_type: ContentType,
63 boundary: String,
65 pub scheme: Arc<Mutex<Scheme>>,
66 pub accept_language: Language,
68}
69
70
71impl Request {
72 pub fn new(config: Config, scheme: Arc<Mutex<Scheme>>) -> Self {
73
74 let client_ip = scheme.lock().unwrap().client_ip();
76 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 {
113 let header_line = self.scheme.lock().unwrap().read_line()?;
114 self.handle_header_line(header_line.trim())?;
115 }
125
126 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 {
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 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 self.protocol = match version {
191 None => return Err(HttpError::new(400, "协议版本错误")),
192 Some(e) => Protocol::from(e)
193 };
194 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()); 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 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 .append(true) .create(true) .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 if start <= data.len() {
479 parts.push(data[start..].to_vec());
480 }
481 parts
482}
483